langchain 核心概念与使用笔记

langchain

一、LangChain 是什么?

LangChain 是一个用于构建基于大语言模型(LLM)应用的开发框架。它的核心思想是将 LLM 与外部数据源、工具、记忆等组件“链”式组合,从而构建出更强大的 AI 应用。

一句话概括:Agent = LLM + Memory + Tools + Planning + Action

二、RAG(检索增强生成)

2.1 什么是RAG?为什么需要 RAG?

全称:Retrieval-Augmented Generation 检索增强生成

一句话:先检索私有资料,再交给大模型生成答案,解决 LLM 幻觉、知识过时、无法读取内部文档问题

原生大模型存在三个明显短板:

知识截止:只学到训练数据为止,无法获取最新资讯、企业内部文档

AI 幻觉:没见过的内容容易编造虚假数据、案例、条款

私有数据不可用:不能直接读取公司合同、手册、数据库等内部资料

2.2 RAG 的核心思路

不改动大模型本身,外挂检索系统,实时补充外部事实资料。

2.3 RAG 工作流程
用户提问 → 检索外部文档 → 拼接 Prompt → LLM 生成回答

具体步骤:

  1. 文档加载:将 PDF、网页、数据库等数据源加载进来
  2. 文本切分:把长文档拆分成小段(Chunk),便于检索
  3. 向量化:使用 Embedding 模型将文本段转为向量
  4. 存入向量库:将向量存入 FAISS、Chroma 等向量数据库
  5. 检索匹配:用户提问时,将问题向量化,检索最相关的文档片段
  6. 生成回答:将检索到的内容作为上下文,交给 LLM 生成最终回答
2.4 RAG vs 微调
对比项 RAG 微调(Fine-tuning)
成本 低,无需训练模型 高,需要 GPU 训练
数据时效性 实时更新,改文档即可 需重新训练才能更新
适用场景 知识问答、文档检索 风格调整、专业领域适配
幻觉控制 较好,有检索内容做依据 一般,仍可能产生幻觉

三、核心组件

3.1 Model(模型)

LangChain 支持多种 LLM 接入,统一封装为两类:

LLM:纯文本输入 → 纯文本输出(如 GPT-3.5、GLM-4)

ChatModel:消息列表输入 → 消息输出(如 GPT-4、ChatGLM)

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4", temperature=0)
response = llm.invoke("什么是 LangChain?")
print(response.content)
3.2 Prompt Template(提示词模板)

将变量注入 Prompt,避免硬编码,方便复用。

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的{role}"),
    ("human", "{question}")
])

chain = prompt | llm
response = chain.invoke({"role": "Python工程师", "question": "如何读取JSON文件?"})
3.3 Output Parser(输出解析器)

将 LLM 的非结构化文本输出,解析为结构化数据(如 JSON、列表)。

from langchain_core.output_parsers import StrOutputParser, JsonOutputParser

# 纯文本解析
str_parser = StrOutputParser()

# JSON 解析
json_parser = JsonOutputParser()
3.4 Chain(链)

将多个组件串联成一条处理流水线,是 LangChain 最核心的编排方式。

# LCEL 链式写法
chain = prompt | llm | StrOutputParser()
result = chain.invoke({"role": "助手", "question": "你好"})

LCEL(LangChain Expression Language)使用 | 管道符串联组件,简洁直观。

3.5 Memory(记忆)

让应用具备“记住上下文”的能力,支持多轮对话。

常用记忆类型:

ConversationBufferMemory:保存完整对话历史

ConversationBufferWindowMemory:只保留最近 K 轮对话

ConversationSummaryMemory:用 LLM 对历史对话做摘要,节省 Token

3.6 Tool & Agent(工具与智能体)

Tool 是 Agent 可以调用的外部能力(如搜索引擎、数据库查询、API 调用)。

Agent 是 LLM + Tools 的组合,LLM 自主决定调用哪个工具、传什么参数。

from langchain_core.tools import tool

@tool
def search_web(query: str) -> str:
    """搜索互联网获取最新信息"""
    # 实际实现调用搜索 API
    return f"搜索结果:{query} 的相关信息..."

@tool
def calculator(expression: str) -> str:
    """计算数学表达式"""
    return str(eval(expression))

tools = [search_web, calculator]

Agent 执行流程:

用户输入 → LLM 分析意图 → 选择 Tool → 执行 Tool → 返回结果 → LLM 生成最终回答

四、向量数据库

RAG 场景下,向量数据库是核心基础设施,负责存储和检索文档向量。

常用选择:

FAISS:Meta 开源,本地运行,适合快速验证

Chroma:轻量级,内置嵌入支持,适合开发测试

Milvus:分布式架构,适合大规模生产环境

Pinecone:全托管云服务,免运维

from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_texts(["LangChain 是一个框架", "RAG 用于检索增强"], embeddings)

# 相似度检索
results = vectorstore.similarity_search("什么是 RAG", k=2)

五、Text Splitter(文本切分)

长文档必须切分后才能向量化,切分策略直接影响检索质量。

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,       # 每段最大字符数
    chunk_overlap=50,     # 相邻段重叠字符数,避免语义截断
    separators=["\n\n", "\n", "。", "!", "?", ".", " "]  # 优先按段落→句子→词切分
)

chunks = splitter.split_text(long_text)

切分经验:

chunk_size 一般 300~1000 字符,太小丢失上下文,太大检索不精准

chunk_overlap 设为 chunk_size 的 10%~20%,保证语义连贯

● 优先使用 RecursiveCharacterTextSplitter,它会按语义边界递归切分

六、一个完整的 RAG 示例

import warnings
import os

warnings.filterwarnings("ignore", category=DeprecationWarning)

os.environ["OPENAI_API_KEY"] = os.environ.get("OPENAI_API_KEY", "sk-xxxxxxxxxx")
os.environ["OPENAI_BASE_URL"] = os.environ.get("OPENAI_BASE_URL", "https://api.deepseek.com")
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1"

from langchain_openai import ChatOpenAI
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_community.document_loaders import TextLoader

# 1. 加载文档
loader = TextLoader("knowledge.txt", encoding="utf-8")
docs = loader.load()

# 2. 切分文档
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)

# 3. 向量化并存储
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vectorstore = FAISS.from_documents(chunks, embeddings)

# 4. 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# 5. 构建 RAG 链
llm = ChatOpenAI(model="deepseek-chat", temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", "根据以下上下文回答问题,如果上下文中没有相关信息,请回答'我不知道'。\n\n上下文:{context}"),
    ("human", "{question}")
])

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

chain = (
    {"context": (lambda x: x["question"]) | retriever | format_docs, "question": lambda x: x["question"]}
    | prompt
    | llm
    | StrOutputParser()
)

# 6. 提问
result = chain.invoke({"question": "文档中提到了哪些内容?"})
print(result)

RAG-note.png

七、小结

LangChain 的核心价值在于组件化编排能力

Model:统一接入各种 LLM

Prompt Template:模板化管理提示词

Chain:管道式编排,LCEL 一行搞定

RAG:外挂知识库,解决幻觉和时效性问题

Agent + Tool:让 LLM 自主调用工具,走向真正的智能体

掌握这些核心概念,基本就能覆盖大部分 LLM 应用开发场景了。