AI专业课程培训教材#
面向对象:参加AI专业课程选拔考试的学员
教材特点:理论结合实操,严格按大纲知识点逐条覆盖,每章含知识讲解、代码示例和考试要点
大纲来源:附件2:AI专业课程大纲
更新日期:2026年7月
- 第一天:大模型前沿技术发展与实践
- 第二天:大模型部署与应用 + TokenHub
- 第三天:RAG原理与企业知识库建设基础
- 第四天:Dify进阶Agent系统开发
- 第五天:Vibe Coding工具使用
- 第六天:大模型开发工具链实战(LangChain)
- 第七天:大模型开发工具链实战(LangGraph与DeepAgents)
- 第八天:MCP与Skills开发实战
- 第九天:企业级数字员工开发基础实操
- 第十天:进阶实操-多智能体数字员工电信运维场景
第一天 大模型前沿技术发展与实践#
1.1 大语言模型发展趋势洞察#
1.1.1 从GPT-3到GPT-4、Llama、Qwen、DeepSeek的架构演进#
| 模型系列 | 发布时间 | 参数规模 | 核心架构创新 | 意义 |
|---|
| GPT-3 | 2020 | 175B | 稀疏注意力优化 | 规模化涌现能力首次验证 |
| GPT-4 | 2023 | 未公开(推测1.8T) | MoE混合专家架构 | 多模态+推理大幅提升 |
| Llama 2/3/4 | 2023-2025 | 7B-405B | GQA分组查询注意力 | 开源旗舰,可本地部署 |
| Qwen 2.5/3 | 2024-2025 | 0.5B-72B | 千问MoE架构,中文优化 | 国产开源标杆 |
| DeepSeek V3/R1 | 2025 | 671B(MoE) | MLA多头潜在注意力+DeepSeekMoE | 训练成本极低,推理能力对标o1 |
架构演进核心趋势:
Dense(稠密)→ MoE(混合专家)→ MLA+MoE(潜在注意力+稀疏化)
GPT-3: Dense Transformer,所有参数每次都激活
↓
GPT-4/Mixtral: MoE,每次只激活部分专家参数(如8选2)
↓
DeepSeek V3: MLA+DeepSeekMoE,KV Cache压缩到1/4,训练成本仅557万美元
1.1.2 参数规模、数据质量、训练策略对模型性能的影响#
Chinchilla定律(DeepMind 2022):最优训练策略下,模型参数量和训练数据量应同步增长,比例约20 tokens/参数。违反此定律的模型(如GPT-3训练不足)性能会受限。
| 因素 | 影响 | 典型案例 |
|---|
| 参数规模 | 超过10B后涌现推理和指令遵循能力 | GPT-3 175B vs 6B差距巨大 |
| 数据质量 | 高质量数据可缩小10倍参数差距 | Phi-3用1/10参数达到GPT-3.5水平 |
| 训练策略 | RLHF/DPO对齐训练决定输出质量 | Llama-2-Chat远超Llama-2-Base |
1.1.3 Scaling Law的新解释:推理阶段Scaling与测试时训练#
传统Scaling Law认为性能提升依赖训练阶段增加参数和数据。2024-2025年出现了新范式:
| Scaling维度 | 传统(训练阶段) | 新范式(推理阶段) |
|---|
| 增加方式 | 更多参数、更多数据 | 更多推理计算、更长思维链 |
| 代表 | GPT-3→GPT-4 | OpenAI o1→o3、DeepSeek-R1 |
| 原理 | 模型容量提升 | 推理时搜索+自我验证 |
| 成本 | 一次性训练成本高 | 每次推理成本高 |
| 效果 | 基础能力提升 | 复杂推理能力飞跃 |
测试时训练(Test-Time Training, TTT):在推理阶段根据当前输入对模型进行少量梯度更新,使其适应该特定任务。典型应用:o1模型在回答数学题前先"思考"数十秒。
1.1.4 开源模型与闭源模型的竞合态势#
| 维度 | 闭源模型 | 开源模型 |
|---|
| 代表 | GPT-4o、Claude 4、Gemini | Llama 4、Qwen 3、DeepSeek V3 |
| 性能天花板 | 最高 | 接近(差距<10%) |
| 部署灵活性 | 仅API调用 | 可本地部署、可微调 |
| 数据安全 | 数据需上传 | 数据不出本地 |
| 成本 | 按Token计费 | 一次性算力成本 |
| 2026趋势 | 推理能力领先 | 部署生态更成熟 |
1.2 核心能力涌现与多模态融合#
1.2.1 上下文学习(ICL)、思维链(CoT)、指令遵循的数学原理#
In-Context Learning(ICL):
# ICL:不更新参数,仅通过示例引导模型学习
Prompt: "将以下句子翻译为英文:
示例:你好世界 → Hello World
示例:人工智能 → Artificial Intelligence
输入:大模型 → ???"
# 模型根据上下文中的模式推断任务,无需任何参数更新
Chain-of-Thought(CoT):
# CoT:引导模型展示推理过程
普通Prompt: "一个商店有23个苹果,卖了17个,又进了8个,现在有多少?"
模型可能直接回答: "14个" # 可能计算错误
CoT Prompt: "一个商店有23个苹果,卖了17个,又进了8个,现在有多少?请一步步推理。"
模型回答: "23 - 17 = 6, 6 + 8 = 14。答案是14个。" # 准确率提升30%+
数学原理:
- ICL本质是Transformer的注意力机制实现的模式匹配
- CoT将复杂推理分解为多步简单计算,每步都在注意力的有效范围内
- 指令遵循通过RLHF训练,让模型输出对齐人类意图
1.2.2 多模态模型融合策略#
| 模型 | 融合方式 | 架构特点 |
|---|
| CLIP | 对比学习对齐 | 图像编码器+文本编码器,对比损失对齐 |
| Flamingo | 交叉注意力融合 | 视觉特征通过Perceiver Resampler压缩后注入语言模型 |
| GPT-4o | 原生多模态 | 从头训练统一处理文本、图像、音频 |
| Qwen-VL | 视觉编码器+LLM | ViT编码图像→适配层→Qwen语言模型 |
1.2.3 多模态在电信场景的应用#
| 应用场景 | 输入模态 | 输出 | 技术方案 |
|---|
| 工单图片识别 | 工单照片 | 结构化工单数据 | OCR+VLM |
| 信号热力图分析 | 基站信号覆盖热力图 | 弱覆盖区域标注 | 图像理解+数据分析 |
| 现场照片质检 | 施工/装维现场照片 | 合规性判断 | 图像分类 |
| 客服情绪识别 | 语音通话 | 情绪标签 | 语音情感分析 |
1.3 MaaS平台概述与架构设计#
1.3.1 MaaS分层架构#
┌─────────────────────────────────────────────┐
│ 应用层(Application) │
│ 智能客服 │ 运维Agent │ 数据分析 │ 内容生成 │
├─────────────────────────────────────────────┤
│ 中间件层(Middleware) │
│ API网关 │ 负载均衡 │ 缓存 │ 限流 │ 计量计费 │
├─────────────────────────────────────────────┤
│ 模型层(Model) │
│ 文本模型 │ 多模态模型 │ Embedding │ 推理引擎 │
├─────────────────────────────────────────────┤
│ 基础设施层(Infrastructure) │
│ GPU集群 │ 存储 │ 网络 │ K8s编排 │
└─────────────────────────────────────────────┘
1.3.2 主流MaaS平台对比#
| 平台 | 提供方 | 模型丰富度 | 特色优势 | 计费方式 |
|---|
| 阿里百炼 | 阿里云 | 高(通义+开源) | 一站式开发平台,含Agent开发 | 按Token |
| 火山方舟 | 字节跳动 | 高(豆包+开源) | 精调+评估+部署全链路 | 按Token |
| ModelScope | 阿里达摩院 | 中(聚焦开源) | 开源模型社区+免费额度 | 免费+按量 |
| HuggingFace Hub | HuggingFace | 最高(全球开源) | 全球最大模型社区 | 免费+Pro |
1.3.3 模型版本管理、弹性伸缩、计费模式设计#
| 能力 | 说明 | 实现方式 |
|---|
| 版本管理 | 多版本共存、灰度切换 | 模型注册表+版本号+别名 |
| 弹性伸缩 | 按流量自动扩缩容 | K8s HPA + GPU弹性 |
| 计费模式 | 按Token/按次/包月 | API网关计量+账单系统 |
1.4 大模型推理优化核心技术#
1.4.1 KV Cache原理与显存优化#
核心原理:Transformer自注意力机制中,每层需要计算Q、K、V三个矩阵。K和V只依赖已生成的token,生成新token时无需重新计算,直接缓存复用。
# KV Cache显存占用计算(以7B模型为例)
# 参数: hidden_size=4096, num_layers=32, num_heads=32
# 每个token的KV Cache大小
kv_cache_per_token = 2 * num_layers * hidden_size * dtype_size
# FP16: 2 * 32 * 4096 * 2 bytes = 524,288 bytes ≈ 0.5MB
# 生成4096个token的KV Cache总量
total_kv_cache = kv_cache_per_token * 4096
# ≈ 2GB (仅KV Cache就占2GB显存!)
# 优化:MQA/GQA减少KV头数
# GQA: num_kv_heads=8 (原32头分8组)
kv_cache_gqa = 2 * 32 * 4096 * (8/32) * 2 * 4096 # 节省75%
| 优化技术 | 原理 | 显存节省 |
|---|
| MQA | 所有Query共享1组KV | 1/N(N=头数) |
| GQA | 分组共享KV(Llama 2采用) | 1/G(G=组数) |
| MLA | 潜在注意力压缩(DeepSeek) | 约1/4 |
| PagedAttention | 分页管理KV Cache(vLLM) | 减少碎片 |
1.4.2 Flash Attention 1/2/3#
Flash Attention是GPU友好的注意力计算优化算法,核心思想:通过分块计算避免实例化完整的N×N注意力矩阵。
| 版本 | 发布 | 核心优化 | 加速比 |
|---|
| Flash Attention 1 | 2022 | 分块计算+IO感知 | 2-4x |
| Flash Attention 2 | 2023 | 减少非矩阵乘法操作 | 2x(相对v1) |
| Flash Attention 3 | 2024 | 异步化+FP8支持 | 1.5-2x(相对v2) |
# Flash Attention在Transformers中的使用
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3-8B",
torch_dtype="auto",
attn_implementation="flash_attention_2" # 启用Flash Attention 2
)
1.4.3 量化技术:GPTQ、AWQ、GGUF#
量化是将模型权重从FP16/BF16压缩到低精度(INT8/INT4),大幅减少显存占用和推理延迟。
| 技术 | 量化方式 | 精度损失 | 适用场景 | 文件格式 |
|---|
| GPTQ | 训练后量化,逐层最小化输出误差 | 较大 | GPU推理 | .safetensors |
| AWQ | 激活感知量化,保护重要权重 | 较小 | GPU推理 | .safetensors |
| GGUF | llama.cpp格式,支持CPU/GPU混合 | 可调 | CPU/边缘部署 | .gguf |
# GGUF量化等级
| 量化等级 | 位宽 | 模型大小(7B) | 精度损失 | 适用硬件 |
|---------|------|-------------|---------|---------|
| F16 | 16bit | 13GB | 无 | GPU |
| Q8_0 | 8bit | 7GB | 极小 | GPU/CPU |
| Q4_K_M | 4bit | 4GB | 小 | CPU/GPU混合 |
| Q3_K_S | 3bit | 3GB | 中等 | CPU |
1.4.4 投机采样(Speculative Decoding)与批处理#
投机采样:用一个小的"草稿模型"快速生成候选token,再用大模型并行验证,减少大模型的前向传播次数。
传统自回归: 大模型逐token生成 → N次前向传播
投机采样: 小模型生成K个候选 → 大模型1次前向验证 → 接受/拒绝
若K=5且接受4个,则1次大模型前向生成5个token
批处理策略:
| 策略 | 说明 | 适用场景 |
|---|
| 静态批处理 | 固定批次大小 | 离线推理 |
| 动态批处理 | 请求到齐即处理 | 在线推理 |
| 连续批处理 | 边生成边加入新请求 | vLLM/SGLang |
1.4.5 服务化框架选型#
| 框架 | 开发方 | 核心优势 | 适用场景 |
|---|
| vLLM | UC Berkeley | PagedAttention,高吞吐 | 生产高并发 |
| TGI | HuggingFace | 功能全面,生态好 | 中等规模 |
| TensorRT-LLM | NVIDIA | 极致GPU优化 | NVIDIA硬件 |
| SGLang | 系统作者 | 结构化生成+RadixAttention | 复杂提示 |
# vLLM部署示例
pip install vllm
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3-8B-Instruct \
--port 8000 \
--gpu-memory-utilization 0.9 \
--max-model-len 8192
1.5 模型服务化工程实践与生态#
1.5.1 模型封装为RESTful/gRPC服务#
# RESTful API封装(FastAPI + vLLM)
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ChatRequest(BaseModel):
model: str
messages: list[dict]
temperature: float = 0.7
max_tokens: int = 1024
stream: bool = False
@app.post("/v1/chat/completions")
async def chat(req: ChatRequest):
# 调用vLLM推理引擎
result = llm_engine.generate(req.messages, req.max_tokens)
return {"choices": [{"message": {"content": result}}]}
1.5.2 灰度发布、AB测试、监控告警#
| 能力 | 实现方式 | 工具 |
|---|
| 灰度发布 | 按比例路由到新旧模型版本 | Istio + K8s |
| AB测试 | 对比不同模型/参数的效果 | 自建实验平台 |
| 监控告警 | QPS/延迟/错误率/GPU利用率 | Prometheus + Grafana |
| 日志采集 | 请求/响应日志审计 | ELK Stack |
1.6 Hermes原理与实战 + TeleAgent#
1.6.1 Hermes 2 Pro函数调用机制#
Hermes是由Nous Research开源的大模型系列,Hermes 2 Pro版本强化了**函数调用(Function Calling)**能力,允许模型根据用户意图自动选择并调用预定义的函数。
# Hermes 2 Pro Function Calling示例
import json
# 定义可用工具(函数)
tools = [
{
"type": "function",
"function": {
"name": "query_user_info",
"description": "查询用户套餐信息",
"parameters": {
"type": "object",
"properties": {
"phone": {"type": "string", "description": "手机号"}
},
"required": ["phone"]
}
}
},
{
"type": "function",
"function": {
"name": "recommend_package",
"description": "根据用户使用情况推荐套餐",
"parameters": {
"type": "object",
"properties": {
"monthly_data": {"type": "number", "description": "月均流量使用(GB)"},
"monthly_calls": {"type": "integer", "description": "月均通话(分钟)"},
"budget": {"type": "number", "description": "月预算(元)"}
},
"required": ["monthly_data", "budget"]
}
}
}
]
# 用户消息
messages = [
{"role": "system", "content": "你是电信客服助手,可以查询用户信息和推荐套餐。"},
{"role": "user", "content": "我的手机号是13800138000,帮我看看用什么套餐合适,我每月用大概30G流量,预算100元"}
]
# 调用Hermes模型(兼容OpenAI API格式)
response = client.chat.completions.create(
model="NousResearch/Hermes-2-Pro-Llama-3-8B",
messages=messages,
tools=tools,
tool_choice="auto"
)
# 模型返回工具调用决策
tool_call = response.choices[0].message.tool_calls[0]
print(f"调用函数: {tool_call.function.name}")
print(f"参数: {json.loads(tool_call.function.arguments)}"
)
# 输出: 调用函数: recommend_package
# 参数: {"monthly_data": 30.0, "budget": 100.0}
1.6.2 TeleAgent:电信领域专用Agent框架#
TeleAgent是面向电信行业设计的专用Agent框架,核心设计理念包括:
| 特性 | 说明 |
|---|
| 任务模板 | 预置电信场景任务模板(报障、查话费、套餐变更等) |
| 领域知识注入 | 内置电信行业知识库和术语词典 |
| 工具集成 | 封装CRM、计费、网络管理等系统API |
| 安全合规 | 遵循电信行业数据安全规范 |
1.6.3 实战:基于Hermes Pro编写套餐推荐Function Calling Demo#
"""
套餐推荐Demo
用户输入需求 → Hermes模型决策 → 调用推荐函数 → 返回结果
"""
def recommend_package(monthly_data: float, monthly_calls: int = 0, budget: float = 100):
"""根据用户需求推荐套餐"""
packages = [
{"name": "5G尊享129", "price": 129, "data": 50, "calls": 1000, "features": "适合大流量用户"},
{"name": "5G畅享99", "price": 99, "data": 30, "calls": 500, "features": "性价比之选"},
{"name": "5G活力59", "price": 59, "data": 15, "calls": 200, "features": "经济实惠"},
]
# 筛选符合预算且满足流量需求的套餐
suitable = [
p for p in packages
if p["price"] <= budget * 1.2 and p["data"] >= monthly_data
]
if not suitable:
return {"error": "未找到匹配套餐", "suggestion": "建议适当增加预算"}
# 按价格排序取最优
best = min(suitable, key=lambda x: x["price"])
return {
"recommended": best["name"],
"price": f"{best['price']}元/月",
"data": f"{best['data']}GB",
"calls": f"{best['calls']}分钟",
"features": best["features"],
"reason": f"满足{monthly_data}GB流量需求,价格{best['price']}元在预算{budget}元范围内"
}
# 完整调用链
def run_demo():
user_input = "我每月用30G流量,通话500分钟,预算100元"
# Step 1: Hermes决策调用哪个函数
# Step 2: 执行函数
result = recommend_package(monthly_data=30, monthly_calls=500, budget=100)
# Step 3: 生成交互回复
print(f"为您推荐【{result['recommended']}】套餐")
print(f"月费{result['price']},含{result['data']}流量{result['calls']}")
print(f"推荐理由:{result['reason']}")
run_demo()
考试要点#
- 理解从GPT-3到DeepSeek的架构演进路线(Dense→MoE→MLA+MoE)
- 掌握参数规模、数据质量、训练策略三大影响因素及Chinchilla定律
- 理解推理阶段Scaling的新范式(o1/R1的测试时计算)
- 理解ICL、CoT的原理和区别
- 掌握MaaS四层架构和主流平台特点
- 理解KV Cache原理,能计算KV Cache显存占用
- 了解Flash Attention分块计算的核心思想
- 掌握GPTQ、AWQ、GGUF三种量化技术的适用场景
- 了解投机采样和连续批处理的基本概念
- 能对比vLLM/TGI/TensorRT-LLM选择服务化框架
- 掌握Hermes Function Calling的工作流程
- 了解TeleAgent电信Agent框架的核心设计理念
AI生成
第二天 大模型部署与应用 + TokenHub#
2.1 HuggingFace/ModelScope库使用#
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
# 1. from_pretrained: 加载模型和分词器
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct",
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
# 2. pipeline: 快速推理
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
result = pipe("什么是5G网络切片?", max_new_tokens=200)
print(result[0]["generated_text"])
# 3. tokenizer: 文本编码/解码
inputs = tokenizer("大模型推理优化", return_tensors="pt")
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])
print(f"Token化: {tokens}")
print(f"Token数: {len(tokens)}")
2.1.2 模型缓存管理#
# 默认缓存路径: ~/.cache/huggingface/hub
# 可自定义cache_dir
model = AutoModel.from_pretrained("Qwen/Qwen2.5-7B", cache_dir="./models")
# ModelScope下载
from modelscope import snapshot_download
model_dir = snapshot_download("Qwen/Qwen2.5-7B-Instruct", revision="master")
print(f"模型下载到: {model_dir}")
2.1.3 国内镜像加速配置#
# 方式1: 环境变量配置hf-mirror镜像
export HF_ENDPOINT=https://hf-mirror.com
# Windows PowerShell:
$env:HF_ENDPOINT="https://hf-mirror.com"
# 方式2: 使用ModelScope(国内速度快)
pip install modelscope
# ModelScope是阿里达摩院开源的模型社区,国内访问速度快
# 方式3: 配置.gitconfig加速
# 对于git clone方式下载模型
git config --global url."https://hf-mirror.com".insteadOf "https://huggingface.co"
2.2 模型推理与本地部署#
2.2.1 Ollama安装与使用#
# 安装Ollama(Linux)
curl -fsSL https://ollama.com/install.sh | sh
# Windows: 从ollama.com下载安装包
# 基本命令
ollama pull qwen2.5:7b # 下载模型
ollama run qwen2.5:7b # 运行模型
ollama list # 查看已安装模型
ollama stop qwen2.5:7b # 停止模型
ollama rm qwen2.5:7b # 删除模型
2.2.2 Modelfile编写(自定义系统提示词、对话模板)#
# Modelfile: 自定义Ollama模型配置
FROM qwen2.5:7b
# 自定义系统提示词
SYSTEM """
你是电信行业AI助手,专注于电信领域知识。
回答需要专业准确,使用标准电信术语。
不确定时请明确告知用户。
"""
# 参数设置
PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER num_ctx 4096
# 对话模板
TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}<|im_start|>user
{{ .Prompt }}<|im_end|>
<|im_start|>assistant
"""
# 保存后构建
# ollama create telecom-bot -f Modelfile
# ollama run telecom-bot
2.2.3 从GGUF导入模型#
# 1. 下载GGUF格式模型
# 从HuggingFace或ModelScope下载 .gguf 文件
# 2. 创建Modelfile指定GGUF路径
echo 'FROM ./qwen2.5-7b-instruct-q4_k_m.gguf' > Modelfile
# 3. 导入
ollama create my-qwen -f Modelfile
# 4. 运行
ollama run my-qwen
2.2.4 使用Ollama的OpenAI兼容API#
import requests
# Ollama默认提供OpenAI兼容API(端口11434)
url = "http://localhost:11434/v1/chat/completions"
headers = {"Content-Type": "application/json"}
data = {
"model": "qwen2.5:7b",
"messages": [
{"role": "system", "content": "你是电信助手"},
{"role": "user", "content": "什么是5G网络切片?"}
],
"stream": False # 非流式
}
response = requests.post(url, json=data, headers=headers)
print(response.json()["choices"][0]["message"]["content"])
# 流式调用
data["stream"] = True
response = requests.post(url, json=data, headers=headers, stream=True)
for line in response.iter_lines():
if line:
import json
chunk = json.loads(line)
if chunk["choices"][0].get("delta", {}).get("content"):
print(chunk["choices"][0]["delta"]["content"], end="")
2.2.5 Ollama与vLLM性能对比#
| 维度 | Ollama | vLLM |
|---|
| 部署难度 | 极简(一键安装) | 中等(需Python环境) |
| 并发能力 | 低(单请求为主) | 高(PagedAttention) |
| 吞吐量 | 中 | 高(2-5x于Ollama) |
| GPU利用率 | 一般 | 高(连续批处理) |
| 适用场景 | 开发调试/个人使用 | 生产环境高并发 |
2.3 大模型API调用#
2.3.1 HTTP请求构造#
import requests
import json
# 通用OpenAI兼容API调用
def call_llm(messages, model="gpt-4o", stream=False):
"""大模型API通用调用函数"""
url = "https://api.openai.com/v1/chat/completions"
headers = {
"Authorization": "Bearer sk-your-api-key",
"Content-Type": "application/json"
}
payload = {
"model": model,
"messages": messages,
"temperature": 0.7,
"max_tokens": 2048,
"stream": stream
}
if stream:
response = requests.post(url, json=payload, headers=headers, stream=True)
for line in response.iter_lines():
if line and line.startswith(b"data: "):
data = json.loads(line[6:])
if data != "[DONE]":
yield data["choices"][0]["delta"].get("content", "")
else:
response = requests.post(url, json=payload, headers=headers)
return response.json()["choices"][0]["message"]["content"]
2.3.2 异常处理(重试、超时、Rate Limit)#
import time
from requests.exceptions import RequestException
def call_with_retry(messages, max_retries=3, timeout=30):
"""带重试和超时的API调用"""
for attempt in range(max_retries):
try:
response = requests.post(
url, json=payload, headers=headers,
timeout=timeout
)
# Rate Limit处理
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 5))
print(f"触发限流,等待{retry_after}秒后重试")
time.sleep(retry_after)
continue
response.raise_for_status()
return response.json()
except RequestException as e:
print(f"第{attempt+1}次请求失败: {e}")
if attempt < max_retries - 1:
wait = 2 ** attempt # 指数退避
time.sleep(wait)
raise Exception(f"请求失败,已重试{max_retries}次")
2.3.3 异步调用与批量请求#
import asyncio
import aiohttp
async def async_call(session, message):
"""异步单次调用"""
async with session.post(url, json={"model": "gpt-4o", "messages": message}) as resp:
return await resp.json()
async def batch_call(messages_list):
"""批量异步调用"""
async with aiohttp.ClientSession() as session:
tasks = [async_call(session, msg) for msg in messages_list]
results = await asyncio.gather(*tasks)
return results
# 批量调用示例
messages_batch = [
[{"role": "user", "content": f"分析第{i}个告警: ..."}]
for i in range(10)
]
results = asyncio.run(batch_call(messages_batch))
2.3.4 使用LangChain统一封装多厂商API#
from langchain_openai import ChatOpenAI
from langchain_community.chat_models import ChatOllama
# OpenAI
llm_openai = ChatOpenAI(model="gpt-4o", api_key="sk-xxx")
# 本地Ollama
llm_ollama = ChatOllama(model="qwen2.5:7b", base_url="http://localhost:11434")
# 统一调用接口
llm = llm_openai # 或 llm_ollama,切换无需改业务代码
response = llm.invoke("什么是5G网络切片?")
print(response.content)
2.4 Prompt基本结构与常见类型#
2.4.1 Prompt组成要素#
| 要素 | 说明 | 示例 |
|---|
| 角色(Role) | 定义AI的身份 | “你是电信网络工程师” |
| 指令(Instruction) | 具体任务描述 | “分析以下告警的原因” |
| 上下文(Context) | 背景信息 | 设备型号、网络拓扑、历史记录 |
| 输出格式(Format) | 期望的输出结构 | “以JSON格式输出” |
2.4.2 零样本、少样本、思维链写法#
# 零样本(Zero-shot)
prompt_zeroshot = """
请将以下工单分类(宽带/话费/增值业务/其他):
工单:用户反馈手机无法上网,显示无信号。
"""
# 少样本(Few-shot)
prompt_fewshot = """
请将工单分类。
示例:
工单:用户说宽带频繁掉线 → 宽带
工单:用户质疑上月话费偏高 → 话费
工单:用户想取消增值服务 → 增值业务
工单:用户反馈手机无法上网,显示无信号 →
"""
# 思维链(CoT)
prompt_cot = """
请分析工单并分类,请先推理再给出答案。
工单:用户反馈手机无法上网,显示无信号。
思考过程:
1. 症状是"无法上网"+"无信号"
2. 手机无信号通常与网络覆盖或SIM卡有关
3. 无法上网是无信号的直接结果
4. 这属于网络接入问题
分类:宽带/网络接入
"""
2.4.3 系统提示词设计与安全护栏#
SYSTEM_PROMPT = """你是电信智能客服助手。
【可做事项】
- 查询用户套餐、余额、流量
- 回答电信业务咨询
- 协助处理简单故障
【禁止事项】
- 不提供非电信相关信息
- 不进行任何涉及付款的操作
- 不泄露其他用户信息
- 不确定时回答"抱歉,我无法确认,请咨询人工客服"
【输出要求】
- 简洁准确,使用中文
- 复杂问题分步骤回答
- 涉及操作时给出明确指引"""
2.4.4 行业场景Prompt实战#
办公类:会议纪要生成
prompt_meeting = """
请根据以下会议记录生成结构化纪要:
{transcript}
输出格式:
## 会议信息
- 时间/地点/参会人
## 会议要点
1. ...
## 决议事项
- ...
## 待办任务
| 任务 | 负责人 | 截止日期 |
"""
数据分析类:用户话单SQL生成
prompt_sql = """
你是SQL专家。根据用户问题生成PostgreSQL查询语句。
表结构:
- call_records(id, phone, call_time, duration, type, cost)
- user_packages(id, phone, package_name, monthly_fee, data_gb)
用户问题:查询2026年7月话费超过100元的用户
请只输出SQL语句,不要解释。
"""
客服类:投诉情绪安抚话术
prompt_appeasement = """
用户投诉内容:{complaint}
用户情绪:{emotion_level}(1-5,5最激动)
要求:
1. 先共情回应用户情绪
2. 表示理解并道歉
3. 给出初步处理方案
4. 承诺跟进时间
语气:温和、专业、有同理心
"""
2.5 TokenHub#
2.5.1 TokenHub概述#
TokenHub是依托天翼云云网融合优势构建的大模型聚合服务平台,核心定位为企业级大模型统一接入网关。
2.5.2 四大核心能力#
| 核心能力 | 说明 | 解决的痛点 |
|---|
| 全品类模型聚合 | 聚合豆包、DeepSeek、通义千问等文本和多模态大模型 | 模型选型难 |
| 智能调度路由 | 根据任务类型、成本、延迟自动选择最优模型 | 多模型管理复杂 |
| 分级企业账号管控 | 部门/团队/个人三级权限和额度控制 | 用量难管控 |
| 全模态安全合规围栏 | 内容审核、数据脱敏、合规过滤 | 数据不安全 |
2.5.3 统一API接入#
# TokenHub统一API调用示例
import requests
# 无论调用哪个模型,API格式统一
url = "https://tokenhub.ctyun.cn/v1/chat/completions"
headers = {
"Authorization": "Bearer th-your-token",
"Content-Type": "application/json"
}
# 调用DeepSeek
payload_deepseek = {
"model": "deepseek-v3",
"messages": [{"role": "user", "content": "分析网络告警"}]
}
# 调用豆包
payload_doubao = {
"model": "doubao-pro",
"messages": [{"role": "user", "content": "分析网络告警"}]
}
# 调用通义千问
payload_qwen = {
"model": "qwen-max",
"messages": [{"role": "user", "content": "分析网络告警"}]
}
# 统一调用方式
response = requests.post(url, json=payload_deepseek, headers=headers)
2.5.4 应用场景与解决方案#
| 场景 | TokenHub方案 | 价值 |
|---|
| 政务 | 安全围栏+国产模型优先 | 合规安全 |
| 工业制造 | 多模态模型+边缘部署 | 产线质检 |
| 科研 | 大上下文模型+批量调用 | 论文分析 |
| 机场智慧服务 | 低延迟路由+多模态 | 实时服务 |
| 软件研发 | 代码模型+API集成 | 编程辅助 |
考试要点#
- 掌握Transformers库核心API:from_pretrained、pipeline、tokenizer
- 了解ModelScope在国内镜像加速中的作用
- 能编写Ollama Modelfile(系统提示词、参数、模板)
- 掌握从GGUF导入模型到Ollama的流程
- 能使用Ollama OpenAI兼容API进行流式/非流式调用
- 对比Ollama与vLLM的性能差异和适用场景
- 掌握HTTP请求构造大模型API调用(Headers、Payload、Stream)
- 理解API异常处理:重试、超时、Rate Limit、指数退避
- 了解异步调用和批量请求优化
- 掌握Prompt四要素:角色、指令、上下文、输出格式
- 能编写零样本、少样本、思维链Prompt
- 理解系统提示词安全护栏设计
- 掌握TokenHub四大核心能力和统一API接入方式
AI生成
第三天 RAG原理与企业知识库建设基础#
3.1 企业知识库应用场景与RAG vs 微调#
3.1.1 知识库典型场景#
| 场景 | 输入 | 知识来源 | 输出 |
|---|
| 政策问答 | 用户提问 | 政策文件 | 准确政策条款引用 |
| 运维手册检索 | 故障描述 | 运维知识库 | 处理步骤和方案 |
| 产品说明书 | 产品咨询 | 产品文档 | 产品参数和使用方法 |
3.1.2 RAG与微调的本质区别#
| 维度 | RAG | 微调 |
|---|
| 本质 | 外部检索增强生成 | 更新模型参数 |
| 知识更新 | 实时(更新文档即可) | 需重新训练 |
| 成本 | 低(无需GPU训练) | 高(需GPU训练) |
| 幻觉风险 | 低(有引用来源) | 可控(但不保证准确) |
| 适用 | 动态知识、事实型问答 | 风格定制、领域术语 |
3.1.3 组合策略#
微调固定风格(回答语气、格式、术语)
+
RAG动态知识(最新的政策、手册、数据)
=
最佳效果:风格统一 + 内容准确 + 实时更新
3.1.4 电信案例:为什么资费政策必须选RAG#
资费政策每月可能调整,微调模型需要每月重新训练,成本高且周期长。RAG只需更新知识库文档即可实时生效。
3.2 Embedding模型作用与选型#
3.2.1 文本向量化原理#
文本: "宽带无法上网"
↓ Tokenize
Tokens: [宽, 带, 无法, 上网]
↓ Embedding模型
Vector: [0.21, -0.45, 0.87, ..., 0.12] # 768或1024维向量
语义相近的文本 → 向量距离相近
"宽带连不上" → [0.19, -0.43, 0.85, ..., 0.14] # 距离很近
"手机欠费了" → [0.55, 0.22, -0.31, ..., 0.67] # 距离较远
3.2.2 主流Embedding模型#
| 模型 | 提供方 | 维度 | 中文支持 | 特点 |
|---|
| BCE | 网易有道 | 768 | 优秀 | 中英双语,免费 |
| GTE | 阿里达摩院 | 768/1024 | 优秀 | 长文本支持好 |
| Ada-002 | OpenAI | 1536 | 一般 | API调用 |
| text-embedding-3 | OpenAI | 1536/3072 | 良好 | 最新版本 |
| BGE | 智源 | 768 | 优秀 | MTEB榜首 |
3.2.3 向量维度与检索精度/存储成本权衡#
| 维度 | 检索精度 | 存储成本 | 适用场景 |
|---|
| 384 | 中 | 低 | 边缘设备/海量数据 |
| 768 | 高 | 中 | 通用推荐 |
| 1024 | 高 | 较高 | 精度要求高 |
| 1536+ | 最高 | 高 | API调用无存储压力 |
3.3 向量数据库原理#
3.3.1 ANN检索核心算法#
| 算法 | 原理 | 查询速度 | 精度 | 适用 |
|---|
| HNSW | 分层小世界图,逐层缩小搜索范围 | 快 | 高 | 通用首选 |
| IVF | 倒排文件,先聚类再搜索 | 快 | 中 | 大规模数据 |
| PQ | 乘积量化,压缩向量加速比较 | 很快 | 中低 | 海量+内存有限 |
| HNSW+PQ | 结合两者 | 快 | 中高 | 大规模生产 |
# HNSW关键参数
| 参数 | 说明 | 取值建议 |
|------|------|---------|
| ef_construction | 建图时搜索宽度 | 200-400(越大越精确) |
| M | 每个节点的最大连接数 | 16-48 |
| ef_search | 查询时搜索宽度 | 50-200(越大越精确) |
# IVF关键参数
| 参数 | 说明 | 取值建议 |
|------|------|---------|
| nlist | 聚类中心数 | sqrt(N)~4*sqrt(N) |
| nprobe | 查询时搜索的簇数 | 8-32(越大越精确) |
3.3.2 主流向量库对比#
| 向量库 | 部署方式 | 特色 | 适用场景 |
|---|
| Milvus | 分布式 | 支持亿级向量,生态完善 | 大规模生产 |
| PgVector | PostgreSQL扩展 | 与现有PostgreSQL集成 | 中小型/SQL环境 |
| Chroma | 本地嵌入式 | 轻量级,Python原生 | 开发/小型应用 |
| Qdrant | Rust实现 | 高性能,Filter支持好 | 生产高性能 |
3.3.3 向量数据库CRUD与元数据过滤#
import chromadb
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.create_collection(
name="telecom_kb",
metadata={"hnsw:space": "cosine"}
)
# Create
collection.add(
documents=["宽带无法上网的排查步骤:1.检查光猫指示灯",
"5G套餐变更流程:发送短信至10001"],
metadatas=[{"category": "宽带故障"}, {"category": "套餐业务"}],
ids=["doc1", "doc2"]
)
# Read(带元数据过滤)
results = collection.query(
query_texts=["宽带连不上"],
n_results=3,
where={"category": "宽带故障"} # 元数据过滤
)
# Update
collection.update(
ids=["doc1"],
documents=["更新后的排查步骤..."]
)
# Delete
collection.delete(ids=["doc2"])
3.4 文档清洗与切分策略#
3.4.1 文档解析#
# PDF解析(含表格)
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("资费手册.pdf")
pages = loader.load()
# Word文档
from langchain_community.document_loaders import Docx2txtLoader
loader = Docx2txtLoader("运维手册.docx")
# Markdown
from langchain_community.document_loaders import UnstructuredMarkdownLoader
# HTML
from langchain_community.document_loaders import WebBaseLoader
3.4.2 清洗规则#
import re
def clean_text(text):
# 去除多余空白
text = re.sub(r'\s+', ' ', text)
# 去除特殊字符
text = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', text)
# 标准化标点
text = text.replace(',', ',').replace('。', '.')
return text.strip()
3.4.3 切分策略#
from langchain_text_splitters import (
RecursiveCharacterTextSplitter,
MarkdownHeaderTextSplitter,
CharacterTextSplitter
)
# 1. 固定长度切分
splitter = CharacterTextSplitter(
chunk_size=500, # 每块500字符
chunk_overlap=50, # 重叠50字符(避免信息断裂)
separator="\n\n"
)
# 2. 递归字符切分(推荐)
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", ",", " ", ""] # 优先按段落→句号→逗号
)
# 3. 按Markdown标题结构切分
headers_to_split = [
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]
splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split)
电信场景:套餐表格如何保留完整列关系
# 表格切分需要特殊处理,不能按行分割
# 方案1:整表作为一个chunk(如果不太大)
# 方案2:每行转为"套餐名|月费|流量|通话"的自然语言描述
def table_to_text(table):
"""将表格转为文本,保持列关系"""
rows = []
for row in table.rows[1:]: # 跳过表头
cells = [cell.text for cell in row.cells]
text = f"套餐:{cells[0]}, 月费:{cells[1]}元, 流量:{cells[2]}GB, 通话:{cells[3]}分钟"
rows.append(text)
return "\n".join(rows)
3.5 召回与重排#
3.5.1 混合检索:向量召回 + BM25#
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import Chroma
# 向量检索(语义匹配)
vector_results = vectorstore.similarity_search(query, k=10)
# BM25检索(关键词匹配)
bm25_retriever = BM25Retriever.from_documents(docs)
bm25_results = bm25_retriever.invoke(query)
# 混合:合并去重,取并集
all_results = list(set(vector_results + bm25_results))
| 检索方式 | 优势 | 劣势 |
|---|
| 向量召回 | 语义匹配,理解同义词 | 精确关键词可能遗漏 |
| BM25 | 精确关键词匹配 | 无法理解语义 |
| 混合检索 | 兼顾语义和精确匹配 | 需融合排序 |
3.5.2 重排模型(Reranker)#
from langchain_cohere import CohereRerank
# 召回后重排
retriever = vectorstore.as_retriever(search_kwargs={"k": 20}) # 先召回20条
reranker = CohereRerank(top_n=5) # 重排后取TOP5
# 重排流程:召回20条 → Reranker打分 → 取分数最高的5条
重排的效果:召回阶段追求高召回率(多捞),重排阶段追求高精度(精选)。
3.6 知识库问答链路与幻觉控制#
3.6.1 完整RAG链路#
用户提问
↓
Query改写(扩展/纠错/多查询)
↓
检索(向量+BM25混合检索)
↓
重排(Cross-Encoder精排)
↓
上下文压缩(超出长度时摘要)
↓
生成(LLM基于检索内容回答)
↓
引用溯源(标注来源文件:章节)
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
prompt_template = """
基于以下已知信息回答用户问题。
已知信息:
{context}
问题:{question}
要求:
1. 只基于已知信息回答,不要编造
2. 如果已知信息中没有答案,请回答"根据知识库,暂无相关信息"
3. 回答时标注信息来源
回答:
"""
prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={"prompt": prompt},
return_source_documents=True
)
result = qa_chain.invoke({"query": "宽带无法上网怎么排查?"})
print(result["result"])
for doc in result["source_documents"]:
print(f"来源: {doc.metadata.get('source', 'N/A')}")
3.6.2 幻觉控制策略#
| 策略 | 说明 | 实现 |
|---|
| 系统提示词约束 | 强制"未找到时拒绝回答" | Prompt中加入"不要编造" |
| Self-Check | 生成后自我验证 | LLM检查答案是否在上下文中 |
| 事实核查模块 | 外部知识验证 | 调用外部API核对事实 |
| 引用溯源 | 要求标注来源 | Prompt中要求返回[文件:章节] |
3.6.3 评估指标#
| 指标 | 说明 | 公式 |
|---|
| Hit Rate | 正确文档在召回结果中的比例 | 命中次数/总查询数 |
| MRR | 平均倒数排名 | 平均(1/正确文档排名) |
| Faithfulness | 答案是否忠于检索内容 | 可由LLM评判 |
考试要点#
- 理解RAG与微调的本质区别及组合策略
- 掌握Embedding向量化原理和主流模型选型
- 理解ANN检索算法:HNSW、IVF、PQ的原理和参数
- 能对比Milvus/PgVector/Chroma/Qdrant选择向量库
- 掌握向量数据库CRUD操作和元数据过滤
- 理解文档切分策略:固定长度、递归字符、语义切分、Markdown标题
- 掌握电信场景中表格数据保留列关系的处理方法
- 理解混合检索(向量+BM25)和重排模型的作用
- 掌握RAG完整链路:Query改写→检索→重排→压缩→生成→溯源
- 理解幻觉控制策略和评估指标(Hit Rate、MRR、Faithfulness)
AI生成
第四天 Dify进阶Agent系统开发#
4.1 Dify平台核心界面与环境配置#
4.1.1 Docker-Compose方式部署Dify#
# 1. 克隆Dify仓库
git clone https://github.com/langgenius/dify.git
cd dify/docker
# 2. 复制环境变量模板
cp .env.example .env
# 3. 修改.env关键配置
# EXPOSE_PORT=8080 # Dify访问端口
# 修改数据库密码等
# 4. 启动(含PostgreSQL、Redis、Weaviate)
docker-compose up -d
# 5. 访问 http://localhost:8080
# 首次访问需创建管理员账号
Docker-Compose包含的服务:
| 服务 | 说明 | 端口 |
|---|
| dify-api | API服务 | 5001 |
| dify-web | Web前端 | 8080 |
| postgres | PostgreSQL数据库 | 5432 |
| redis | Redis缓存 | 6379 |
| weaviate | 向量数据库 | 8080(内部) |
| sandbox | 代码沙箱 | - |
| worker | 异步任务处理 | - |
4.1.2 模型供应商配置#
路径:设置 → 模型供应商
支持模型供应商:
├── Ollama(本地模型)
│ └── 配置:Base URL = http://host.docker.internal:11434
├── OpenAI(GPT系列)
│ └── 配置:API Key
├── 通义千问(Qwen)
│ └── 配置:阿里云API Key
├── DeepSeek
│ └── 配置:DeepSeek API Key
├── Azure OpenAI
│ └── 配置:Endpoint + Key + Deployment Name
└── 更多...
4.1.3 工作区管理、成员权限、日志审计#
| 功能 | 说明 |
|---|
| 工作区 | 隔离不同团队/项目的应用和知识库 |
| 成员权限 | Owner/Admin/Editor/Viewer四级权限 |
| 日志审计 | 记录所有API调用、成员操作日志 |
4.2 Dify基础组件与Chat APP搭建#
4.2.1 应用类型对比#
| 类型 | 说明 | 适用场景 |
|---|
| Chat APP | 对话型应用,支持多轮对话 | 客服、问答助手 |
| Workflow | 工作流,固定流程处理 | 批量处理、审批流 |
| Agent | 自主决策型,可调用工具 | 复杂任务、工单处理 |
4.2.2 创建Chat应用#
步骤:
1. 创建应用 → 选择"聊天助手"
2. 编排Prompt:
- 填写系统提示词(角色设定+约束)
- 设置变量(如{{user_name}})
- 选择模型和参数(temperature、max_tokens)
3. 添加知识库(如已有)
4. 发布 → 获得Web链接/API密钥
5. 测试对话
4.2.3 发布与测试#
| 发布方式 | 说明 | 适用 |
|---|
| Web界面 | Dify自带聊天界面 | 快速测试 |
| API调用 | RESTful API + Bearer Token | 集成到业务系统 |
| 嵌入iframe | 网页内嵌聊天窗口 | 官网客服 |
4.3 Workflow基础与流程设计#
4.3.1 节点类型#
| 节点 | 功能 | 示例 |
|---|
| 代码节点 | 执行Python/JS代码 | 数据格式转换 |
| 条件判断 | IF/ELSE分支 | 判断告警级别 |
| 模板转换 | Jinja2模板渲染 | 生成报告 |
| 知识库检索 | RAG检索 | 查故障处理方案 |
| HTTP请求 | 调用外部API | 查询用户信息 |
| LLM | 大模型推理 | 分析、生成 |
| 循环/迭代 | 批量处理 | 逐条处理告警 |
4.3.2 变量传递与数据转换#
[开始节点]
↓ output: user_question
[LLM节点: 意图识别]
↓ output: intent_type
[条件判断]
├── 意图=查询 → [HTTP请求: 查询接口] → output: query_result
└── 意图=投诉 → [知识库检索] → output: kb_result
↓
[LLM节点: 生成回复]
↓ output: final_answer
[结束节点]
4.3.3 项目实战#
搭建"AI办公助手"工作流:
意图识别节点(LLM)
├── 会议纪要 → 会议纪要子流程
├── 邮件润色 → 邮件润色子流程
└── 公文撰写 → 公文撰写子流程
搭建"企业文本生成"工作流:
[输入: 关键词]
→ [LLM: 生成大纲]
→ [LLM: 逐段生成正文]
→ [LLM: 润色优化]
→ [输出: 完整文章]
4.4 Agent模式与工具绑定#
4.4.1 Agent模式配置#
| 配置项 | 说明 | 建议值 |
|---|
| 迭代次数 | Agent最大思考轮数 | 5-10 |
| 工具调用策略 | ReAct / Plan-and-Execute | ReAct通用 |
| 工具调用失败回退 | 失败后处理方式 | 重试2次→告知用户 |
4.4.2 可视化工具绑定#
内置工具:
├── 计算器
├── 网页搜索
├── Wikipedia
└── ...
自定义OpenAPI工具:
1. 在"工具"页面添加OpenAPI Schema
2. 定义API端点、参数、认证方式
3. 在Agent应用中绑定该工具
4. Agent自动决定何时调用
示例OpenAPI Schema(查询用户套餐):
openapi: 3.0.0
paths:
/api/user/package:
get:
summary: 查询用户套餐
parameters:
- name: phone
in: query
required: true
schema:
type: string
4.4.3 工具调用规则#
| 规则 | 说明 |
|---|
| 强制工具 | 每次必须调用指定工具 |
| 自动选择 | Agent自主决定是否调用 |
| 失败回退 | 工具调用失败时的处理策略 |
4.5 对话记忆、上下文管理与日志调试#
4.5.1 记忆管理#
| 类型 | 说明 | 适用 |
|---|
| 滑动窗口 | 保留最近N轮对话 | 通用 |
| Token窗口 | 按Token数截断 | 长对话 |
| 重要信息持久化 | 提取关键信息存储 | 客服场景 |
4.5.2 Agent运行日志#
日志内容包括:
- Agent思考链路(Thought → Action → Observation)
- Token消耗统计
- 工具调用记录和返回结果
- 执行耗时
通过日志可调试:
- 为什么Agent没调用某个工具?(检查工具描述)
- 为什么返回结果错误?(检查工具参数)
- Token消耗异常?(检查上下文长度)
4.6 电信场景实战与轻量化部署#
4.6.1 运营商智能客服Agent#
需求:用户通过对话查询欠费、流量余量、办理套餐变更
工具配置:
1. 查询欠费API → GET /api/billing/balance?phone=xxx
2. 查询流量API → GET /api/data/usage?phone=xxx
3. 套餐变更API → POST /api/package/change
Agent配置:
系统提示词: "你是电信客服助手..."
工具: [查询欠费, 查询流量, 套餐变更]
记忆: 滑动窗口10轮
4.6.2 简易工单处理Agent#
流程:
1. 用户描述问题
2. Agent提取关键字段(设备ID、故障类型、区域)
3. 调用工单创建API
4. 返回工单号和处理进度
提示词技巧:
- Few-shot示例:展示如何从描述中提取字段
- 输出格式约束:JSON格式输出
4.6.3 轻量化上线#
| 方式 | 说明 | 适用 |
|---|
| 嵌入式部署 | iframe嵌入现有系统 | 网页集成 |
| API部署 | RESTful API + 限流 | 系统集成 |
| 企微/钉钉 | Webhook对接 | 企微办公 |
考试要点#
- 掌握Docker-Compose部署Dify的流程和包含的服务
- 理解Chat APP、Workflow、Agent三种应用类型的区别
- 能创建Chat应用并配置Prompt、变量、模型
- 能设计Workflow流程(节点类型、变量传递、条件分支)
- 掌握Agent模式配置(迭代次数、工具策略、回退机制)
- 能配置自定义OpenAPI工具并绑定到Agent
- 理解对话记忆管理和上下文管理策略
- 能通过运行日志调试Agent问题
- 能搭建电信场景的智能客服和工单处理Agent
- 了解Dify的轻量化上线方式
AI生成
第五天 Vibe Coding工具使用#
5.1 Vibe Coding核心理念与能力认知#
5.1.1 什么是Vibe Coding#
Vibe Coding(氛围编程)是由 Andrej Karpathy(OpenAI联合创始人)于2025年2月提出的AI辅助编程范式。核心理念:开发者用自然语言描述需求,AI负责生成代码,开发者凭直觉和效果迭代。
| 传统编程 | Vibe Coding |
|---|
| 手写代码 | 自然语言描述需求 |
| 关注实现细节 | 关注"做什么"和"效果" |
| 逐行调试 | 看效果→调描述→再生成 |
| 需要深入语法 | 需要清晰表达需求 |
5.1.2 人机协作最佳实践#
编写高质量需求(做什么)
↓
AI生成代码(怎么做)
↓
人工审查优化(对不对/好不好)
↓
迭代修正(效果不行→调整需求→重新生成)
5.1.3 适用边界#
| 适用 | 不适用 |
|---|
| 原型开发 | 安全关键系统 |
| 脚本编写 | 高性能优化 |
| 重复性代码 | 精确算法实现 |
| 快速验证想法 | 大型系统核心架构 |
5.2 Claude Code部署#
5.2.1 桌面端与VSCode插件安装#
# 桌面端:从claude.ai/download下载安装
# VSCode插件:
# 1. 打开VSCode扩展商店
# 2. 搜索 "Claude Code"
# 3. 点击安装
# CLI部署
npm install -g @anthropic-ai/claude-code
# 配置环境变量
export ANTHROPIC_API_KEY="sk-ant-xxx"
# Windows PowerShell:
$env:ANTHROPIC_API_KEY="sk-ant-xxx"
5.2.2 国内模型配置#
# 使用DeepSeek替代Claude(修改base_url)
export ANTHROPIC_BASE_URL="https://api.deepseek.com/v1"
export ANTHROPIC_API_KEY="sk-deepseek-xxx"
# 使用通义千问
export ANTHROPIC_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
export ANTHROPIC_API_KEY="sk-qwen-xxx"
# 通过代理访问
export HTTPS_PROXY="http://127.0.0.1:10808"
5.2.3 验证部署#
# 执行第一个代码生成
claude "编写一个Python函数,查询手机号对应的用户套餐信息"
# Claude Code会:
# 1. 读取项目上下文(CLAUDE.md)
# 2. 理解需求
# 3. 生成代码
# 4. 可直接创建/修改文件
5.3 Claude Code基础配置与命令#
5.3.1 会话管理命令#
| 命令 | 功能 | 说明 |
|---|
/new | 新建会话 | 清空上下文开始新对话 |
/load | 加载历史会话 | 恢复之前的对话 |
/save | 保存当前会话 | 保存到本地 |
/history | 查看历史会话 | 列出所有保存的会话 |
/context | 上下文管理 | 查看当前上下文 |
/remember | 记忆管理 | 保存重要信息 |
5.3.2 配置项#
# 模型选择
claude --model claude-sonnet-4-20250514
# 温度、最大令牌
# 在CLAUDE.md或对话中设置
# 工作目录
cd /your/project && claude
# Claude Code会读取工作目录下的CLAUDE.md
5.3.3 上下文与记忆系统#
# 添加文件到上下文
/context add src/main.py
/context add src/utils.py
# 添加URL到上下文
/context add https://docs.example.com/api
# 记忆系统
/remember "本项目使用Python 3.11,数据库为PostgreSQL"
/remember "电信工单表名为work_orders,主键ticket_id"
# 查看记忆列表
/forget # 删除指定记忆
5.4 插件与技能体系#
5.4.1 官方插件#
| 插件 | 功能 |
|---|
| 代码解释器 | 执行Python代码并返回结果 |
| 测试生成 | 自动生成单元测试 |
| API文档生成 | 从代码生成API文档 |
5.4.2 自定义技能:skills.yaml#
# skills.yaml - 自定义技能定义
name: telecom-data-export
description: |
电信数据导出技能
当用户需要导出话单、工单、告警数据时使用
input_schema:
type: object
properties:
data_type:
type: string
enum: [call_records, work_orders, alarms]
description: 数据类型
format:
type: string
enum: [csv, xlsx, json]
description: 导出格式
date_range:
type: string
description: 日期范围,如2026-07-01~2026-07-31
required: [data_type, format]
output_schema:
type: object
properties:
file_path:
type: string
row_count:
type: integer
examples:
- input: {"data_type": "call_records", "format": "csv", "date_range": "2026-07-01~2026-07-31"}
output: {"file_path": "export/call_records_202607.csv", "row_count": 15234}
5.4.3 技能版本管理与热加载#
技能目录结构:
.claude/skills/
├── telecom-data-export/
│ ├── skills.yaml
│ └── scripts/
│ └── export.py
├── alarm-analysis/
│ ├── skills.yaml
│ └── scripts/
│ └── analyze.py
# 热加载:修改skills.yaml后,Claude Code自动重新加载
# 无需重启
5.5 Spec Driven开发流程#
5.5.1 完整流程#
需求分析 → PRD编写 → Spec编写 → Task拆解 → AI开发 → 验收测试
5.5.2 需求分析(电信场景:用户画像生成器)#
需求:根据用户的通话、流量、套餐使用数据,生成用户画像,用于精准营销。
5.5.3 PRD编写#
# 用户画像生成器 PRD
## 功能列表
1. 输入手机号,查询用户近3个月使用数据
2. 分析用户消费水平、流量偏好、通话习惯
3. 生成画像标签(如"大流量用户"、"价格敏感")
4. 输出画像JSON和可视化报告
## 用户故事
- 作为营销人员,我想查看用户画像,以便推荐合适套餐
- 作为客服,我想了解用户特征,以便个性化服务
## 非功能需求
- 响应时间 < 3秒
- 支持批量查询(100个手机号/次)
- 数据脱敏处理
5.5.4 Spec编写#
# 用户画像生成器 技术Spec
## 输入
- phone: string (手机号,11位)
- months: int (分析月数,默认3)
## 输出
{
"phone": "138****8000",
"profile": {
"data_preference": "high", // high/medium/low
"call_preference": "medium",
"price_sensitivity": "high",
"churn_risk": "low"
},
"tags": ["大流量用户", "价格敏感", "忠诚度高"],
"recommendation": "推荐30GB以上套餐"
}
## 异常处理
- 手机号不存在 → {"error": "USER_NOT_FOUND"}
- 数据不足 → {"error": "INSUFFICIENT_DATA"}
- 限流 → {"error": "RATE_LIMITED", "retry_after": 60}
## 依赖库
- requests(HTTP调用)
- pandas(数据分析)
5.5.5 Task拆解#
Task 1: 创建项目结构和配置文件
Task 2: 实现手机号查询API调用
Task 3: 实现数据分析逻辑(消费/流量/通话)
Task 4: 实现画像标签生成
Task 5: 实现JSON输出格式化
Task 6: 异常处理和边界情况
Task 7: 单元测试
Task 8: 批量查询接口
5.5.6 AI开发流程#
# 将Spec和Task作为Prompt输入Claude Code
claude "
请基于以下技术规格开发用户画像生成器:
[粘贴Spec内容]
开发任务清单:
[粘贴Task列表]
请逐个Task完成,每完成一个Task后运行测试验证。
"
考试要点#
- 理解Vibe Coding的核心理念:自然语言描述需求+AI生成+人类审查
- 掌握人机协作最佳实践和适用边界
- 能安装部署Claude Code(CLI + 环境变量配置)
- 能配置国内模型替代Claude(修改base_url)
- 掌握Claude Code常用命令:/new、/load、/save、/context、/remember
- 能编写skills.yaml定义自定义技能
- 理解技能热加载机制
- 掌握Spec Driven开发完整流程:需求→PRD→Spec→Task→AI开发→验收
- 能编写PRD(功能列表、用户故事、非功能需求)
- 能编写技术Spec(输入输出、异常处理、依赖库)
- 能将Spec拆分为可执行的Task列表
AI生成
第六天 大模型开发工具链实战(LangChain)#
6.1 LangChain核心生态与LCEL#
6.1.1 核心组件#
| 组件 | 说明 | 常用类 |
|---|
| Model I/O | 模型输入输出 | ChatOpenAI, PromptTemplate, StrOutputParser |
| Retrieval | 检索增强 | VectorStoreRetriever, TextSplitter |
| Chains | 链式调用 | LCEL管道, SequentialChain |
| Agents | 智能体 | create_tool_calling_agent, AgentExecutor |
| Callbacks | 回调追踪 | CallbackHandler, LangSmith |
6.1.2 LCEL表达式语法#
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 管道运算符 | 连接组件
chain = prompt | llm | StrOutputParser()
# RunnableParallel: 并行执行
parallel = RunnableParallel(
summary=summary_chain,
keywords=keyword_chain,
original=RunnablePassthrough() # 原样传递
)
# RunnablePassthrough: 透传输入
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
6.1.3 回调机制#
from langchain.callbacks import StdOutCallbackHandler
# 记录执行日志
handler = StdOutCallbackHandler()
chain.invoke("查询用户信息", config={"callbacks": [handler]})
# LangSmith追踪(生产环境推荐)
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls-xxx"
# 所有链调用自动上报到LangSmith可视化平台
6.2 多模型集成与切换策略#
6.2.1 ChatModel统一接口#
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_community.chat_models import ChatOllama
# 所有模型统一接口
models = {
"gpt4": ChatOpenAI(model="gpt-4o"),
"claude": ChatAnthropic(model="claude-sonnet-4-20250514"),
"local": ChatOllama(model="qwen2.5:7b", base_url="http://localhost:11434"),
}
# 统一调用
for name, llm in models.items():
result = llm.invoke("什么是5G?")
print(f"[{name}] {result.content[:50]}...")
6.2.2 模型路由:按成本/延迟/复杂度选择#
class ModelRouter:
"""根据任务复杂度动态选择模型"""
def __init__(self):
self.fast_model = ChatOpenAI(model="gpt-4o-mini") # 便宜快速
self.smart_model = ChatOpenAI(model="gpt-4o") # 贵但智能
def route(self, task_type: str):
if task_type in ["分类", "提取", "格式化"]:
return self.fast_model
elif task_type in ["分析", "推理", "生成"]:
return self.smart_model
else:
return self.fast_model # 默认用小模型
router = ModelRouter()
llm = router.route("分类")
result = llm.invoke("将此工单分类:宽带频繁掉线")
6.2.3 LoRA微调模型与基础模型切换#
# 本地部署时,可根据任务动态切换基础模型和LoRA适配器
# 使用vLLM支持的热加载功能
# 基础模型处理通用任务,LoRA模型处理电信专业任务
6.3 自定义工具开发与Schema校验#
from langchain.tools import tool
from pydantic import BaseModel, Field
# 方式1: 简单工具
@tool
def query_data_balance(phone: str) -> str:
"""查询用户流量余额
Args:
phone: 手机号,11位数字
Returns:
流量余额信息
"""
# 模拟查询
return f"手机号{phone}剩余流量:15.2GB"
# 方式2: 使用Pydantic精细化校验入参
class PackageQueryInput(BaseModel):
phone: str = Field(
pattern=r"^1[3-9]\d{9}$",
description="手机号,11位数字"
)
month: str = Field(
default="2026-07",
description="查询月份,格式YYYY-MM"
)
@tool(args_schema=PackageQueryInput)
def query_package_detail(phone: str, month: str) -> dict:
"""查询用户套餐使用详情"""
return {
"phone": phone,
"month": month,
"package": "5G畅享99",
"data_used": "28.5GB",
"data_total": "30GB",
"calls_used": "456分钟",
"calls_total": "500分钟"
}
6.3.2 异常处理与错误返回规范#
@tool
def create_trouble_ticket(device_id: str, description: str) -> dict:
"""创建运维工单
Returns:
成功: {"status": "success", "ticket_id": "TKT-xxx"}
失败: {"status": "error", "message": "失败原因"}
"""
try:
if not device_id:
return {"status": "error", "message": "设备ID不能为空"}
ticket_id = f"TKT-{device_id}-001"
return {"status": "success", "ticket_id": ticket_id}
except Exception as e:
return {"status": "error", "message": str(e)}
6.4 工具链编排与链式调用#
6.4.1 顺序链与路由链#
from langchain.chains import LLMChain
# 顺序链:检索 → 生成 → 格式化
retrieval_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 路由链:根据输入类型选择不同处理链
def route_chain(info):
if "宽带" in info["topic"]:
return broadband_chain
elif "话费" in info["topic"]:
return billing_chain
else:
return general_chain
from langchain_core.runnables import RunnableLambda
router_chain = (
{"topic": RunnablePassthrough()}
| RunnableLambda(route_chain)
)
6.4.2 条件分支与并行执行#
# LCEL实现条件分支
from langchain_core.runnables import RunnableBranch
branch = RunnableBranch(
(lambda x: "紧急" in x["input"], urgent_handler),
(lambda x: "普通" in x["input"], normal_handler),
default_handler
)
# 并行执行
parallel = RunnableParallel(
analysis=analysis_chain,
summary=summary_chain,
keywords=keyword_chain
)
result = parallel.invoke({"input": "分析此告警"})
6.5 自定义持久化记忆#
6.5.1 Memory类型#
| 类型 | 说明 | 适用场景 |
|---|
| ConversationBufferMemory | 保存所有对话 | 短对话 |
| ConversationSummaryMemory | 摘要式记忆 | 长对话 |
| ConversationBufferWindowMemory | 滑动窗口 | 控制上下文长度 |
| 自定义Memory | 对接数据库 | 用户级记忆隔离 |
6.5.2 自定义Memory对接MySQL/Redis#
from langchain.memory import BaseChatMemory
import redis
import json
class TelecomUserMemory(BaseChatMemory):
"""基于手机号的用户记忆隔离"""
def __init__(self, phone: str, redis_client=None):
super().__init__()
self.phone = phone
self.redis = redis_client or redis.Redis(host='localhost', port=6379)
self.key = f"chat_memory:{phone}"
def save_context(self, inputs, outputs):
"""保存对话到Redis(设置7天TTL)"""
history = self.load_memory_variables({})
messages = history.get("history", [])
messages.extend([
{"role": "user", "content": str(inputs)},
{"role": "assistant", "content": str(outputs)}
])
# 超过50条时做摘要压缩
if len(messages) > 50:
messages = self._compress(messages)
self.redis.setex(self.key, 7*86400, json.dumps(messages))
def load_memory_variables(self, inputs):
"""加载用户历史记忆"""
data = self.redis.get(self.key)
if data:
return {"history": json.loads(data)}
return {"history": []}
def _compress(self, messages):
"""记忆压缩:保留最近10条 + 前面的摘要"""
old = messages[:-10]
recent = messages[-10:]
summary = f"之前对话摘要:用户咨询了{len(old)}条消息,主要关于套餐和故障问题。"
return [{"role": "system", "content": summary}] + recent
6.5.3 上下文溢出解决方案#
| 方案 | 说明 | 实现方式 |
|---|
| 摘要压缩 | 旧对话生成摘要 | LLM总结后替换 |
| 重要信息抽取 | 提取关键事实存储 | 结构化存储到数据库 |
| 窗口限制 | 只保留最近N轮 | 滑动窗口 |
| 分层记忆 | 短期+长期分离 | 短期Redis + 长期向量库 |
6.6 LangChain Agent进阶与电信Prompt工程#
6.6.1 Agent类型#
| 类型 | 说明 | 适用 |
|---|
| ZeroShotReact | 零样本推理+行动 | 通用简单任务 |
| OpenAI Functions | 使用Function Calling | OpenAI模型 |
| Plan-and-Execute | 先规划再执行 | 复杂多步任务 |
from langchain.agents import create_tool_calling_agent, AgentExecutor
# OpenAI Functions Agent(推荐)
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True, max_iterations=10)
# Plan-and-Execute(复杂任务)
from langchain.agents import create_plan_and_execute_agent
6.6.2 电信场景Prompt工程#
# 客服话术模板注入用户画像
CUSTOMER_SERVICE_PROMPT = """
你是电信客服助手。当前用户画像:
- 姓名:{user_name}
- 套餐:{package_name}
- 月均消费:{avg_spending}元
- 投诉历史:{complaint_count}次
用户提问:{question}
请基于用户画像提供个性化回答。
语气亲切,称呼用户姓名。高消费用户推荐升级套餐,低消费用户侧重性价比。
"""
# 工单分类Few-shot
TICKET_CLASSIFY_PROMPT = """
请将工单分类为以下类别之一:
- 宽带故障
- 话费争议
- 增值业务
- 网络覆盖
- 其他
示例:
工单:用户说家里WiFi频繁断线 → 宽带故障
工单:上月话费多了30元不知为何 → 话费争议
工单:想取消每月10元的来电显示 → 增值业务
工单:{ticket_content}
分类:
"""
# 诱导LLM输出结构化数据
STRUCTURED_OUTPUT_PROMPT = """
请以JSON格式输出分析结果,不要输出其他内容。
{
"device_id": "设备ID",
"alarm_level": "critical/warning/info",
"root_cause": "根因分析",
"suggestion": "处理建议",
"priority": 1-5
}
"""
考试要点#
- 掌握LangChain核心组件:Model I/O、Retrieval、Chains、Agents、Callbacks
- 理解LCEL语法:管道符、RunnableParallel、RunnablePassthrough
- 能用回调机制进行日志追踪和LangSmith集成
- 掌握多模型统一接口和模型路由策略
- 能用@tool装饰器开发自定义工具,使用Pydantic做Schema校验
- 理解顺序链、路由链、条件分支的实现方式
- 能自定义Memory对接MySQL/Redis实现用户级记忆隔离
- 理解记忆压缩和上下文溢出解决方案
- 掌握Agent类型选择和电信场景Prompt工程技巧
- 能设计Few-shot分类Prompt和结构化输出Prompt
AI生成
第七天 大模型开发工具链实战(LangGraph与DeepAgents)#
7.1 LangGraph核心定位与核心组件#
7.1.1 为什么需要LangGraph#
| 维度 | LangChain Agent | LangGraph |
|---|
| 执行模式 | 线性循环 | 图结构(DAG) |
| 状态管理 | 无显式状态 | 有状态Schema |
| 控制流 | 固定Reason-Act循环 | 自定义条件边、循环边 |
| 人机协同 | 不支持 | 内置中断/恢复 |
| 多Agent | 不原生支持 | 原生支持节点编排 |
7.1.2 核心概念#
from langgraph.graph import StateGraph, START, END
from typing import TypedDict
# 1. State: 共享状态Schema
class AgentState(TypedDict):
messages: list
current_step: str
result: str
# 2. Node: 节点(处理函数)
def agent_node(state: AgentState) -> dict:
# 处理逻辑
return {"result": "处理完成"}
# 3. Edge: 边(连接节点)
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)
graph.set_entry_point("agent")
graph.add_edge("agent", "tools")
graph.add_edge("tools", END)
# 4. 编译并执行
app = graph.compile()
result = app.invoke({"messages": [("user", "查询套餐")]})
7.1.3 状态Schema定义#
from pydantic import BaseModel
# 方式1: TypedDict(轻量)
class LightState(TypedDict):
query: str
result: str
# 方式2: Pydantic Model(带校验)
class StrictState(BaseModel):
phone: str
intent: str
confidence: float
response: str = ""
7.2 状态化工作流设计#
7.2.1 条件边#
def route_by_intent(state: AgentState) -> str:
"""根据意图路由到不同节点"""
intent = state.get("intent", "")
if intent == "宽带":
return "broadband_node"
elif intent == "话费":
return "billing_node"
else:
return "general_node"
graph.add_conditional_edges(
"classifier", # 源节点
route_by_intent, # 路由函数
{
"broadband_node": "broadband_diagnostic",
"billing_node": "billing_query",
"general_node": "general_handler"
}
)
7.2.2 循环边:自我纠错与重试#
def quality_check(state: AgentState) -> str:
"""质量检查,不合格则回到生成节点重试"""
if state.get("quality_score", 0) < 0.8:
state["retry_count"] = state.get("retry_count", 0) + 1
if state["retry_count"] <= 3:
return "regenerate" # 回到生成节点
return "pass" # 通过,继续向下
graph.add_conditional_edges(
"quality_checker",
quality_check,
{"regenerate": "generator", "pass": "output"}
)
7.2.3 人机协同节点#
from langgraph.checkpoint.memory import MemorySaver
# 在关键节点前暂停,等待人工输入
app = graph.compile(
checkpointer=MemorySaver(),
interrupt_before=["human_review"] # 在人工审核节点前暂停
)
# 第一次执行(到human_review前暂停)
config = {"configurable": {"thread_id": "task-001"}}
result = app.invoke({"query": "处理此告警"}, config=config)
# 人工输入后恢复
result = app.invoke(
{"human_feedback": "确认为光模块故障,执行更换"},
config=config # 同一thread_id恢复
)
7.2.4 电信场景案例:故障诊断流程#
[接收报障文本]
↓
[分类节点: 宽带/IPTV/话费]
↓ (条件边)
┌───┼───────┐
↓ ↓ ↓
[宽带 [IPTV [话费
诊断] 诊断] 处理]
↓
[宽带诊断子图]
├── 检查账号状态
├── 检查光猫在线
└── 循环ping测速(最多3次)
↓
[结果输出]
class FaultState(TypedDict):
raw_text: str # 原始报障文本
fault_type: str # 故障类型
account_status: str # 账号状态
modem_online: bool # 光猫在线
ping_results: list # 测速结果
retry_count: int # 重试次数
diagnosis: str # 诊断结论
solution: str # 解决方案
def ping_test(state: FaultState) -> dict:
"""ping测速节点,支持循环"""
retry = state.get("retry_count", 0)
if retry < 3:
# 执行ping测速
result = "延迟: 45ms, 丢包: 2%"
results = state.get("ping_results", []) + [result]
return {"ping_results": results, "retry_count": retry + 1}
return {"ping_results": state.get("ping_results", [])}
def check_ping_quality(state: FaultState) -> str:
"""判断ping结果质量"""
results = state.get("ping_results", [])
if not results:
return "retry" # 没结果,重试
last = results[-1]
if "丢包: 0%" in last:
return "pass" # 正常
elif state.get("retry_count", 0) >= 3:
return "fail" # 重试3次仍失败
return "retry" # 继续重试
# 构建子图
broadband_subgraph = StateGraph(FaultState)
broadband_subgraph.add_node("check_account", check_account_node)
broadband_subgraph.add_node("check_modem", check_modem_node)
broadband_subgraph.add_node("ping_test", ping_test)
broadband_subgraph.add_node("diagnose", diagnose_node)
broadband_subgraph.set_entry_point("check_account")
broadband_subgraph.add_edge("check_account", "check_modem")
broadband_subgraph.add_edge("check_modem", "ping_test")
broadband_subgraph.add_conditional_edges(
"ping_test", check_ping_quality,
{"retry": "ping_test", "pass": "diagnose", "fail": "diagnose"}
)
broadband_subgraph.add_edge("diagnose", END)
7.3 LangGraph的多智能体编排#
7.3.1 Supervisor模式#
┌───────────────┐
│ Supervisor │ ← 任务分解、结果聚合
│ Agent │
└──┬───┬───┬───┘
│ │ │
▼ ▼ ▼
[A1] [A2] [A3]
告警 故障 派单
分析 定位 Agent
class MultiAgentState(TypedDict):
task: str
subtasks: list
results: dict
final_report: str
def supervisor(state: MultiAgentState) -> dict:
"""主Agent:分解任务并分发"""
task = state["task"]
subtasks = [
{"agent": "alarm_analyst", "task": "分析告警内容"},
{"agent": "fault_locator", "task": "定位故障根因"},
{"agent": "dispatcher", "task": "生成派单建议"}
]
return {"subtasks": subtasks}
# 子Agent作为独立节点
def alarm_analyst(state: MultiAgentState) -> dict:
"""告警分析子Agent"""
result = llm.invoke(f"分析告警: {state['task']}")
return {"results": {"alarm_analysis": result.content}}
def fault_locator(state: MultiAgentState) -> dict:
"""故障定位子Agent"""
alarm_result = state["results"].get("alarm_analysis", "")
result = llm.invoke(f"基于告警分析结果定位故障: {alarm_result}")
return {"results": {"fault_location": result.content}}
7.3.2 上下文隔离与结果聚合#
# 每个子Agent有独立的状态空间
# 主Agent通过共享State聚合结果
def aggregate(state: MultiAgentState) -> dict:
"""聚合各子Agent结果"""
results = state["results"]
report = f"""
告警分析: {results.get('alarm_analysis', 'N/A')}
故障定位: {results.get('fault_location', 'N/A')}
派单建议: {results.get('dispatch', 'N/A')}
"""
return {"final_report": report}
7.4 LangGraph与LangChain融合#
# 将LangChain的Runnable链包装为LangGraph节点
from langchain_core.runnables import Runnable
def langchain_node(runnable: Runnable):
"""将LangChain Runnable包装为LangGraph节点"""
def node(state):
# 从state中提取输入
input_data = state.get("input", "")
result = runnable.invoke(input_data)
return {"output": result}
return node
# 在LangGraph中使用LangChain的Retriever和Memory
graph = StateGraph(AgentState)
graph.add_node("retrieve", langchain_node(retriever_chain))
graph.add_node("generate", langchain_node(generation_chain))
7.5 DeepAgents任务分解实战#
7.5.1 DeepAgents框架#
DeepAgents是层次化任务规划框架,将复杂任务自动分解为子任务并分配执行。
"解决用户信号差投诉"
↓ DeepAgents分解
├── 查基站覆盖 → 子Agent A
├── 查终端型号 → 子Agent B
├── 查历史投诉 → 子Agent C
└── 推荐方案 → 子Agent D(依赖A/B/C结果)
7.5.2 在LangGraph中实现Plan-and-Execute#
class PlanExecuteState(TypedDict):
task: str
plan: list # 执行计划
current_step: int # 当前步骤
step_results: dict # 各步骤结果
final_answer: str
def planner(state: PlanExecuteState) -> dict:
"""规划Agent:将任务分解为步骤"""
task = state["task"]
prompt = f"""将以下任务分解为3-5个可执行步骤:
任务:{task}
输出JSON数组格式。"""
result = llm.invoke(prompt)
# 解析计划
plan = parse_plan(result.content)
return {"plan": plan, "current_step": 0}
def executor(state: PlanExecuteState) -> dict:
"""执行Agent:执行当前步骤"""
plan = state["plan"]
step_idx = state["current_step"]
current = plan[step_idx]
# 动态选择工具执行
result = execute_step(current)
step_results = state.get("step_results", {})
step_results[current["name"]] = result
return {
"step_results": step_results,
"current_step": step_idx + 1
}
def should_continue(state: PlanExecuteState) -> str:
"""判断是否继续执行"""
if state["current_step"] < len(state["plan"]):
return "continue"
return "done"
# 构建Plan-Execute工作流
workflow = StateGraph(PlanExecuteState)
workflow.add_node("planner", planner)
workflow.add_node("executor", executor)
workflow.add_node("synthesizer", synthesize_result)
workflow.set_entry_point("planner")
workflow.add_edge("planner", "executor")
workflow.add_conditional_edges(
"executor", should_continue,
{"continue": "executor", "done": "synthesizer"}
)
workflow.add_edge("synthesizer", END)
plan_execute_app = workflow.compile()
# 执行
result = plan_execute_app.invoke({
"task": "解决用户信号差投诉:用户在朝阳区反馈5G信号弱",
"step_results": {}
})
print(result["final_answer"])
考试要点#
- 理解LangGraph相比LangChain Agent的优势(图结构、状态管理、控制流)
- 掌握StateGraph、Node、Edge、State四个核心概念
- 能定义状态Schema(TypedDict或Pydantic Model)
- 掌握条件边实现路由和循环边实现重试
- 理解人机协同节点(interrupt_before + 恢复机制)
- 能设计电信故障诊断流程(分类→子图→循环测速→诊断)
- 掌握Supervisor模式的多Agent编排
- 理解上下文隔离与结果聚合策略
- 能将LangChain组件包装为LangGraph节点
- 理解DeepAgents的任务分解和Plan-and-Execute模式
- 能在LangGraph中实现Plan-Execute工作流
AI生成
第八天 MCP与Skills开发实战#
8.1 MCP协议原理#
8.1.1 MCP目标与设计理念#
MCP(Model Context Protocol)由Anthropic于2024年11月开源,目标是统一大模型与外部世界的交互方式,类似"AI的USB-C接口"。
| 特性 | 说明 |
|---|
| 协议基础 | JSON-RPC 2.0 |
| 传输层 | stdio(本地标准流)/ SSE(远程流式传输) |
| 架构 | Client-Server模型 |
| 核心价值 | 一次开发处处可用,解决N×M集成问题 |
8.1.2 与API Gateway的区别#
| 维度 | API Gateway | MCP |
|---|
| 服务对象 | 应用间通信 | 大模型与工具间通信 |
| 接口描述 | OpenAPI/Swagger | JSON Schema自动生成 |
| 发现机制 | 手动配置 | 自动发现 |
| 语义理解 | 不含语义 | 带工具描述供LLM理解 |
8.1.3 三大核心概念#
| 概念 | 说明 | 类比 |
|---|
| Resources | 可读取的数据源 | 文件系统 |
| Tools | 可调用的函数 | API接口 |
| Prompts | 预定义提示模板 | 代码模板 |
8.2 Skill.md开发规范#
8.2.1 Skill.md文件结构#
---
name: query-balance
description: 查询用户余额和套餐使用情况
version: 1.0.0
author: Telecom Team
---
# 查询余额技能
## 使用场景
当用户询问话费余额、流量余量、套餐使用情况时使用
## 输入参数
- phone: 手机号(必填)
- item: 查询项(balance/data/calls,默认balance)
## 输出格式
{
"phone": "138****8000",
"balance": 45.6,
"package": "5G畅享99",
"data_remaining": "15.2GB"
}
## 示例
输入: {"phone": "13800138000", "item": "balance"}
输出: {"phone": "138****8000", "balance": 45.6, "currency": "CNY"}
8.2.2 Agent自动发现并调用Skill#
# Skill放置在.claude/skills/目录下
# Agent通过description匹配自动发现
目录结构:
.claude/skills/
├── query-balance/
│ └── SKILL.md
├── create-ticket/
│ └── SKILL.md
└── diagnose-fault/
├── SKILL.md
└── scripts/
└── diagnose.py
# Claude Code/Agent自动扫描skills目录
# 根据用户意图匹配description
# 加载对应SKILL.md并按流程执行
8.2.3 技能版本管理与热加载#
| 特性 | 说明 |
|---|
| 版本号 | 在frontmatter中定义version |
| 热加载 | 修改SKILL.md后Agent自动重新加载 |
| 技能市场 | 团队共享skills文件夹,Git版本控制 |
8.3 MCP插件和CLI开发实战#
8.3.1 使用Python SDK搭建MCP Server#
from fastmcp import FastMCP
mcp = FastMCP("电信客服服务")
# 实现Tools
@mcp.tool()
def query_balance(phone: str) -> dict:
"""查询用户余额
Args:
phone: 手机号
Returns:
余额信息
"""
return {"phone": phone, "balance": 45.6, "package": "5G畅享99"}
@mcp.tool()
def order_data_package(phone: str, package_id: str) -> dict:
"""订购流量包
Args:
phone: 手机号
package_id: 流量包ID(如: 10GB-30元)
"""
return {"status": "success", "phone": phone, "package": package_id}
@mcp.tool()
def send_notification(channel: str, message: str) -> dict:
"""发送通知"""
return {"status": "sent", "channel": channel}
# 实现Resources:暴露知识文档
@mcp.resource("docs://troubleshooting/{topic}")
def get_troubleshooting_doc(topic: str) -> str:
"""获取故障排除文档"""
docs = {
"broadband": "宽带故障排查:1.检查光猫 2.检查网线 3.重启设备",
"5g_signal": "5G信号问题:1.检查覆盖 2.检查SIM卡 3.网络设置",
}
return docs.get(topic, "暂无此文档")
# 启动Server
if __name__ == "__main__":
mcp.run(transport="stdio")
8.3.2 CLI工具调试#
# mcp-cli: 命令行调试MCP Server
# 1. 查看MCP Server提供的能力
mcp-cli inspect python telecom_server.py
# 输出: Tools: [query_balance, order_data_package, send_notification]
# Resources: [docs://troubleshooting/{topic}]
# 2. 直接调用某个工具
mcp-cli call query_balance --phone 13800138000
# 输出: {"phone": "13800138000", "balance": 45.6, "package": "5G畅享99"}
# 3. 读取资源
mcp-cli read docs://troubleshooting/broadband
8.4 企业级MCP与Skills开发#
8.4.1 多租户与权限控制#
from fastmcp import FastMCP
from functools import wraps
mcp = FastMCP("企业电信服务")
# API Key认证中间件
TENANT_KEYS = {
"tenant_a": "key-aaa-123",
"tenant_b": "key-bbb-456",
}
def require_auth(tenant: str, api_key: str) -> bool:
return TENANT_KEYS.get(tenant) == api_key
@mcp.tool()
def query_user_balance(phone: str, tenant: str, api_key: str) -> dict:
"""查询用户余额(需租户认证)"""
if not require_auth(tenant, api_key):
return {"error": "认证失败", "code": "AUTH_FAILED"}
# 不同租户数据隔离
return {"phone": phone, "balance": 45.6, "tenant": tenant}
8.4.2 日志监控与性能指标#
import time
import logging
logger = logging.getLogger("mcp_server")
def monitor_tool(func):
"""工具调用监控装饰器"""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
try:
result = func(*args, **kwargs)
duration = time.time() - start
logger.info(f"工具{func.__name__}执行成功, 耗时{duration:.3f}s")
return result
except Exception as e:
duration = time.time() - start
logger.error(f"工具{func.__name__}执行失败, 耗时{duration:.3f}s, 错误: {e}")
raise
return wrapper
@mcp.tool()
@monitor_tool
def query_balance(phone: str) -> dict:
return {"balance": 45.6}
8.4.3 微服务架构下的MCP Server部署#
# Dockerfile
FROM python:3.11-slim
COPY . /app
WORKDIR /app
RUN pip install fastmcp
EXPOSE 8080
CMD ["python", "server.py", "--transport", "http", "--port", "8080"]
# docker-compose.yml
version: '3'
services:
mcp-server:
build: .
ports:
- "8080:8080"
environment:
- DB_HOST=postgres
- REDIS_HOST=redis
depends_on:
- postgres
- redis
postgres:
image: postgres:16
environment:
POSTGRES_DB: telecom
redis:
image: redis:7
8.5 电信场景实战#
8.5.1 智能客服智能体#
开发MCP Server封装"查询余额"、"流量包订购"接口
+
编写对应的Skill.md
+
在Dify/LangGraph中接入MCP Server
用户: "帮我查下话费余额"
→ Agent匹配query-balance技能
→ 调用MCP Tool: query_balance
→ 返回: "您的余额为45.6元,套餐5G畅享99"
8.5.2 智能工单运维系统#
# MCP Server对接工单数据库
@mcp.tool()
def query_ticket_status(ticket_id: str) -> dict:
"""查询工单状态"""
return {"ticket_id": ticket_id, "status": "处理中", "handler": "张三"}
@mcp.tool()
def transfer_ticket(ticket_id: str, to_team: str) -> dict:
"""转派工单"""
return {"ticket_id": ticket_id, "transferred_to": to_team}
@mcp.tool()
def close_ticket(ticket_id: str, resolution: str) -> dict:
"""关闭工单"""
return {"ticket_id": ticket_id, "status": "closed", "resolution": resolution}
# Skill定义
# SKILL.md:
# 1. 用户说"我的工单处理到哪了" → 调用query_ticket_status
# 2. 用户说"转给宽带组" → 调用transfer_ticket
# 3. 用户说"已解决,可以关闭" → 调用close_ticket
8.5.3 用户画像分析与日志异常分析#
# 画像分析MCP工具
@mcp.tool()
def aggregate_user_profile(phone: str) -> dict:
"""聚合用户画像:上网行为+资费敏感度→360度画像"""
return {
"phone": phone,
"profile": {
"data_preference": "high",
"price_sensitivity": "medium",
"churn_risk": "low",
"tags": ["大流量用户", "稳定客户"]
}
}
# 日志分析MCP Server
@mcp.tool()
def query_error_rate(service: str, hours: int = 1) -> dict:
"""查询错误率(对接ELK/CLS)"""
return {"service": service, "error_rate": 2.3, "trend": "上升"}
@mcp.tool()
def get_error_stack(trace_id: str) -> str:
"""获取异常堆栈"""
return f"TraceID: {trace_id}\nNullPointerException at com.telecom.Service..."
@mcp.tool()
def analyze_root_cause(error_log: str) -> str:
"""Agent根据日志自动分析根因"""
root_cause = llm.invoke(f"分析以下日志的根因: {error_log}")
return root_cause.content
考试要点#
- 理解MCP协议的核心设计理念和与API Gateway的区别
- 掌握MCP三大核心概念:Resources、Tools、Prompts
- 能编写SKILL.md(name、description、input/output_schema、examples)
- 理解Agent自动发现Skill的机制(目录扫描+description匹配)
- 能用Python SDK(FastMCP)搭建MCP Server(Tools、Resources)
- 能使用mcp-cli调试MCP Server(inspect、call、read)
- 掌握企业级MCP开发:多租户认证、日志监控、Docker部署
- 能构建电信智能客服系统(MCP封装API + Skill定义 + Agent接入)
- 能实现智能工单运维系统(工单CRUD的MCP+Skill)
- 能开发用户画像分析和日志异常分析Agent
AI生成
第九天 企业级数字员工开发基础实操#
9.1 电信场景需求分析与方案设计#
9.1.1 案例:宽带装维助手#
核心需求:
- 查用户宽带账号信息
- 执行测速
- 查历史故障记录
- 给出排障建议
9.1.2 能力拆解#
| 能力 | 实现方式 | 说明 |
|---|
| 查宽带账号 | API Tool | 调用CRM系统API |
| 执行测速 | API Tool (MCP) | 封装测速接口 |
| 查历史故障 | RAG | 检索故障知识库 |
| 排障建议 | RAG + LLM | 知识库检索+推理生成 |
9.1.3 技术方案选型#
| 组件 | 选型 | 理由 |
|---|
| 模型 | Qwen2.5-7B(本地Ollama) | 数据安全+成本低 |
| 框架 | LangChain + LangGraph | Agent编排+流程控制 |
| 向量库 | Chroma | 轻量级,嵌入方便 |
| 工具协议 | MCP | 标准化接口封装 |
9.1.4 架构图设计与接口契约#
┌────────────────────────────────────────────┐
│ 宽带装维助手架构 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │ LangGraph│ │ MCP │ │ Chroma │ │
│ │ 编排引擎 │→│ 工具服务 │ │ 故障库 │ │
│ │ │ │ │ │ │ │
│ │ State管理│ │·测速API │ │·故障案例│ │
│ │ 节点路由 │ │·账号查询 │ │·处理手册│ │
│ │ │ │·工单创建 │ │ │ │
│ └──────────┘ └──────────┘ └─────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Qwen2.5 │ ← 本地Ollama推理 │
│ │ 7B │ │
│ └──────────┘ │
└────────────────────────────────────────────┘
接口契约:
- query_account(phone) → {account_id, package, speed}
- run_speed_test(account_id) → {download, upload, latency, jitter}
- search_fault_kb(symptom) → [fault_cases]
- create_ticket(device_id, issue) → {ticket_id}
9.2 开发环境整合#
9.2.1 环境配置清单#
| 组件 | 版本 | 配置方式 |
|---|
| VSCode + Cline | 最新版 | 安装Cline插件 |
| Ollama + Qwen2.5:7b | 0.3+ | ollama pull qwen2.5:7b |
| Chroma | 0.5+ | pip install chromadb |
| MCP Server | Python 3.11+ | pip install fastmcp |
| LangGraph | 0.2+ | pip install langgraph |
9.2.2 联调验证#
# 验证所有服务连通性
def verify_environment():
# 1. Ollama
import requests
r = requests.get("http://localhost:11434/api/tags")
assert r.status_code == 200, "Ollama未启动"
# 2. Chroma
import chromadb
client = chromadb.PersistentClient(path="./chroma_db")
assert client.heartbeat() > 0, "Chroma异常"
# 3. MCP Server
from mcp import ClientSession
# 测试MCP连接...
print("所有服务连通性验证通过")
9.3 Agent Skills开发#
9.3.1 将测速API封装为Skill#
# MCP Server中的测速工具
@mcp.tool()
async def run_speed_test(account_id: str) -> dict:
"""执行宽带测速
Args:
account_id: 宽带账号ID
Returns:
测速结果
"""
# 调用测速API
return {
"account_id": account_id,
"download_mbps": 95.6,
"upload_mbps": 28.3,
"latency_ms": 12,
"jitter_ms": 2.1,
"rating": "良好" # 优秀/良好/一般/差
}
9.3.2 将账号查询API封装为Skill#
@mcp.tool()
def query_broadband_account(phone: str) -> dict:
"""查询宽带账号信息
Args:
phone: 用户手机号
"""
return {
"account_id": "KD20260001",
"phone": phone,
"package": "千兆宽带200M",
"address": "北京市朝阳区XX小区",
"install_date": "2024-03-15",
"status": "正常"
}
9.3.3 编写RAG检索技能#
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings # 或本地Embedding
# 初始化故障知识库
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings,
collection_name="fault_kb"
)
def search_fault_kb(symptom: str, k: int = 3) -> list:
"""检索故障知识库
Args:
symptom: 故障症状描述
k: 返回结果数
"""
results = vectorstore.similarity_search(symptom, k=k)
return [
{"content": doc.page_content, "source": doc.metadata.get("source")}
for doc in results
]
9.4 单智能体核心开发#
9.4.1 使用LangGraph定义State#
from typing import TypedDict
class BroadbandAssistantState(TypedDict):
phone: str # 用户手机号
account_info: dict # 宽带账号信息
speed_test_result: dict # 测速结果
fault_history: list # 历史故障
kb_results: list # 知识库检索结果
intent: str # 用户意图
response: str # 最终回复
9.4.2 主控节点与条件边路由#
from langgraph.graph import StateGraph, END
def intent_recognition(state: BroadbandAssistantState) -> dict:
"""意图识别节点"""
user_input = state.get("phone", "") # 实际应获取用户输入
# LLM判断意图
prompt = f"""判断用户意图:query_account/speed_test/troubleshoot
用户输入:{user_input}"""
result = llm.invoke(prompt)
return {"intent": result.content.strip()}
def route_by_intent(state: BroadbandAssistantState) -> str:
intent = state.get("intent", "")
if intent == "query_account":
return "account_node"
elif intent == "speed_test":
return "speed_node"
elif intent == "troubleshoot":
return "fault_node"
return "general_node"
# 构建工作流
workflow = StateGraph(BroadbandAssistantState)
workflow.add_node("intent", intent_recognition)
workflow.add_node("account_node", query_account_node)
workflow.add_node("speed_node", speed_test_node)
workflow.add_node("fault_node", fault_diagnosis_node)
workflow.add_node("format_output", format_output_node)
workflow.set_entry_point("intent")
workflow.add_conditional_edges(
"intent", route_by_intent,
{
"account_node": "account_node",
"speed_node": "speed_node",
"fault_node": "fault_node",
"general_node": "format_output"
}
)
# 所有业务节点执行后统一到输出格式化
for node in ["account_node", "speed_node", "fault_node"]:
workflow.add_edge(node, "format_output")
workflow.add_edge("format_output", END)
app = workflow.compile()
9.5 功能测试与问题调试#
9.5.1 测试策略#
| 测试类型 | 说明 | 示例 |
|---|
| 单元测试 | 单独测试每个节点 | 测试query_account返回是否正确 |
| 集成测试 | 模拟完整用户交互 | “我的宽带很慢,帮我测速” |
| 链路追踪 | 分析调用链耗时 | LangSmith可视化追踪 |
9.5.2 常见问题与修复#
| 问题 | 原因 | 修复方法 |
|---|
| JSON解析错误 | LLM输出格式不标准 | 在Prompt中强调"只输出JSON",加正则提取 |
| 工具超时 | MCP Server响应慢 | 增加timeout,加重试机制 |
| 上下文溢出 | 状态过多撑爆上下文 | 压缩历史信息,只保留关键字段 |
| 意图误判 | 分类不清晰 | 优化Few-shot示例,增加边界case |
考试要点#
- 能进行电信场景需求分析和能力拆解(RAG vs API Tool)
- 能制定技术方案选型(模型/框架/向量库/工具协议)
- 能设计架构图和接口契约
- 能搭建完整的开发环境(Ollama/Chroma/MCP/LangGraph)
- 能将API封装为MCP Skill和RAG检索技能
- 能用LangGraph定义State、主控节点和条件边路由
- 能编写完整的单智能体工作流
- 掌握功能测试方法(单元/集成/链路追踪)
- 能定位和修复常见问题(JSON解析/超时/上下文溢出/意图误判)
AI生成
第十天 进阶实操-多智能体数字员工电信运维场景#
10.1 电信智能运维场景需求分析#
10.1.1 场景描述#
场景:服务器CPU持续飙高,需根因定位并派单
用户故事:
运维人员收到告警 → 系统自动分析 → 输出可能原因 → 推荐修复动作 → 生成派单建议
10.1.2 非功能需求#
| 需求 | 指标 |
|---|
| 响应时间 | < 5秒(从告警到分析结果) |
| 可解释性 | 输出包含证据链和推理过程 |
| 人工介入接口 | 关键决策可暂停等待人工确认 |
10.2 多智能体架构设计#
10.2.1 Agent角色#
| Agent | 职责 | 输入 | 输出 |
|---|
| Supervisor(主智能体) | 任务规划与结果聚合 | 告警信息 | 执行计划+最终报告 |
| 告警分析Agent | 解析告警内容,提取关键信息 | 原始告警 | 结构化告警数据 |
| 故障定位Agent | 结合知识库(RAG)和实时日志(MCP) | 告警数据 | 根因分析 |
| 派单Agent | 根据根因和团队技能生成派单 | 根因+团队信息 | 派单建议 |
| 人工审核节点 | 关键决策等待人工确认 | 派单建议 | 批准/驳回/修改 |
10.2.2 状态设计#
from typing import TypedDict
class OpsMultiAgentState(TypedDict):
# 输入
alert_info: dict # 原始告警 {time, ip, metric, value, threshold}
# 告警分析Agent输出
parsed_alert: dict # 结构化告警 {time, ip, metric, severity}
# 故障定位Agent输出
root_cause: str # 根因分析
confidence_score: float # 置信度 0-1
evidence_chain: list # 证据链
# 派单Agent输出
assigned_team: str # 分配团队
dispatch_suggestion: str # 派单建议
# 人工审核
need_human: bool # 是否需要人工
human_feedback: str # 人工反馈
approved: bool # 是否批准
# 最终输出
final_report: str # 最终报告
10.3 LangGraph编排多智能体节点#
10.3.1 节点定义#
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
# ===== Supervisor Agent =====
def supervisor_plan(state: OpsMultiAgentState) -> dict:
"""主Agent:制定分析计划"""
alert = state["alert_info"]
plan = f"""
分析计划:
1. 告警分析Agent:解析{alert['ip']}的CPU告警
2. 故障定位Agent:查询历史+实时日志定位根因
3. 派单Agent:根据根因生成派单
"""
return {"parsed_alert": alert} # 传递给下一节点
# ===== 告警分析Agent =====
def alert_analysis(state: OpsMultiAgentState) -> dict:
"""解析告警内容,提取关键信息"""
alert = state["alert_info"]
parsed = {
"time": alert.get("time"),
"ip": alert.get("ip"),
"metric": alert.get("metric", "cpu_usage"),
"value": alert.get("value", "95%"),
"threshold": alert.get("threshold", "80%"),
"severity": "critical" if float(alert.get("value", "0").rstrip("%")) > 90 else "warning"
}
return {"parsed_alert": parsed}
# ===== 故障定位Agent =====
def fault_location(state: OpsMultiAgentState) -> dict:
"""结合RAG知识库和MCP实时日志定位根因"""
parsed = state["parsed_alert"]
# 1. RAG检索历史类似故障
kb_results = vectorstore.similarity_search(
f"CPU高 {parsed['ip']}", k=3
)
# 2. MCP调用获取实时日志
error_logs = mcp_call("get_error_stack", {"service": parsed["ip"]})
cpu_trend = mcp_call("query_error_rate", {"service": parsed["ip"]})
# 3. LLM综合分析根因
prompt = f"""基于以下信息分析CPU飙高根因:
告警:{parsed}
历史案例:{[r.page_content for r in kb_results]}
实时日志:{error_logs}
CPU趋势:{cpu_trend}
请输出:
1. 最可能的根因
2. 置信度(0-1)
3. 证据链(列出证据)
"""
result = llm.invoke(prompt)
return {
"root_cause": result.content,
"confidence_score": 0.85, # 从LLM输出解析
"evidence_chain": ["告警数据", "历史案例匹配", "实时日志确认"]
}
# ===== 派单Agent =====
def dispatch(state: OpsMultiAgentState) -> dict:
"""根据根因和团队技能生成派单建议"""
root_cause = state["root_cause"]
confidence = state["confidence_score"]
# 根据根因类型分配团队
if "内存泄漏" in root_cause:
team = "应用运维组"
elif "网络" in root_cause:
team = "网络运维组"
else:
team = "系统运维组"
suggestion = f"建议派单至{team},根因:{root_cause[:50]}..."
# 置信度低于0.8需要人工审核
need_human = confidence < 0.8
return {
"assigned_team": team,
"dispatch_suggestion": suggestion,
"need_human": need_human
}
# ===== 人工审核节点 =====
def human_review(state: OpsMultiAgentState) -> dict:
"""人工审核节点(实际执行时会暂停)"""
pass # interrupt_before会在此节点前暂停
# ===== 结果聚合 =====
def aggregate_report(state: OpsMultiAgentState) -> dict:
"""生成结构化报告"""
approved = state.get("approved", True)
if not approved:
return {"final_report": "工单已被人工驳回,原因:" + state.get("human_feedback", "")}
report = f"""
# 运维故障分析报告
## 一、告警概览
- IP: {state['parsed_alert']['ip']}
- 指标: {state['parsed_alert']['metric']} = {state['parsed_alert']['value']}
- 严重性: {state['parsed_alert']['severity']}
## 二、根因分析
{state['root_cause']}
## 三、证据链
"""
for i, ev in enumerate(state.get("evidence_chain", [])):
report += f"{i+1}. {ev}\n"
report += f"""
## 四、派单建议
- 分配团队: {state['assigned_team']}
- 建议: {state['dispatch_suggestion']}
- 置信度: {state['confidence_score']:.0%}
- 人工审核: {'是' if state.get('need_human') else '否'}
"""
return {"final_report": report}
10.3.2 条件边与工作流编排#
# 构建工作流
workflow = StateGraph(OpsMultiAgentState)
# 添加所有节点
workflow.add_node("supervisor", supervisor_plan)
workflow.add_node("alert_analysis", alert_analysis)
workflow.add_node("fault_location", fault_location)
workflow.add_node("dispatch", dispatch)
workflow.add_node("human_review", human_review)
workflow.add_node("end", aggregate_report)
# 设置入口和流程边
workflow.set_entry_point("supervisor")
workflow.add_edge("supervisor", "alert_analysis")
workflow.add_edge("alert_analysis", "fault_location")
workflow.add_edge("fault_location", "dispatch")
# 关键:置信度决定是否走人工审核
def route_by_confidence(state: OpsMultiAgentState) -> str:
if state.get("need_human", False):
return "human_review"
return "end"
workflow.add_conditional_edges(
"dispatch", route_by_confidence,
{"human_review": "human_review", "end": "end"}
)
# 人工审核后继续到结束
workflow.add_edge("human_review", "end")
workflow.add_edge("end", END)
# 编译(在人机协同节点前中断)
ops_app = workflow.compile(
checkpointer=MemorySaver(),
interrupt_before=["human_review"]
)
10.3.3 执行与人工协同交互#
# 模拟告警
alert = {
"time": "2026-07-22 14:30:00",
"ip": "10.0.1.50",
"metric": "cpu_usage",
"value": "95.2%",
"threshold": "80%"
}
# 第一次执行(到human_review前暂停)
config = {"configurable": {"thread_id": "alert-001"}}
result = ops_app.invoke({"alert_info": alert}, config=config)
print("=== 分析结果 ===")
print(f"根因: {result.get('root_cause', 'N/A')[:100]}")
print(f"置信度: {result.get('confidence_score', 0):.0%}")
print(f"派单: {result.get('assigned_team', 'N/A')}")
print(f"需人工: {result.get('need_human', False)}")
# 如果需要人工审核,人工输入后恢复
if result.get("need_human"):
print("\n等待人工审核...")
print(f"派单建议: {result.get('dispatch_suggestion')}")
# 人工确认
result = ops_app.invoke(
{"approved": True, "human_feedback": "确认派单"},
config=config
)
print("\n=== 最终报告 ===")
print(result.get("final_report", "无报告"))
10.4 DeepAgents任务分解#
# 主智能体调用DeepAgents将任务分解
def supervisor_with_deepagents(state: OpsMultiAgentState) -> dict:
"""使用DeepAgents层次化分解故障解决任务"""
alert = state["alert_info"]
# DeepAgents自动分解
plan = f"""
任务:解决{alert['ip']}的CPU飙高问题
分解子任务:
1. 查指标 → 查询CPU/内存/网络指标趋势(告警分析Agent)
2. 查变更记录 → 查询最近是否有部署变更(故障定位Agent)
3. 查同类历史 → 检索知识库类似故障(故障定位Agent)
4. 推荐方案 → 综合分析推荐修复动作(派单Agent)
将子任务通过LangGraph节点映射分配给各子Agent执行
"""
return {"alert_info": alert}
10.5 WebMCP对接运维后台#
10.5.1 MCP Server对接虚拟运维后台#
from fastmcp import FastMCP
mcp = FastMCP("运维后台工具")
@mcp.tool()
def get_cpu_trend(ip: str, hours: int = 1) -> dict:
"""获取CPU趋势数据"""
# 模拟从运维后台获取数据
return {
"ip": ip,
"trend": [
{"time": "14:00", "cpu": 45},
{"time": "14:15", "cpu": 62},
{"time": "14:30", "cpu": 95},
],
"trend_direction": "急剧上升"
}
@mcp.tool()
def restart_service(ip: str, service: str) -> dict:
"""重启服务"""
return {"ip": ip, "service": service, "status": "restarted"}
@mcp.tool()
def rollback_deployment(ip: str, version: str) -> dict:
"""回滚变更"""
return {"ip": ip, "rolled_back_to": version, "status": "success"}
@mcp.tool()
def get_recent_changes(ip: str, hours: int = 24) -> list:
"""获取最近变更记录"""
return [
{"time": "14:00", "change": "部署v2.3.1", "operator": "CI/CD"},
{"time": "13:30", "change": "配置修改", "operator": "admin"},
]
10.5.2 子智能体上下文隔离#
# 每个子Agent作为独立节点,只接收自己需要的状态字段
# 主Agent负责状态分发和结果聚合
def alert_analysis_isolated(state: OpsMultiAgentState) -> dict:
"""告警分析Agent - 只看到alert_info"""
alert = state["alert_info"] # 只访问告警信息
# 不访问其他Agent的中间结果
return {"parsed_alert": parse(alert)}
def fault_location_isolated(state: OpsMultiAgentState) -> dict:
"""故障定位Agent - 只看到parsed_alert"""
parsed = state["parsed_alert"] # 只访问告警分析结果
# 通过MCP调用获取实时数据
cpu_trend = mcp_call("get_cpu_trend", {"ip": parsed["ip"]})
changes = mcp_call("get_recent_changes", {"ip": parsed["ip"]})
# 通过RAG获取历史案例
cases = search_kb(f"CPU高 {parsed['ip']}")
return {"root_cause": analyze(parsed, cpu_trend, changes, cases)}
10.6 测试与调优#
10.6.1 模拟多种告警场景#
| 场景 | 输入 | 预期行为 |
|---|
| CPU高 | CPU=95% | 分析→定位→高置信度→自动派单 |
| 内存泄漏 | Memory=98% | 分析→定位→低置信度→人工审核 |
| 网络延迟 | Latency=500ms | 分析→定位→查网络→派网络组 |
10.6.2 性能优化#
| 优化点 | 方法 | 效果 |
|---|
| 并行子Agent | 无依赖的子Agent并行执行 | 减少总耗时40%+ |
| 模型分级 | 分析用大模型,分类用小模型 | 降低成本50% |
| 结果缓存 | 相同告警5分钟内不重复分析 | 减少LLM调用 |
| 流式输出 | 报告生成流式返回 | 用户等待感降低 |
10.6.3 最终端到端演示#
演示流程:
1. 触发模拟告警
2. 系统自动启动多Agent分析
3. 各子Agent并行/串行执行
4. 低置信度场景展示人机协同
5. 人工确认后继续执行
6. 生成包含证据链的完整报告
7. 展示Token消耗和耗时统计
考试要点#
- 能进行电信智能运维场景的需求分析和非功能需求定义
- 能设计多智能体架构(Supervisor + 各子Agent + 人工审核节点)
- 能定义多Agent共享状态Schema(包含告警、根因、置信度、派单等字段)
- 能用LangGraph编排多Agent工作流(节点注册、条件边、人机协同中断)
- 掌握置信度驱动的自动/人工路由(confidence_score > 0.8自动派单)
- 理解DeepAgents任务分解与LangGraph节点映射
- 能开发MCP Server对接运维后台API(CPU趋势、重启服务、回滚变更)
- 理解子Agent上下文隔离原则(每个Agent只看自己的工具和数据)
- 能设计主Agent结果聚合与人机协同交互流程
- 掌握测试调优方法:多场景模拟、并行优化、模型分级、缓存策略
- 能完成端到端演示:告警触发→多Agent协作→人工审核→报告生成
AI生成