news 2026/9/28 21:15:29

LangChain+Python实战:从RAG构建到Agent部署全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain+Python实战:从RAG构建到Agent部署全解析

# LangChain+Python实战:从RAG构建到Agent部署全解析

## 1. 背景:LLM应用从“玩具”到“产品”的鸿沟

2023年以来,以GPT-4、Claude-3为代表的LLM能力惊人,但多数开发者仍停留在“调用API写个聊天框”的阶段。真实场景需要知识库问答、多步骤推理、工具调用——这些恰恰是LangChain (v0.1.12) 等框架试图解决的核心问题。根据2024年LangChain官方报告,78%的生产级LLM应用使用了RAG(检索增强生成)或Agent模式。然而,很多教程只演示了简单的“Prompt+API”调用,导致开发者面对复杂工程时无从下手。

本文基于LangChain 0.1.12、Python 3.12、OpenAI API 1.6.0,从原理到代码,完整演示一个可部署的RAG问答系统与AI Agent,并讨论Streamlit (v1.28.0) 部署注意事项。

## 2. 技术原理:LangChain的三大核心抽象

LangChain的成功在于它将LLM应用开发抽象为三个可组合的层:

- **Models**:统一封装LLM、ChatModel、Embeddings接口。例如 `ChatOpenAI(model="gpt-4-turbo")` 或本地 `Ollama`。

- **Chains**:将多个步骤(Prompt + Model + 输出解析)链接成端到端流程。例如 `LLMChain`、`SequentialChain`。

- **Agents & Tools**:让LLM根据用户需求动态选择工具(搜索、计算、数据库),并循环执行直至完成。

RAG的本质是“先检索后生成”:用户查询 → 向量数据库检索相关文档 → 将文档作为上下文注入Prompt → LLM生成答案。这解决了LLM知识滞后和幻觉问题。

Agent则更进一步:LLM作为推理引擎,决定调用哪个工具、解析结果、决定下一步。例如用户问“今天纽约天气如何?”,Agent先调用天气API获取数据,再格式化回答。

## 3. 实践:构建一个带流式输出的RAG问答系统

### 3.1 环境与版本依赖

```python

# requirements.txt

langchain==0.1.12

langchain-community==0.0.19

langchain-openai==0.0.5

chromadb==0.4.22

openai==1.6.0

streamlit==1.28.0

python-dotenv==1.0.0

```

使用 `dotenv` 加载 `.env` 中的 `OPENAI_API_KEY`。

### 3.2 数据准备:从PDF构建向量库

假设我们有一个公司政策PDF `policy.pdf`。用 `PyPDFLoader` 加载并按段落分割。

```python

from langchain.document_loaders import PyPDFLoader

from langchain.text_splitter import RecursiveCharacterTextSplitter

from langchain.embeddings.openai import OpenAIEmbeddings

from langchain.vectorstores import Chroma

# 加载PDF

loader = PyPDFLoader("policy.pdf")

documents = loader.load()

# 分割:chunk_size=500, chunk_overlap=50

text_splitter = RecursiveCharacterTextSplitter(

chunk_size=500,

chunk_overlap=50,

separators=["\n\n", "\n", "。", ",", " ", ""]

)

docs = text_splitter.split_documents(documents)

# 生成Embedding并存入ChromaDB(持久化)

embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

vectordb = Chroma.from_documents(

documents=docs,

embedding=embeddings,

persist_directory="./chroma_db"

)

vectordb.persist()

print(f"向量库创建完成,包含 {len(docs)} 个文档块")

```

**关键参数**:`chunk_size=500` 是很多生产系统的经验值(约200-1000 tokens),overlap确保上下文不丢失。`text-embedding-ada-002` 是OpenAI性价比最高的嵌入模型,1536维。

### 3.3 构建RAG Chain(含流式输出)

使用LangChain的 `RetrievalQA` 链,并包装为 `Streamlit` 交互窗口。

