基于LangChain构建医学文献RAG问答系统
本文介绍了一个基于LangChain和向量数据库的医学文献智能问答系统。系统通过加载医学PDF文献、切分文本、构建向量数据库,实现了RAG(检索增强生成)问答流程。用户提问后,系统从文献库中检索相关内容,并利用GPT-4生成专业回答,同时提供引用来源。文章详细说明了技术实现步骤,包括文档加载与切分、向量数据库构建、问答链创建等核心模块,并提供了进阶优化建议如混合检索、对话记忆等。该系统适用于科研辅
·
🎯 项目目标
用LangChain + 向量数据库搭建一个医学文献智能问答系统,用户输入问题,AI从文献库中检索相关内容并生成专业回答。
核心流程:
用户提问 → 向量检索 → 召回相关文献 → LLM生成答案 → 返回结果+引用
🛠️ 技术栈
pip install langchain openai chromadb pypdf sentence-transformers
| 技术 | 作用 |
|---|---|
| LangChain | RAG框架 |
| ChromaDB | 向量数据库 |
| OpenAI API | GPT-4生成答案 |
| SentenceTransformers | 文本向量化 |
🚀 完整代码实现
步骤1:文献加载与切分
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
步骤2:构建向量数据库
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
步骤3:构建RAG问答链
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")
步骤4:完整使用示例
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")
💡 实际应用场景
场景1:科研辅助
研究人员快速查询文献中的关键信息
场景2:临床决策支持
医生查询疾病治疗方案和药物信息
场景3:医学教育
学生通过问答学习医学知识
🆚 与现有工具对比
如果你需要更专业的医学文献问答,可以参考 suppr超能文献 的深度研究功能:
- ✅ 已接入海量医学文献库
- ✅ 针对医学术语优化的检索
- ✅ 25分钟生成综述报告
当然,自建RAG系统的优势是完全可控和可定制,适合有特定需求的研发团队。
📚 完整代码
GitHub: medical-rag-langchain
包含完整代码、测试数据和部署文档
📝 总结
- 核心技术: LangChain + 向量数据库 + LLM
- 关键步骤: 文档加载 → 向量化 → 检索 → 生成答案
- 优化方向: 混合检索、对话记忆、准确性评估
- 适用场景: 私有知识库问答、领域专家系统
从零搭建只需30分钟,代码可直接运行!
更多推荐
所有评论(0)