全部版块 我的主页
论坛 数据科学与人工智能 人工智能
49 0
2025-11-22

项目目标

构建一个基于 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分钟,所有代码均可直接运行,具备良好的工程实用性。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群