如何在LangChain向量检索中确保单篇研究论文独立区分
多研究论文独立对比的LangChain实现方案
核心需求梳理
需要基于LangChain处理多篇研究论文的对比分析,核心要求是每篇论文作为独立来源被全程识别,解决当前代码仅加载单列论文、无来源标识的问题。
分步实现方案
1. 重构DataFrame结构(关键步骤)
原宽表结构不利于批量处理多论文,先转成窄表,让每一行对应一篇独立论文,同时保留所有元数据:
import pandas as pd # 把原宽表转为窄表 df_long = pd.melt( df, id_vars=["id", "subject"], value_vars=["research_paper_text_1", "research_paper_text_2", "research_paper_text_3"], var_name="paper_source", value_name="paper_content" ) # 可选:简化paper_source名称,比如把research_paper_text_1改成Paper 1 df_long["paper_source"] = df_long["paper_source"].str.replace("research_paper_text_", "Paper ")
转换后的数据结构:
| id | subject | paper_source | paper_content |
|---|---|---|---|
| 1 | covid | Paper 1 | 研究论文文本1... |
| 1 | covid | Paper 2 | 研究论文文本2... |
| 1 | covid | Paper 3 | 研究论文文本3... |
| 2 | gut health | Paper 1 | 研究论文文本1... |
2. 加载数据并绑定元数据
使用DataFrameLoader时,指定page_content_column为论文内容列,同时自动携带其他列作为元数据:
from langchain.document_loaders import DataFrameLoader # 加载所有论文,自动把id、subject、paper_source作为元数据绑定到每个文档 loader = DataFrameLoader(df_long, page_content_column="paper_content") documents = loader.load() # 查看示例文档的元数据 print(documents[0].metadata) # 输出:{'id': 1, 'subject': 'covid', 'paper_source': 'Paper 1'}
3. 文本拆分(保留元数据)
文本拆分器会自动保留每个文档块的元数据,确保拆分后的小文本块仍能追溯到原论文:
from langchain.text_splitter import CharacterTextSplitter text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100) # 拆分后每个docs元素都带完整元数据 docs = text_splitter.split_documents(documents)
4. 向量库存储与检索
存储时元数据会和嵌入向量关联,检索时可以按主题过滤(比如只分析covid相关论文),同时返回的结果自带来源信息:
from langchain.vectorstores import Chroma from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings embedding_function = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2") # 存储带元数据的文档块 db = Chroma.from_documents(docs, embedding_function) # 检索时可添加元数据过滤,比如只查covid主题的论文 query = "对比各论文的测试方法差异" retrieved_docs = db.similarity_search( query, k=10, filter={"subject": "covid"} # 可选:按主题过滤 )
5. 构造Prompt让GPT区分来源
把检索到的带元数据的文本块整理成结构化格式,明确标注每个段落的来源,让GPT清晰区分不同论文:
from langchain.chat_models import ChatOpenAI from langchain.prompts import ChatPromptTemplate # 整理检索结果为带来源的文本 context = "" for doc in retrieved_docs: context += f"【来源:{doc.metadata['paper_source']},主题:{doc.metadata['subject']}】\n{doc.page_content}\n\n" # 构造对比分析Prompt prompt = ChatPromptTemplate.from_messages([ ("system", "你是研究论文对比分析专家,需要基于以下标注了来源的论文段落,对比不同论文的测试方法差异,明确指出每个差异对应的论文来源。"), ("user", "论文段落:\n{context}\n\n分析要求:{query}") ]) # 调用ChatGPT分析 llm = ChatOpenAI(temperature=0) chain = prompt | llm response = chain.invoke({"context": context, "query": query}) print(response.content)
关键注意事项
- 元数据要尽可能明确:至少包含论文唯一标识(如Paper 1/2/3)和主题,避免混淆不同id下的同编号论文
- 文本拆分时设置合理的
chunk_overlap,避免关键信息被拆分到两个块中 - 检索时可通过
filter参数缩小范围,减少无关文本干扰分析结果
内容的提问来源于stack exchange,提问作者mikelowry
相关产品推荐
相关产品推荐