```python

import streamlit as st

from langchain.chains import RetrievalQA

from langchain.prompts import PromptTemplate

from langchain_openai import ChatOpenAI

# 加载向量库

vectordb = Chroma(persist_directory="./chroma_db", embedding_function=OpenAIEmbeddings())

retriever = vectordb.as_retriever(search_kwargs={"k": 4}) # 检索最相似4块

# 自定义Prompt

prompt_template = """你是公司政策助手。基于以下上下文,用中文回答用户问题。如果上下文无关,请说“我找不到相关信息”。

上下文:{context}

问题:{question}

答案:"""

prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])

# 使用GPT-4-turbo(支持128k上下文)

llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0, streaming=True)

# 构建Chain

qa_chain = RetrievalQA.from_chain_type(

llm=llm,

chain_type="stuff", # 简单拼接所有docs

retriever=retriever,

chain_type_kwargs={"prompt": prompt},

return_source_documents=True # 返回引用来源

)

# Streamlit UI

st.title("📄 公司政策智能助手")

query = st.text_input("请输入问题:")

if query:

with st.spinner("AI思考中..."):

result = qa_chain({"query": query})

# 流式输出(需配合Streamlit的write_stream,此处简化)

st.write(result["result"])

with st.expander("📚 参考文档"):

for doc in result["source_documents"]:

st.markdown(f"- {doc.page_content[:200]}...")

```

**版本兼容说明**:`langchain_openai` 包是0.1.x推荐的方式,避免使用废弃的 `from langchain.llms import OpenAI`。`streaming=True` 配合 `ChatOpenAI` 实现逐token输出,但RetrievalQA自带阻塞模式,生产环境建议用 `CallbackHandler` 实现真正流式。

### 3.4 性能与调优

| 参数 | 说明 | 推荐值 |

|------|------|--------|

| chunk_size | 分割粒度 | 500-1000 |

| k (检索数量) | 传给LLM的文档数 | 3-5 |

| temperature | 生成随机性 | 0(问答场景) |

| model | LLM模型 | gpt-4-turbo / gpt-3.5-turbo-0125 |

实测:在2核4G服务器上,ChromaDB加载约5000个文档块耗时8秒,单次问答(含检索+生成)约3-5秒(gpt-3.5-turbo)。若使用gpt-4-turbo,生成延迟约2倍,但答案质量明显提升。

## 4. 进阶:打造自定义Agent(工具调用)

Agent允许LLM调用外部API。例如让Agent计算员工年假天数(需要调用计算器和日期工具)。

### 4.1 定义工具

```python

from langchain.agents import Tool, AgentExecutor, create_openai_tools_agent

from langchain_openai import ChatOpenAI

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 工具1:计算器(模拟)

def calculate_vacation_days(employee_id: str) -> str:

"""根据员工ID返回可休假天数(模拟数据)"""

data = {"E001": 15, "E002": 10, "E003": 12}

return str(data.get(employee_id, 0))

tools = [

Tool(

name="VacationCalculator",

func=calculate_vacation_days,

description="输入员工ID(如E001),返回年假余额"

)

]

# 初始化LLM

llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)

# 创建Agent(OpenAI Functions风格)

prompt = ChatPromptTemplate.from_messages([

("system", "你是HR助手,使用工具回答员工假期问题。"),

("human", "{input}"),

MessagesPlaceholder(variable_name="agent_scratchpad"),

])

agent = create_openai_tools_agent(llm, tools, prompt)

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 测试

response = agent_executor.invoke({"input": "员工E002还剩下多少天年假?"})

print(response["output"])

```

### 4.2 输出示例

```

> Entering new AgentExecutor chain...

Invoking: `VacationCalculator` with `{'employee_id': 'E002'}`

Responded: 根据查询,员工E002目前剩余年假天数为10天。

```

**原理**:`create_openai_tools_agent` 利用OpenAI的function calling能力,让模型自动决定何时调用工具。LangChain负责解析调用结果并反馈给模型。`agent_scratchpad` 存储中间步骤。

## 5. 部署到生产:Streamlit + 容器化注意事项

