🚀 从零到一:LangChain 完整实战教程
前言
本教程将带你从零开始,使用 LangChain 框架和阿里云百炼平台,构建一个完整的 AI 智能助手,支持:
· 📄 RAG 检索增强生成(基于 PDF/TXT 文档问答)
· 🤖 Agent 智能代理(自动调用工具)
· 🎨 多模态生成(文生图、图生图)
· 💬 对话记忆(多轮对话)
· 🌐 Web 界面(Streamlit)
一、环境搭建
1.1 安装 Python 依赖
bash
# 创建项目目录
mkdir ai_blog_demo
cd ai_blog_demo
# 安装依赖包
pip3 install langchain langchain-openai langchain-community -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install streamlit chromadb pypdf python-dotenv -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install sentence-transformers langchain-chroma -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install openai pillow requests -i https://pypi.tuna.tsinghua.edu.cn/simple
1.2 配置 API Key
创建 .env 文件:
bash
DASHSCOPE_API_KEY="你的阿里云百炼API Key"
DASHSCOPE_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
💡 获取 API Key:访问 阿里云百炼控制台 注册并创建
1.3 准备测试文档
创建 sample.txt:
text
人工智能(AI)是计算机科学的一个分支,致力于创建能够执行通常需要人类智能的任务的系统。
这些任务包括视觉感知、语音识别、决策制定和语言翻译等。
机器学习是人工智能的一个子集,它使系统能够从数据中学习并改进,而无需明确编程。
深度学习是机器学习的一个子集,使用多层神经网络来处理复杂的数据模式。
大语言模型(LLM)如GPT、通义千问等,是基于深度学习技术的模型,能够理解和生成人类语言。
LangChain 是一个用于开发由大语言模型驱动的应用程序的框架。
检索增强生成(RAG)是一种结合信息检索和文本生成的技术,可以让大模型基于外部知识库回答问题,
有效解决大模型知识陈旧和幻觉问题。
二、核心功能实现
2.1 基础 LLM 调用
python
# 01_basic_llm.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
load_dotenv()
llm = ChatOpenAI(
model="qwen3-max",
temperature=0.7,
openai_api_key=os.getenv("DASHSCOPE_API_KEY"),
openai_api_base=os.getenv("DASHSCOPE_BASE_URL"),
)
messages = [
SystemMessage(content="你是一个专业的Python编程助手,回答要简洁。"),
HumanMessage(content="请用一句话介绍什么是装饰器")
]
response = llm.invoke(messages)
print(response.content)
2.2 提示词模板
python
# 02_prompt_template.py
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个{role}专家,回答要{style}。"),
("user", "{question}")
])
chain = prompt | llm | StrOutputParser()
result = chain.invoke({
"role": "Python编程",
"style": "简洁,不超过30字",
"question": "什么是列表推导式?"
})
print(result)
2.3 输出解析器(JSON 格式)
python
# 03_output_parser.py
from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field
class Person(BaseModel):
name: str = Field(description="人物姓名")
age: int = Field(description="人物年龄")
hobby: str = Field(description="人物爱好")
parser = JsonOutputParser(pydantic_object=Person)
prompt = ChatPromptTemplate.from_messages([
("system", "提取信息,按格式输出:{format_instructions}"),
("user", "小明今年18岁,喜欢打篮球")
])
chain = prompt | llm | parser
result = chain.invoke({"format_instructions": parser.get_format_instructions()})
print(f"姓名: {result['name']}, 年龄: {result['age']}, 爱好: {result['hobby']}")
2.4 对话记忆
python
# 04_memory.py
from langchain.memory import ConversationBufferMemory
from langchain.chains import LLMChain
memory = ConversationBufferMemory(return_messages=True)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个友好的AI助手"),
("placeholder", "{history}"),
("human", "{input}")
])
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
chain.invoke({"input": "我叫小明,我喜欢吃披萨"})
response = chain.invoke({"input": "我叫什么名字?我喜欢吃什么?"})
print(response['text'])
2.5 RAG 检索增强生成
python
# 05_rag.py
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_chroma import Chroma
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
# 加载文档
loader = TextLoader("sample.txt", encoding="utf-8")
docs = loader.load()
# 分割文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=50)
chunks = text_splitter.split_documents(docs)
# 向量化
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
vectorstore = Chroma.from_documents(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# RAG 链
system_prompt = "基于以下内容回答问题:{context}"
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "{input}")
])
document_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, document_chain)
response = rag_chain.invoke({"input": "什么是RAG?"})
print(response['answer'])
2.6 Agent 智能代理
python
# 06_agent.py
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain.tools import tool
from datetime import datetime
@tool
def calculator(expression: str) -> str:
"""计算数学表达式"""
try:
return f"结果: {eval(expression)}"
except:
return "计算错误"
@tool
def get_current_time() -> str:
"""获取当前时间"""
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
tools = [calculator, get_current_time]
prompt = ChatPromptTemplate.from_messages([
("system", "你是智能助手,可使用工具:{tools}"),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}")
])
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
response = agent_executor.invoke({"input": "现在几点?计算 123*456"})
print(response['output'])
2.7 多模态(文生图)
python
# 07_multimodal.py
from openai import OpenAI
import requests
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
response = client.images.generate(
model="wanx-v1",
prompt="一只穿着宇航服的橘猫,漂浮在星云中,写实风格",
n=1,
size="1024*1024",
)
image_url = response.data[0].url
print(f"生成的图片: {image_url}")
# 下载保存
img_data = requests.get(image_url).content
with open("generated_image.png", "wb") as f:
f.write(img_data)
print("图片已保存到 generated_image.png")
三、完整的 Streamlit Web 应用
这是本教程的核心,整合了以上所有功能:
python
# app.py - 完整的 Streamlit 应用
import os
import tempfile
import streamlit as st
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.memory import ConversationBufferMemory
from langchain.chains import LLMChain
from langchain_community.document_loaders import TextLoader, PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_chroma import Chroma
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain.tools import tool
from datetime import datetime
from openai import OpenAI
import requests
load_dotenv()
# 页面配置
st.set_page_config(
page_title="AI 智能助手",
page_icon="🤖",
layout="wide"
)
st.title("🤖 AI 智能助手 - LangChain 完整实战")
st.markdown("支持 RAG 文档问答、Agent 智能代理、多模态生图")
# 初始化 session_state
if "messages" not in st.session_state:
st.session_state.messages = []
if "memory" not in st.session_state:
st.session_state.memory = ConversationBufferMemory(return_messages=True)
if "retriever" not in st.session_state:
st.session_state.retriever = None
if "vectorstore" not in st.session_state:
st.session_state.vectorstore = None
# 初始化 LLM
@st.cache_resource
def init_llm():
return ChatOpenAI(
model="qwen3-max",
temperature=0.7,
openai_api_key=os.getenv("DASHSCOPE_API_KEY"),
openai_api_base=os.getenv("DASHSCOPE_BASE_URL"),
)
llm = init_llm()
# 初始化多模态客户端
@st.cache_resource
def init_multimodal_client():
return OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
multimodal_client = init_multimodal_client()
# ========== 侧边栏 ==========
with st.sidebar:
st.header("⚙️ 功能配置")
# 功能选择
mode = st.radio(
"选择模式",
["💬 普通对话", "📚 RAG 文档问答", "🤖 Agent 智能代理", "🎨 文生图"]
)
st.divider()
# RAG 文档上传
if mode == "📚 RAG 文档问答":
st.subheader("📄 上传文档")
uploaded_file = st.file_uploader(
"支持 TXT/PDF",
type=["txt", "pdf"]
)
if uploaded_file and st.button("处理文档"):
with st.spinner("处理中..."):
# 保存临时文件
suffix = f".{uploaded_file.name.split('.')[-1]}"
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
tmp.write(uploaded_file.getvalue())
tmp_path = tmp.name
# 加载文档
if uploaded_file.name.endswith('.txt'):
loader = TextLoader(tmp_path, encoding="utf-8")
else:
loader = PyPDFLoader(tmp_path)
docs = loader.load()
# 分割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=100
)
chunks = text_splitter.split_documents(docs)
# 向量化
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
st.session_state.vectorstore = Chroma.from_documents(chunks, embeddings)
st.session_state.retriever = st.session_state.vectorstore.as_retriever(
search_kwargs={"k": 3}
)
os.unlink(tmp_path)
st.success(f"✅ 已加载 {len(chunks)} 个文档块")
# Agent 工具说明
if mode == "🤖 Agent 智能代理":
st.subheader("🛠️ 可用工具")
st.info("""
- 📅 获取当前时间
- 🧮 数学计算
- 📝 文本长度统计
""")
# 文生图配置
if mode == "🎨 文生图":
st.subheader("🎨 生成配置")
img_size = st.selectbox("图片尺寸", ["1024*1024", "768*1024", "1024*768"])
img_style = st.selectbox("风格", ["<auto>", "写实", "插画", "水墨"])
# 清空对话
if st.button("🗑️ 清空对话"):
st.session_state.messages = []
st.session_state.memory.clear()
st.rerun()
# ========== 主界面 ==========
st.header("💬 对话")
# 显示历史消息
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# ========== 模式处理函数 ==========
def normal_chat(prompt: str) -> str:
"""普通对话模式"""
chain = LLMChain(llm=llm, prompt=ChatPromptTemplate.from_messages([
("system", "你是友好的AI助手"),
("placeholder", "{history}"),
("human", "{input}")
]), memory=st.session_state.memory)
response = chain.invoke({"input": prompt})
return response['text']
def rag_chat(prompt: str) -> str:
"""RAG 文档问答模式"""
if not st.session_state.retriever:
return "⚠️ 请先在侧边栏上传文档"
system_prompt = "基于以下文档内容回答问题,如果文档中没有相关信息,请明确说明:\n{context}"
chat_prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "{input}")
])
document_chain = create_stuff_documents_chain(llm, chat_prompt)
rag_chain = create_retrieval_chain(st.session_state.retriever, document_chain)
response = rag_chain.invoke({"input": prompt})
return response['answer']
def agent_chat(prompt: str) -> str:
"""Agent 智能代理模式"""
@tool
def get_time() -> str:
"""获取当前时间"""
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@tool
def calculate(expr: str) -> str:
"""计算数学表达式"""
try:
return str(eval(expr))
except:
return "计算错误"
@tool
def text_len(text: str) -> str:
"""计算文本长度"""
return str(len(text))
tools = [get_time, calculate, text_len]
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是智能助手,可使用工具"),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}")
])
agent = create_tool_calling_agent(llm, tools, prompt_template)
executor = AgentExecutor(agent=agent, tools=tools, verbose=False)
response = executor.invoke({"input": prompt})
return response['output']
def image_gen(prompt: str) -> str:
"""文生图模式"""
try:
response = multimodal_client.images.generate(
model="wanx-v1",
prompt=prompt,
n=1,
size=img_size,
parameters={"style": img_style}
)
image_url = response.data[0].url
# 下载并显示
img_data = requests.get(image_url).content
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"generated_{timestamp}.png"
with open(filename, "wb") as f:
f.write(img_data)
# 在聊天中显示图片
st.image(image_url, caption=f"生成: {prompt[:50]}...")
return f"✅ 图片已生成!\n\n"
except Exception as e:
return f"❌ 生成失败: {str(e)}"
# ========== 输入处理 ==========
user_input = st.chat_input("输入你的问题...")
if user_input:
# 添加用户消息
st.session_state.messages.append({"role": "user", "content": user_input})
with st.chat_message("user"):
st.markdown(user_input)
# 生成回复
with st.chat_message("assistant"):
with st.spinner("思考中..."):
if mode == "💬 普通对话":
response = normal_chat(user_input)
elif mode == "📚 RAG 文档问答":
response = rag_chat(user_input)
elif mode == "🤖 Agent 智能代理":
response = agent_chat(user_input)
elif mode == "🎨 文生图":
response = image_gen(user_input)
else:
response = normal_chat(user_input)
st.markdown(response)
# 添加助手消息
st.session_state.messages.append({"role": "assistant", "content": response})
# ========== 页脚 ==========
st.divider()
st.caption("💡 使用说明:")
st.caption("1. 选择模式:普通对话 / RAG文档问答 / Agent代理 / 文生图")
st.caption("2. RAG模式需先在侧边栏上传文档并点击「处理文档」")
st.caption("3. Agent模式支持:时间查询、数学计算、文本统计")
四、运行与部署
4.1 本地运行
bash
# 确保所有文件在同一目录
ls -la
# 应包含:.env, sample.txt, app.py
# 启动 Streamlit
streamlit run app.py
4.2 项目文件结构
ai_blog_demo/
├── .env # API Key 配置
├── sample.txt # 测试文档
├── app.py # 主应用(Streamlit)
├── 01_basic_llm.py # 基础调用
├── 02_prompt_template.py
├── 03_output_parser.py
├── 04_memory.py
├── 05_rag.py
├── 06_agent.py
├── 07_multimodal.py
└── generated_images/ # 生成的图片(自动创建)
4.3 部署到云端
bash
# 安装依赖
pip3 install streamlit
# 后台运行(Linux 服务器)
nohup streamlit run app.py --server.port 8501 --server.address 0.0.0.0 > streamlit.log 2>&1 &
五、总结
通过本教程,你学会了:
功能 状态
✅ LangChain 环境搭建 完成
✅ 基础 LLM 调用 完成
✅ 提示词模板 完成
✅ 输出解析器(JSON) 完成
✅ 对话记忆 完成
✅ RAG 检索增强生成 完成
✅ Agent 智能代理 完成
✅ 多模态文生图 完成
✅ Streamlit Web 界面 完成