项目目标
构建一个基于 LangChain 与向量数据库的医学文献智能问答系统。用户提出问题后,系统能够从医学文献库中自动检索相关信息,并由大模型生成专业、准确的回答。
核心流程
整个系统的运行逻辑如下:
用户提问 → 向量检索 → 召回相关文献 → LLM生成答案 → 返回结果+引用
技术架构
| 技术 | 功能说明 |
|---|---|
| LangChain | 作为RAG(检索增强生成)的核心框架 |
| ChromaDB | 用作本地向量数据库,存储文献的嵌入表示 |
| OpenAI API | 调用GPT-4模型进行自然语言回答生成 |
| SentenceTransformers | 将文本转换为高维向量,用于语义检索 |
pip install langchain openai chromadb pypdf sentence-transformers
实现步骤详解
第一步:文献数据加载与分段处理
从原始医学文献中读取内容,使用文本分割器将其切分为语义完整的片段,便于后续索引和检索。
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
import os
def load_medical_papers(pdf_folder: str):
"""
加载医学文献PDF文件
Args:
pdf_folder: PDF文件夹路径
Returns:
文档片段列表
"""
documents = []
# 遍历文件夹中的所有PDF
for filename in os.listdir(pdf_folder):
if filename.endswith('.pdf'):
pdf_path = os.path.join(pdf_folder, filename)
print(f"???? 加载文献: {filename}")
# 加载PDF
loader = PyPDFLoader(pdf_path)
pages = loader.load()
documents.extend(pages)
print(f"? 共加载 {len(documents)} 页文献")
# 切分文档(避免单个片段过长)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # 每个片段1000字符
chunk_overlap=200, # 片段间重叠200字符
length_function=len
)
splits = text_splitter.split_documents(documents)
print(f"? 切分为 {len(splits)} 个片段")
return splits
第二步:创建向量数据库
利用 SentenceTransformers 对切分后的文本进行向量化编码,并将结果存入 ChromaDB,形成可高效检索的知识库。
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
def create_vector_db(documents, persist_directory="./chroma_db"):
"""
创建向量数据库
Args:
documents: 文档片段列表
persist_directory: 数据库持久化路径
Returns:
向量数据库对象
"""
print("???? 生成文本向量...")
# 使用开源embedding模型(也可用OpenAI Embeddings)
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2"
)
# 创建向量数据库
vectordb = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory=persist_directory
)
# 持久化到磁盘
vectordb.persist()
print(f"? 向量数据库已保存至 {persist_directory}")
return vectordb
# 也可以加载已有数据库
def load_vector_db(persist_directory="./chroma_db"):
"""加载已有向量数据库"""
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2"
)
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=embeddings
)
return vectordb
第三步:集成RAG问答链路
通过 LangChain 构建完整的检索-生成流程:接收问题 → 在向量库中查找相似文献片段 → 将上下文传递给 GPT-4 → 输出结构化答案。
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
def create_qa_chain(vectordb, openai_api_key: str):
"""
创建问答链
Args:
vectordb: 向量数据库
openai_api_key: OpenAI API密钥
Returns:
问答链对象
"""
# 初始化LLM
llm = ChatOpenAI(
model_name="gpt-4",
temperature=0.2, # 降低随机性,提高准确度
openai_api_key=openai_api_key
)
# 自定义Prompt模板
prompt_template = """你是一位专业的医学AI助手。请基于以下医学文献内容回答问题。
文献内容:
{context}
问题:{question}
要求:
1. 回答必须基于提供的文献内容
2. 如果文献中没有相关信息,明确说明
3. 提供具体的引用来源
4. 使用专业但易懂的语言
回答:"""
PROMPT = PromptTemplate(
template=prompt_template,
input_variables=["context", "question"]
)
# 创建检索器(返回top-4相关文档)
retriever = vectordb.as_retriever(
search_type="similarity",
search_kwargs={"k": 4}
)
# 构建RAG链
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=True, # 返回引用文档
chain_type_kwargs={"prompt": PROMPT}
)
return qa_chain
def ask_question(qa_chain, question: str):
"""
提问并获取答案
Args:
qa_chain: 问答链
question: 用户问题
"""
print(f"\n? 问题: {question}")
print("???? 检索相关文献...")
# 执行问答
result = qa_chain({"query": question})
# 输出答案
print(f"\n???? 答案:\n{result['result']}")
# 输出引用来源
print(f"\n???? 参考文献:")
for i, doc in enumerate(result['source_documents'], 1):
source = doc.metadata.get('source', 'Unknown')
page = doc.metadata.get('page', 'N/A')
print(f"{i}. {source} (第{page}页)")
print(f" 内容摘要: {doc.page_content[:100]}...\n")
第四步:实际调用示例
演示如何在真实场景中调用该系统,输入具体医学问题并获取由AI生成的专业回复。
def main():
"""主函数:完整工作流"""
# 配置OpenAI API密钥
OPENAI_API_KEY = "sk-your-openai-api-key"
# === 第一次运行:构建向量数据库 ===
print("=== 步骤1: 加载文献 ===")
documents = load_medical_papers("./medical_papers")
print("\n=== 步骤2: 构建向量数据库 ===")
vectordb = create_vector_db(documents)
# === 后续运行:直接加载数据库 ===
# vectordb = load_vector_db()
# === 步骤3: 创建问答系统 ===
print("\n=== 步骤3: 初始化问答系统 ===")
qa_chain = create_qa_chain(vectordb, OPENAI_API_KEY)
# === 步骤4: 开始提问 ===
print("\n=== 步骤4: 医学文献问答 ===")
# 示例问题1
ask_question(qa_chain, "糖尿病的主要治疗方法有哪些?")
# 示例问题2
ask_question(qa_chain, "二甲双胍的作用机制是什么?")
# 示例问题3
ask_question(qa_chain, "1型糖尿病和2型糖尿病的区别?")
if __name__ == "__main__":
main()
运行效果展示
系统在多个测试案例中表现良好,能精准定位相关文献内容并生成符合医学规范的答案。
$ python medical_rag.py
=== 步骤1: 加载文献 ===
???? 加载文献: diabetes_treatment.pdf
???? 加载文献: metformin_mechanism.pdf
? 共加载 45 页文献
? 切分为 128 个片段
=== 步骤2: 构建向量数据库 ===
???? 生成文本向量...
? 向量数据库已保存至 ./chroma_db
=== 步骤3: 初始化问答系统 ===
=== 步骤4: 医学文献问答 ===
? 问题: 糖尿病的主要治疗方法有哪些?
???? 检索相关文献...
???? 答案:
根据文献内容,糖尿病的主要治疗方法包括:
1. **药物治疗**:
- 二甲双胍作为一线用药
- 胰岛素治疗(适用于1型和部分2型患者)
- SGLT-2抑制剂
2. **生活方式干预**:
- 饮食控制:低糖低脂饮食
- 规律运动:每周150分钟中等强度运动
3. **血糖监测**:定期监测血糖水平,调整治疗方案
???? 参考文献:
1. diabetes_treatment.pdf (第3页)
内容摘要: Treatment of diabetes includes pharmacological and lifestyle interventions...
2. diabetes_treatment.pdf (第12页)
内容摘要: Metformin is recommended as first-line therapy...
进阶优化策略
1. 引入混合检索机制
结合关键词匹配与语义向量检索,提升召回率与准确性。
from langchain.retrievers import EnsembleRetriever
from langchain.retrievers import BM25Retriever
# 结合向量检索和关键词检索
vector_retriever = vectordb.as_retriever(search_kwargs={"k": 4})
bm25_retriever = BM25Retriever.from_documents(documents)
ensemble_retriever = EnsembleRetriever(
retrievers=[vector_retriever, bm25_retriever],
weights=[0.7, 0.3] # 向量检索权重更高
)
2. 增加对话记忆功能
支持多轮交互,使系统能理解上下文,提供连贯问答体验。
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True
)
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=retriever,
memory=memory
)
3. 检索质量评估模块
引入评估指标对检索结果的相关性进行打分,持续优化检索性能。
def evaluate_retrieval(vectordb, test_questions):
"""评估检索准确率"""
retriever = vectordb.as_retriever(search_kwargs={"k": 4})
for q in test_questions:
docs = retriever.get_relevant_documents(q)
print(f"问题: {q}")
print(f"召回文档数: {len(docs)}")
print(f"相关性得分: {docs[0].metadata.get('score', 'N/A')}\n")
典型应用领域
科研辅助
帮助研究人员快速获取特定主题下的研究进展、实验数据或结论摘要。
临床决策支持
为医生提供疾病诊疗指南、药物相互作用及最新治疗方案的即时查询服务。
医学教育学习
学生可通过自然语言提问方式掌握复杂医学知识点,提高学习效率。
系统优势总结
相较于通用问答工具,本系统具备以下特点:
- 专为医学领域设计,支持专业术语理解
- 基于私有文献库构建,保障数据安全与可控性
- 高度可定制,适用于不同规模的研发团队
完整代码资源
项目已开源,包含全部实现代码、测试样本及部署说明文档。
GitHub 仓库地址:medical-rag-langchain
总结归纳
核心技术组合:LangChain + 向量数据库 + 大语言模型
关键实施步骤:文档加载 → 文本切分 → 向量化存储 → 相似性检索 → 答案生成
未来优化方向:混合检索策略、对话状态管理、检索效果评估体系
适用业务场景:私有知识库问答系统、垂直领域专家助手
从零开始搭建整套系统仅需约30分钟,所有代码均可直接运行,具备良好的工程实用性。


雷达卡


京公网安备 11010802022788号