素材中提到的“deploy a ChatGPT-like application using Streamlit”需要注意:

- **会话管理**:Streamlit每次交互会重写页面,需用 `st.session_state` 维护对话历史。

- **环境变量**:API Key不应硬编码,使用 `st.secrets` (Streamlit Cloud) 或 docker环境变量。

- **性能**:RAG查询中ChromaDB在容器内持久化需挂载卷(volume),否则重启后丢失。

- **并发**:Streamlit单线程,多用户建议使用Gunicorn + FastAPI包装。LangChain的 `Runnable` 协议支持异步(`ainvoke`),可配合 `asyncio`。

**示例Dockerfile片段**:

```dockerfile

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8501

CMD ["streamlit", "run", "app.py", "--server.port=8501"]

```

## 6. 总结与展望

本文从LangChain v0.1.12的核心抽象出发,通过代码实现了:

1. 基于RAG的企业政策问答系统(含流式输出与来源展示)

2. 调用自定义工具的Agent(员工假期查询)

这些模式可以直接复用到客服、内部知识库、自动化报告等场景。LangChain并非银弹——它封装了复杂度,但开发者仍需理解嵌入模型选择、分块策略、Agent循环终止条件等底层细节。

未来方向:随着GPT-4 Omni、Claude 3.5 Sonnet等模型支持多模态,LangChain即将推出MultiModal Chain;Agent领域正在向“长期记忆”和“多Agent协作”演进。建议关注LangGraph (v0.0.20+) 用于构建有状态的图流程,以及LangSmith用于全链路追踪。

最后,保持工程务实:先用gpt-3.5-turbo跑通MVP,再根据延迟和成本决定是否升级模型。量化、蒸馏、本地部署(如Ollama + Llama3)将是2025年企业落地的另一关键路径。

**参考文献**:

- LangChain Documentation (v0.1.12)

- OpenAI API Reference (2024-01)

- Streamlit Deployment Guide (v1.28.0)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 21:14:38

工业级高精度恒流源设计:从运放方案到LT1166的实战经验分享

恒流源这个东西,说简单也简单,一个运放加一个MOS管就能搭出来;说难也难,要做到高精度、大功率、长期稳定,那坑是一个接一个。最近我在做一个工业级的恒流源项目,要求输出电流0到5A连续可调,精度…

作者头像 李华
网站建设 2026/9/28 21:13:27

原生AI coding agent实战:工具调用、本地部署与多智能体编排

1. 从"能聊"到"能干活":原生 AI coding agent 到底改变了什么大多数人第一次用大模型写代码,体验都差不多:把需求贴进去,它吐出一段代码,你复制到编辑器里,跑一下,报错&…

作者头像 李华
网站建设 2026/9/28 21:09:29

WinForms TextBox水印自绘控件:从Placeholder到防截图

简介:面向Winform开发者的文本框水印实现资源,针对原生TextBox缺少placeholder占位提示的痛点,提供基于自定义控件与重写TextBox类的完整解决方案。资源通过继承System.Windows.Forms.TextBox,重写OnPaint方法并配合GotFocus、Los…

作者头像 李华
网站建设 2026/9/28 21:07:07

版本控制信息泄露:Git / SVN / HG 泄露(CTFHub 题解)

版本控制信息泄露:Git / SVN / HG 泄露(CTFHub 题解) 目录 一、漏洞背景与原理二、通用探测思路三、Git 泄露 —— Stash四、Git 泄露 —— Index五、SVN 泄露六、HG(Mercurial)泄露七、修复与防御建议八、总结 一、…

作者头像 李华
网站建设 2026/9/28 21:06:28

MySQL数据库基础(3):库的操作

&#x1f338;雨落在了我的手上&#xff1a;个人主页 &#x1f41f;个人仓库&#xff1a;Gitee仓库 ❄️个人专栏&#xff1a;<<JaveSe>> <<C语言>> <<C语言数据结构>> <<Java数据结构 >> <<MySQL数据库基础 >>…

作者头像 李华