基于向量数据库与LLM的金融知识库问答系统实战
2026/7/25 4:23:45 网站建设 项目流程

1. 项目背景与核心价值

去年在做一个金融知识库项目时,我深刻体会到传统关键词检索的局限性——当用户问"美联储加息对科技股的影响"时,系统只能返回含有关键词"美联储"、"科技股"的文档,而无法理解问题语义。这正是向量数据库结合大语言模型的用武之地。

这个实战项目将带您构建一个能真正理解PDF文档内容的问答系统。其核心突破在于:

  • 语义理解:通过嵌入模型将文本转化为向量,捕获"加息→货币政策→股市波动"等深层关联
  • 精准召回:用向量相似度匹配替代关键词匹配,找到真正相关的文档片段
  • 可信回答:基于检索到的上下文生成回答,避免大模型幻觉

2. 技术架构解析

2.1 系统组成模块

graph TD A[PDF上传] --> B[文本提取] B --> C[文本分块] C --> D[向量嵌入] D --> E[向量存储] F[用户提问] --> G[问题向量化] G --> H[向量检索] H --> I[上下文组装] I --> J[LLM生成回答]

2.2 关键技术选型

2.2.1 向量数据库对比
数据库写入速度查询性能内存占用适合场景
Chroma★★★★★★★★★快速原型开发
Milvus★★★★★★★★★★★★生产级海量数据
Pinecone★★★★★★★★★★★全托管云服务
Weaviate★★★★★★★★★★★多模态检索

实战建议:初期推荐Chroma(轻量易用),生产环境建议Milvus集群版

2.2.2 嵌入模型选择
  • 通用领域:text-embedding-ada-002(OpenAI)
  • 中文优化:m3e-base(中文语义匹配冠军模型)
  • 领域专用:在特定领域数据上微调BERT

3. 完整实现流程

3.1 环境准备

# 推荐使用Python 3.10+ conda create -n pdfqa python=3.10 conda activate pdfqa # 核心依赖 pip install langchain==0.0.340 pip install chromadb==0.4.15 pip install pypdf==3.17.0 pip install openai==0.28.0

3.2 PDF处理流水线

3.2.1 文本提取优化
from pypdf import PdfReader def extract_text_with_metadata(pdf_path): reader = PdfReader(pdf_path) meta = reader.metadata text = "" for page in reader.pages: # 保留页码信息便于溯源 text += f"【Page {page.page_number}】{page.extract_text()}\n\n" return { "text": text, "source": pdf_path, "title": meta.title or os.path.basename(pdf_path) }
3.2.2 智能分块策略
from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, # 适合问答的片段长度 chunk_overlap=50, # 避免关键信息被切断 length_function=len, add_start_index=True # 记录块在原文中的位置 )

3.3 向量化与存储

3.3.1 嵌入处理
from langchain.embeddings import OpenAIEmbeddings embeddings = OpenAIEmbeddings( model="text-embedding-ada-002", deployment="your-deployment-name" # Azure专用参数 )
3.3.2 ChromaDB集成
from langchain.vectorstores import Chroma vector_db = Chroma.from_documents( documents=split_docs, embedding=embeddings, persist_directory="./chroma_db" ) # 持久化到磁盘 vector_db.persist()

3.4 问答链实现

3.4.1 检索增强生成
from langchain.chains import RetrievalQA from langchain.chat_models import ChatOpenAI qa_chain = RetrievalQA.from_chain_type( llm=ChatOpenAI(temperature=0), chain_type="stuff", retriever=vector_db.as_retriever( search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.7, "k": 3} ), return_source_documents=True )
3.4.2 结果后处理
def format_response(result): answer = result["result"] sources = {doc.metadata["source"] for doc in result["source_documents"]} return f"{answer}\n\n参考资料:{', '.join(sources)}"

4. 生产级优化技巧

4.1 性能提升方案

  1. 批量处理优化

    # 启用并行嵌入 embeddings = OpenAIEmbeddings(request_timeout=60, max_retries=5)
  2. 缓存机制

    from langchain.cache import SQLiteCache import langchain langchain.llm_cache = SQLiteCache(database_path=".langchain.db")

4.2 效果增强策略

  1. 查询扩展

    from langchain.retrievers import ContextualCompressionRetriever from langchain.retrievers.document_compressors import LLMChainExtractor compressor = LLMChainExtractor.from_llm(ChatOpenAI()) compression_retriever = ContextualCompressionRetriever( base_compressor=compressor, base_retriever=vector_db.as_retriever() )
  2. 混合检索

    from langchain.retrievers import BM25Retriever, EnsembleRetriever bm25_retriever = BM25Retriever.from_documents(docs) ensemble_retriever = EnsembleRetriever( retrievers=[vector_db.as_retriever(), bm25_retriever], weights=[0.7, 0.3] )

5. 常见问题排查

5.1 典型错误与解决方案

问题现象可能原因解决方案
返回无关内容嵌入模型不匹配更换为领域专用模型
回答存在幻觉检索阈值过低调整score_threshold≥0.7
处理速度慢未启用批量处理配置batch_size=32
中文效果差使用英文嵌入模型切换为m3e-base中文模型

5.2 监控指标建议

  1. 检索质量

    • 命中率(检索结果中有用文档比例)
    • 平均相似度得分
  2. 生成质量

    • 人工评估分数(1-5分制)
    • 幻觉出现频率
# 自动化评估示例 def evaluate_retrieval(query, ideal_docs): retrieved = retriever.get_relevant_documents(query) overlap = set(ideal_docs) & set(retrieved) return len(overlap)/len(ideal_docs)

6. 进阶扩展方向

  1. 多模态支持

    • 提取PDF中的表格数据(使用camelot或tabula)
    • 处理扫描件(OCR+版面分析)
  2. 对话记忆

    from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory( memory_key="chat_history", return_messages=True )
  3. 权限控制

    • 基于元数据过滤(部门/密级)
    retriever = vector_db.as_retriever( filter={"department": "finance"} )

这个项目最让我惊喜的是,当我们将200份金融研究报告入库后,系统能准确回答"对比过去三次美联储加息周期中纳斯达克指数的表现差异"这类复杂问题。关键在于分块时保持上下文完整(如将整份报告的执行摘要作为单独块),以及调整相似度阈值到0.75左右平衡查全率与准确率。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询