上一篇:速通 AI(五):现代大模型架构——LLaMA 系列 — RMSNorm、RoPE、SwiGLU、KV Cache、GQA
目标:掌握 LLM 应用开发的核心技能——提示词工程、LangChain 框架、OpenAI API 调用,能够独立开发 AI 应用。
前置要求:上一篇(LLaMA 架构理解、Transformer 基础)
本阶段知识依赖图
flowchart TD
A["LLaMA 架构(上一篇)"]
A --> C["提示词工程(高效使用大模型)"]
C -->|输出格式、指令设计| C1[基础技巧]
C -->|CoT、ToT、Few-shot| C2[高级技巧]
C -->|Temperature、Top-P| C3[参数调优]
A --> D["LangChain框架(应用开发框架)"]
D -->|统一接口| D1[LLM调用]
D -->|结构化提示| D2[提示模板]
D -->|组合多个组件| D3["链(Chain)"]
D -->|文档加载与向量| D4[文档处理]
D -->|检索增强生成| D5[RAG链入门]
D -->|自主决策| D6[Agent入门]
A --> F["OpenAI API(模型调用接口)"]
F -->|文本向量化| F1[Embedding]
F -->|对话接口| F2[Chat Completion]
1. 提示词工程——高效使用大模型
为什么提示词工程重要?
类比:和外国人交流
- 你说:“帮我写个东西”
- 外国人(大模型):写什么?写给谁?什么风格?多长?
- 输出:一段泛泛而谈的文字
- 你说:“你是一位资深电商文案专家。请为一款售价 299 元的蓝牙耳机写一段小红书种草文案。要求:标题吸引眼球,突出降噪功能,使用 emoji , 200 字以内。”
- 外国人(大模型):明白了!
- 输出:一篇精准、专业的文案
提示词工程 = 学会如何清晰、精确地表达你的需求。
基础技巧
结构化提示词的四要素
- 角色(Role):告诉模型“你是谁”
- 设定专业背景,让模型调用相关知识
- 例:“你是一位有 10 年经验的 Python 高级工程师”
- 任务(Task):告诉模型“做什么”
- 明确、具体的任务描述
- 例:“请帮我写一个 FastAPI 接口,实现用户登录功能”
- 格式(Format):告诉模型“怎么输出”
- 指定输出的格式和结构
- 例:“输出为完整的 Python 代码,包含注释和错误处理”
- 约束(Constraint):告诉模型“边界在哪”
- 限制条件、质量要求
- 例:“使用异步函数,返回 JSON 格式,包含 token 过期时间”
四要素的组合效果:
- 只有任务:“帮我写个 API” → 输出不确定
- 任务 + 格式:“帮我写个 API ,输出 Python 代码” → 稍好
- 任务 + 格式 + 约束:“帮我写个 FastAPI 用户登录 API ,用 Python 代码输出,包含 JWT 认证” → 更好
- 全部四个:“你是一位 Python 高级工程师。请帮我写一个 FastAPI 用户登录接口。输出完整的 Python 代码,包含注释。要求:使用异步函数,实现 JWT 认证,添加输入验证和错误处理,返回标准 JSON 响应。” → 最好
提示词工程的代价:长 prompt 消耗更多 token(增加 API 费用和延迟);prompt injection 安全风险(恶意用户在输入中嵌入指令覆盖系统提示);过度依赖 prompt 工程可能掩盖模型本身的能力不足。
高级技巧
零样本思维链(Zero-shot CoT)——激活推理能力
- 普通提示:“小明有 5 个苹果,给了小红 2 个,又买了 3 个,现在有几个?”
- 模型可能直接猜“6”(可能错)
- 加一句“让我们一步一步思考”:
- “小明有 5 个苹果,给了小红 2 个,又买了 3 个,现在有几个?让我们一步一步思考。”
- 模型会展示中间步骤:
- 小明开始有 5 个苹果
- 给了小红 2 个,剩下 5-2=3 个
- 又买了 3 个,变成 3+3=6 个
- 答案: 6 个
为什么加一句话就能提升准确率?
- “让我们一步一步思考”激活了模型的“慢思考”模式
- 模型被迫展示中间步骤,减少了“跳步”导致的错误
- 类似于人类“打草稿”比“心算”更准确
少样本提示(Few-shot)——用示例教会模型
- 零样本(Zero-shot):直接让模型做任务
- “请判断情感:这家餐厅很好吃 → ?”
- 模型可能理解你要什么,也可能不理解
- 少样本(Few-shot):给几个示例,让模型学会模式
- “请判断以下评论的情感:
- 评论:这家餐厅太好吃! → 正面
- 评论:服务态度很差 → 负面
- 评论:菜品种类丰富 → 正面
- 评论:等了一个小时才上菜 → ?”
- 模型学会了“判断情感”的模式,准确率大幅提升
- “请判断以下评论的情感:
关键:示例的质量和多样性很重要
- 至少 2-3 个正例和 2-3 个反例
- 示例要覆盖典型情况
- 示例的格式要和目标任务一致
思维树(Tree of Thought)——多路径推理
思维链(CoT):一条推理路径(线性)
- A → B → C → D → 答案
- 问题:如果 B 错了,后面全错
思维树(ToT):多条推理路径(树状)
graph TD
A[问题] --> B1[路径 1]
A --> B2[路径 2]
A --> B3[路径 3]
B1 --> C1[答案 1]
B2 --> C2[答案 2]
B3 --> C3[答案 3]
适用场景:需要多步推理的复杂问题(数学证明、策略规划、代码调试)。
参数调优——调参的艺术
- Temperature(温度)
- 0.0 → 完全确定性,每次输出相同(适合代码、数学)
- 0.3 → 高度确定性,偶尔有小变化(适合翻译、摘要)
- 0.7 → 平衡模式(适合对话、写作)
- 1.0 → 高随机性(适合创意、头脑风暴)
- Top-P(核采样)
- 0.1 → 只从最可能的几个词中选(极度保守)
- 0.9 → 从累积概率 90% 的词中选(推荐默认值)
- 1.0 → 从所有词中选(最多样)
- Frequency Penalty(频率惩罚)
- 0.0 → 不惩罚重复(默认)
- 0.5 → 轻微减少重复
- 1.0 → 强烈避免重复(适合长文本生成)
- Presence Penalty(存在惩罚)
- 0.0 → 不鼓励新话题(默认)
- 0.5 → 轻微鼓励新话题
- 1.0 → 强烈鼓励新话题(适合头脑风暴)
提示词参数调优速查表
| 场景 | Temperature | Top-P | Frequency Penalty | 说明 |
|---|---|---|---|---|
| 代码生成 | 0.0 | 1.0 | 0.0 | 确定性输出,一行解 |
| 翻译/摘要 | 0.3 | 0.9 | 0.0 | 高准确性,少量变化 |
| 一般对话 | 0.7 | 0.9 | 0.0 | 平衡质量和多样性 |
| 创意写作 | 1.0 | 0.95 | 0.5 | 高多样性,避免重复 |
| 头脑风暴 | 1.0 | 1.0 | 1.0 | 最大随机性,鼓励新话题 |
模块小结:提示词工程
| 你学到了什么 | 为什么重要 |
|---|---|
| 结构化提示词四要素 | 角色+任务+格式+约束 |
| Zero-shot CoT | 激活推理能力 |
| Few-shot 提示 | 用示例教会模型 |
| Tree of Thought | 多路径推理 |
| Temperature/Top-P 参数 | 控制生成风格 |
2. LangChain 框架——AI 应用开发的标准工具
LangChain 是什么?
类比: Spring Boot 之于 Java Web 开发, LangChain 之于 LLM 应用开发
没有 LangChain 时,开发一个 RAG 应用需要:
- 手动调用 OpenAI API
- 手动加载和切分文档
- 手动实现向量搜索
- 手动组装提示词
- 手动处理输出解析
- 手动管理对话历史
→ 每个项目都要重复造轮子。
有了 LangChain :
- 统一的 LLM 调用接口(支持 OpenAI 、本地模型、各种 API)
- 内置的文档加载和切分工具
- 内置的向量存储和检索
- 标准化的提示模板
- 自动化的输出解析
- 内置的记忆管理
→ 专注于业务逻辑,不用重复造轮子。
核心组件 1 : LLM 调用——统一接口
from langchain_openai import ChatOpenAI
from langchain_community.llms import Ollama
# OpenAI API
llm = ChatOpenAI(model="gpt-4", temperature=0.7)
# 本地模型(Ollama部署的Qwen3)
llm = Ollama(model="qwen3:8b")
# 智谱AI
from langchain_community.chat_models import ChatZhipuAI
llm = ChatZhipuAI(model="glm-4")
# 统一接口:不管底层是什么模型,调用方式完全一样
response = llm.invoke("什么是RAG?")
print(response.content)
# 这就是LangChain的核心价值之一:
# 一行代码切换模型,不需要修改业务逻辑
核心组件 2 :提示模板——结构化提示词
from langchain_core.prompts import ChatPromptTemplate
# 创建模板(类似填空题)
template = ChatPromptTemplate.from_messages([
("system", "你是一位{role},请用{style}的方式回答问题。"),
("user", "{question}")
])
# 填充模板(把空填上)
prompt = template.invoke({
"role": "AI专家",
"style": "简洁明了",
"question": "什么是Transformer?"
})
# 发送给模型
response = llm.invoke(prompt)
为什么需要模板?
类比:邮件模板
- 没有模板:每次写邮件都要从头写
- 有模板:填入姓名、日期等变量,自动生成完整邮件
提示模板同理:
- 定义一次模板,多次复用
- 变量可以在运行时动态填充
- 保证提示词的一致性
核心组件 3 :链(Chain)——LCEL 管道语法
from langchain_core.output_parsers import StrOutputParser
# LCEL(LangChain Expression Language)管道语法
chain = template | llm | StrOutputParser()
# 等价于:
# 1. template处理输入 → 生成提示词
# 2. llm处理提示词 → 生成回答
# 3. StrOutputParser处理回答 → 提取纯文本
# 执行链
result = chain.invoke({
"role": "AI专家",
"style": "简洁明了",
"question": "什么是Transformer?"
})
# 管道语法的魔力:可以用 | 把任意组件串联起来
# 就像Unix的管道:cat file | grep "error" | sort
核心组件 4 :文档加载与向量存储
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
# 1. 加载文档(把PDF变成可处理的文本)
loader = PyPDFLoader("document.pdf")
documents = loader.load()
# 2. 文本切分(把长文档切成小块)
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块500个字符
chunk_overlap=50 # 相邻块重叠50个字符
)
chunks = splitter.split_documents(documents)
# 3. 向量化(把文本变成数字向量)
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(chunks, embeddings)
# 4. 检索(找到最相关的文档块)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
docs = retriever.invoke("什么是机器学习?")
为什么要切分?为什么要有 overlap ?
为什么切分:
- 大模型有上下文长度限制(如 4K 、 8K 、 128K tokens)
- 一次塞入整本文档不现实
- 检索时需要精确匹配,整本文档太粗糙
为什么 overlap (重叠):
- 如果在句子中间切断,前后两块的语义都不完整
- overlap 让相邻块有重叠部分,确保信息的连续性
- 类比:看书时翻页,上一页的最后一行和下一页的第一行能衔接上
核心组件 5 : RAG 链——检索增强生成
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
# RAG提示模板
rag_prompt = ChatPromptTemplate.from_template("""
请根据以下参考信息回答用户的问题。
如果参考信息中没有相关内容,请说明你不确定。
参考信息:
{context}
用户问题:
{question}
""")
# RAG链的构建(LCEL管道语法)
rag_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| rag_prompt
| llm
| StrOutputParser()
)
# 使用
answer = rag_chain.invoke("什么是注意力机制?")
# 流程:
# 1. "什么是注意力机制?" → retriever检索相关文档
# 2. 检索到的文档 + 问题 → 填入提示模板
# 3. 填充后的提示 → 发送给LLM
# 4. LLM的回答 → 提取纯文本 → 返回
核心组件 6 : Agent——让模型自主决策
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.tools import tool
# 定义工具(给模型"武器")
@tool
def search_web(query: str) -> str:
"""搜索网页获取最新信息"""
return "搜索结果..."
@tool
def calculate(expression: str) -> str:
"""计算数学表达式"""
# 警告:eval() 有安全风险,生产环境应使用 ast.literal_eval 或 sympy
return str(eval(expression))
# 创建Agent(给模型"大脑")
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有用的助手,可以使用工具来回答问题。"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
tools = [search_web, calculate]
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 使用
result = agent_executor.invoke({"input": "今天北京的天气怎么样?"})
# Agent会自动:
# 1. 分析问题 → "需要查天气"
# 2. 选择工具 → search_web
# 3. 调用工具 → search_web("北京今天天气")
# 4. 整合结果 → 生成自然语言回答
Chain vs Agent 的区别:
- Chain(链):固定流程, A → B → C
- 类比:工厂流水线——每一步都是预设的
- 适合:流程明确的任务(RAG 问答、文本翻译)
- Agent(智能体):动态决策,根据情况选择下一步
- 类比:真人客服——根据问题类型灵活应对
- 适合:需要判断和选择的任务(多工具调用、复杂查询)
模块小结: LangChain 框架
| 你学到了什么 | 为什么重要 |
|---|---|
| 统一 LLM 调用接口 | 一行代码切换模型 |
| 提示模板 | 结构化、可复用的提示词 |
| LCEL 管道语法 | 链式组合组件 |
| 文档加载与切分 | RAG 的数据准备基础 |
| RAG 链构建 | 检索增强生成的标准实现 |
| Agent 智能体 | 让模型自主决策 |
3. OpenAI API 与 Embedding
Embedding——把文本变成"语义坐标"
类比:给每个词/句子在"语义地图"上定位
- Embedding = 把文本转换为一个固定长度的数字向量
- “猫” → [0.2, 0.8, -0.1, 0.5, …](1536 维)
- “狗” → [0.3, 0.7, -0.2, 0.4, …](和“猫”接近)
- “汽车” → [-0.5, 0.1, 0.9, -0.3, …](和“猫”很远)
语义相似的文本 → 向量接近(余弦相似度接近 1) 语义不同的文本 → 向量远离(余弦相似度接近 0)
from openai import OpenAI
import numpy as np
client = OpenAI()
# 获取Embedding
response = client.embeddings.create(
model="text-embedding-3-small",
input="什么是机器学习?"
)
embedding = response.data[0].embedding # 1536维向量
# 计算相似度
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 获取三个句子的 Embedding
embedding1 = client.embeddings.create(model="text-embedding-3-small", input="机器学习是什么").data[0].embedding
embedding2 = client.embeddings.create(model="text-embedding-3-small", input="什么是机器学习").data[0].embedding
embedding3 = client.embeddings.create(model="text-embedding-3-small", input="今天天气怎么样").data[0].embedding
# "机器学习是什么" 和 "什么是机器学习" → 几乎相同的问题 → 高相似度
sim1 = cosine_similarity(embedding1, embedding2) # ≈ 0.95
# "什么是机器学习" 和 "今天天气怎么样" → 完全不同的话题 → 低相似度
sim2 = cosine_similarity(embedding1, embedding3) # ≈ 0.1
Embedding 是 RAG 的基础:
- RAG 的检索步骤 = 把用户问题和所有文档都转为 Embedding ,然后找最相似的
- 用户问题:“什么是注意力机制?” → Embedding → [0.1, 0.5, -0.3, …]
- 文档 1 :“注意力机制是一种让模型关注重要信息的技术”
- Embedding → [0.1, 0.5, -0.2, …] ← 高相似度
- 文档 2 :“今天天气很好”
- Embedding → [-0.4, 0.1, 0.8, …] ← 低相似度
- 返回文档 1 给模型作为参考
Chat Completion API
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "你是一位AI助手"},
{"role": "user", "content": "解释什么是RAG"}
],
temperature=0.7,
max_tokens=500,
stream=True # 流式输出,详见 §4 流式输出小节
)
模块小结: OpenAI API
| 你学到了什么 | 为什么重要 |
|---|---|
| Embedding 向量化 | 把文本变成语义坐标 |
| Chat Completion API | 对话接口的标准用法 |
| 流式输出 | 提升用户体验 |
| 余弦相似度 | 衡量语义相似性 |
4. RAG 系统深入——检索增强生成
为什么需要 RAG?——大模型的三大硬伤
大模型虽然强大,但有三个根本性缺陷:
- 知识截止日期:GPT-4 的知识截止到训练数据的时间点,不知道"今天的新闻"
- 幻觉(Hallucination):大模型会"一本正经地胡说八道"——对不知道的事实编造看起来合理的答案
- 企业私有数据:大模型从未见过你公司的内部文档、产品手册
RAG 的解决方案:不让大模型"凭记忆回答",而是先帮它"查资料",再让它"基于资料回答"。
Function Calling——让大模型使用工具
大模型就像一个博学的顾问——他知道很多知识,但没有"手"(不能查数据库、不能发邮件、不能搜索网页)。Function Calling = 给这个顾问配上"工具箱"。
工作流程:
- 用户提问 → 大模型分析问题,判断需要调用哪个工具
- 大模型生成工具调用指令(函数名 + 参数)→ 外部系统执行工具
- 工具返回结果 → 大模型整合结果生成最终回答
代码示例(OpenAI Function Calling):
import openai
# Step 1:定义工具(告诉模型有哪些工具可用)
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"]
}
}
}]
# Step 2:用户提问,模型决定是否调用工具
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "北京今天天气怎么样?"}],
tools=tools,
tool_choice="auto" # 让模型自动决定是否调用工具
)
# Step 3:模型返回 tool_calls(函数名 + 参数)
tool_call = response.choices[0].message.tool_calls[0]
# → function: get_weather, arguments: {"city": "北京"}
# Step 4:外部系统执行工具,返回结果
weather_result = get_weather(city="北京") # 你自己的函数
# Step 5:将结果交给模型,生成最终回答
final_response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": "北京今天天气怎么样?"},
response.choices[0].message, # 模型的 tool_calls
{"role": "tool", "tool_call_id": tool_call.id, "content": str(weather_result)}
]
)
# → "北京今天晴,气温 25°C,适合出行。"
关键理解:大模型不直接执行工具,它只是"决策者"——决定用什么工具、传什么参数。执行由外部系统完成。完整的 Function Calling 和 MCP 协议详解见第八篇 §4。
流式输出——提升用户体验
普通输出:等模型生成全部内容后一次性返回 → 用户等待时间长,体验差。
流式输出(Streaming):模型每生成一个 token 就立即返回 → 用户看到文字逐字出现,像"打字机"一样。底层通过 SSE(Server-Sent Events)或 chunked transfer encoding 实现——服务端不需要等所有内容生成完,每生成一小块就推送给客户端。
# 流式输出的关键参数
response = client.chat.completions.create(
model="gpt-4",
messages=[...],
stream=True # 启用流式输出
)
# 逐块接收并显示
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
RAG 的完整体系(向量数据库、高级检索策略、GraphRAG、评估体系)详见第七篇。
模块小结:RAG 系统深入
| 你学到了什么 | 为什么重要 |
|---|---|
| RAG 三大硬伤 | 知识截止、幻觉、私有数据——RAG 的动机 |
| Function Calling 工作流程 | 让大模型使用外部工具的三步机制 |
| 流式输出 | 逐 token 返回,提升用户体验 |
5. 国产大模型实战
ChatGLM——智谱 AI 生态
ChatGLM 是智谱 AI 开发的开源对话大模型系列。
核心特点:
- 中文能力强:专门为中文优化,中文理解准确度高
- 支持 Function Calling :可以调用外部工具
- 提供云端 API :通过智谱 AI 的 API 直接调用
- 支持本地部署:开源模型可以自己部署
- 与 LangChain 集成:有专门的 LangChain 集成包
架构特点:
- 基于 Prefix LM (不是纯 Decoder)
- 同时支持理解和生成
- 上下文窗口: 128K tokens
Qwen3——通义千问
Qwen3 是阿里云开发的开源大模型系列。
核心特点:
- 多尺寸可选: 0.6B / 1.7B / 4B / 8B / 14B / 32B / 72B
- 从手机端到服务器端都有合适的模型
- 深度思考模式(Thinking Mode):
- 类似 o1 的“慢思考”能力
- 在回答前先进行内部推理
- 数学、编程、逻辑推理能力大幅提升
- 混合推理(Hybrid Mode):
- 简单问题用快速模式
- 复杂问题自动切换到深度思考模式
- 兼顾速度和质量
- 嵌入模型同步可用:
- Qwen3-Embedding :文本向量化
- Qwen3-Reranker :检索结果重排序
TEXT2SQL+Qwen3 项目实战
项目目标:用户输入自然语言问题,自动生成 SQL 查询并返回结果。
技术栈:
- Qwen3 大模型:理解用户意图,生成 SQL 语句
- MCP 服务端:封装数据库操作工具(查表结构、执行 SQL)
- LangGraph :编排工作流(意图识别 → 查表结构 → 生成 SQL → 执行 → 返回) 完整流程: 用户:“上个月销售额最高的产品是什么?” ↓ Step 1: Qwen3 理解意图 → “需要查询销售数据” ↓ Step 2: 调用 MCP 工具 → 获取数据库表结构 ↓ Step 3: Qwen3 生成 SQL → SELECT product_name FROM sales WHERE … ORDER BY amount DESC LIMIT 1 ↓ Step 4: 调用 MCP 工具 → 执行 SQL 查询 ↓ Step 5: Qwen3 整合结果 → “上个月销售额最高的产品是 iPhone 15 ,销售额为 500 万元。”
模块小结:国产大模型实战
| 你学到了什么 | 为什么重要 |
|---|---|
| ChatGLM 生态 | 中文能力强的开源模型 |
| Qwen3 多尺寸模型 | 从端侧到云端全覆盖 |
| 深度思考模式 | 复杂推理能力提升 |
| TEXT2SQL 实战项目 | MCP + LangGraph 综合应用 |
下一篇预告:本文掌握了 LLM 应用开发的基础工具链。在速通 AI(七):RAG 检索增强生成中,你将深入学习 RAG 的完整体系——向量数据库、高级检索策略、GraphRAG、评估体系。