乐于分享
好东西不私藏

LangChain实战-文档问答系统

LangChain实战-文档问答系统

当模型开始遗忘世界,我们用文档喂养它。当知识不再写在脑海,而是沉入向量空间,你写的,不再是代码,而是一条通往“理解”的路径。


什么是文档问答系统?

让模型基于你的私有数据回答问题,而不是“胡说八道”。

核心架构(RAG):

用户问题   ↓向量检索(找到相关文档)   ↓拼接上下文   ↓LLM生成答案

                ┌──────────────┐                │   Web 前端    │                │ Chat + 上传   │                └──────┬───────┘                       ↓                ┌──────────────┐                │   FastAPI     │                │   接口层       │                └──────┬───────┘                       ↓        ┌────────────────────────────┐        │         RAG核心层           │        │                            │        │  Loader → Splitter → Embedding │        │            ↓                │        │      Vector DB(Milvus)     │        │            ↓                │        │        Retriever            │        │            ↓                │        │           Qwen              │        └────────────────────────────┘

整体流程拆解

我们今天做的,不是调用 API,而是完整构建:

文档处理与加载(Document Loader)

索引构建(Embedding + Vector Store)

检索与问答(Retriever + QA Chain)


文档加载

文档,是一切的起点。

from langchain.document_loaders import TextLoaderloader = TextLoader("data.txt", encoding="utf-8")docs = loader.load()

本质理解

这里做了两件事:

  • • 把文本 → LangChain Document对象
  • • 为后续处理统一格式

你可以加载:

txt / pdf / docx / html / 网页 / 数据库

文本切分

为什么要切?

因为模型吃不下整本书。

from langchain.text_splitter import RecursiveCharacterTextSplittersplitter = RecursiveCharacterTextSplitter(    chunk_size=500,    chunk_overlap=50)split_docs = splitter.split_documents(docs)

设计哲学

  • • chunk_size:信息密度
  • • overlap:上下文连续性

切分,不是切文本,是在切“语义”。


构建向量索引

让文本变成“可以被搜索的空间”。

from langchain.embeddings import HuggingFaceEmbeddingsembedding = HuggingFaceEmbeddings(    model_name="BAAI/bge-small-zh")

Embedding 本质

它不是翻译,而是:

把“意义”压缩成向量坐标


向量数据库

from langchain.vectorstores import FAISSdb = FAISS.from_documents(split_docs, embedding)

本质理解

你不是在存文本,而是在构建:

一个“语义空间”

问题进来 → 找最近的点 → 返回相关文档


检索 + 问答

from langchain.chains import RetrievalQAfrom langchain.llms import OpenAIqa = RetrievalQA.from_chain_type(    llm=OpenAI(),    retriever=db.as_retriever())

真正发生的事情

用户问:LangChain是什么?        ↓Embedding → 向量        ↓相似度搜索        ↓找出最相关3段文本        ↓拼接 Prompt        ↓LLM回答

完整最小可运行代码

from langchain.document_loaders import TextLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.vectorstores import FAISSfrom langchain.embeddings import HuggingFaceEmbeddingsfrom langchain.chains import RetrievalQAfrom langchain.llms import OpenAI# 1. 加载文档loader = TextLoader("data.txt", encoding="utf-8")docs = loader.load()# 2. 切分splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)split_docs = splitter.split_documents(docs)# 3. 向量化embedding = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh")# 4. 构建向量库db = FAISS.from_documents(split_docs, embedding)# 5. 构建问答系统qa = RetrievalQA.from_chain_type(    llm=OpenAI(),    retriever=db.as_retriever())# 6. 运行whileTrue:    q = input("问:")print(qa.run(q))

项目下载

我已经帮你打包好一个最小工程

https://github.com/wujianyouhun/demo-for-blog/tree/master/python/LangChain/geo_rag_agent