结论
要实现智能体思考与工具调用(不仅仅是问答),需要在 API 服务层之上增加 LangChain Agent 框架,核心是:封装工具函数 + 配置 Agent 执行逻辑。
智能体架构设计
┌─────────────────────────────────────────────────────────┐
│ LangChain Agent (PC/服务器) │
│ - ReAct/Function Calling 模式 │
│ - 工具注册:天气查询、机器人控制、文件搜索等 │
│ - 多轮对话记忆(ConversationBufferMemory) │
└────────────────────┬────────────────────────────────────┘
│ HTTP (OpenAI API)
▼
┌─────────────────────────────────────────────────────────┐
│ FastAPI 桥接服务 (RDK S100P) │
│ - 接收 LLM 推理请求 │
│ - 转发给 BPU 推理引擎 │
│ - 返回生成结果 │
└────────────────────┬────────────────────────────────────┘
│ C++ SDK / 命令行
▼
┌─────────────────────────────────────────────────────────┐
│ 官方 LLM 工具链 (BPU 加速) │
│ - Qwen2.5-3B HBM 模型 │
│ - BPU 推理加速 │
└─────────────────────────────────────────────────────────┘
实现步骤
先确保 API 服务正常(基础层)
参考之前帖子的 FastAPI 封装代码,确保 LangChain 能调用 S100P 的 BPU 模型:
# s100p_llm_api.py (板端运行)
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import subprocess
app = FastAPI()
class ChatRequest(BaseModel):
messages: list
model: str = "s100p-bpu"
@app.post("/v1/chat/completions")
async def chat(req: ChatRequest):
# 构建 prompt(根据你的模板调整)
prompt = ""
for msg in req.messages:
prompt += f"{msg['role']}: {msg['content']}\n"
# 调用 oellm_run(或 C++ SDK)
cmd = [
"./oellm_run",
"--hbm_path", "./model/qwen2.5_3b.hbm",
"--tokenizer_dir", "./config/",
"--template_path", "./config/qwen.jinja",
"--model_type", "1"
]
result = subprocess.run(cmd, input=prompt, capture_output=True, text=True, timeout=120)
return {
"choices": [{"message": {"role": "assistant", "content": result.stdout}}]
}
启动服务:
uvicorn s100p_llm_api:app --host 0.0.0.0 --port 8000
开发端:LangChain Agent 配置(核心)
在**开发机(PC/服务器)**上编写 Agent 代码,注册工具函数:
# agent_demo.py (开发机运行)
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, Tool, AgentType
from langchain.memory import ConversationBufferMemory
import requests
# === 1. 定义工具函数 ===
def search_weather(city: str) -> str:
"""查询指定城市的天气"""
# 这里可以调用真实天气 API
return f"{city} 今天晴朗,温度 25°C"
def control_robot(action: str) -> str:
"""控制机器人执行动作(前进、后退、转向等)"""
# 通过 ROS2/HTTP 控制机器人
# requests.post("http://192.168.1.100:5000/control", json={"action": action})
return f"机器人已执行:{action}"
def file_search(query: str) -> str:
"""搜索本地文档"""
# 可以用 RAG 检索本地知识库
return f"找到相关文档:{query}"
# === 2. 注册工具 ===
tools = [
Tool(
name="Weather",
func=search_weather,
description="查询城市天气,输入格式:城市名"
),
Tool(
name="RobotControl",
func=control_robot,
description="控制机器人动作,输入格式:动作名称(前进/后退/左转/右转)"
),
Tool(
name="FileSearch",
func=file_search,
description="搜索本地文档,输入格式:搜索关键词"
),
]
# === 3. 连接 S100P 的 API 服务 ===
llm = ChatOpenAI(
base_url="http://192.168.1.100:8000/v1", # S100P 的 IP
api_key="not-needed",
model="s100p-bpu",
temperature=0.7
)
# === 4. 初始化 Agent(带记忆) ===
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, # ReAct 模式
memory=memory,
verbose=True # 打印思考过程
)
# === 5. 测试智能体 ===
if __name__ == "__main__":
# 测试 1:工具调用
response = agent.run("北京今天天气怎么样?")
print(f"回答:{response}")
# 测试 2:多轮对话 + 工具调用
response = agent.run("我想让机器人前进,然后查询一下上海天气")
print(f"回答:{response}")
# 测试 3:纯对话(无需工具)
response = agent.run("介绍一下你自己")
print(f"回答:{response}")
智能体思考过程示例
当用户问:“北京今天天气怎么样?然后让机器人前进”
Agent 会输出以下思考过程(verbose=True 时可见):
> Entering new AgentExecutor chain...
Thought: 我需要先查询北京的天气,然后控制机器人前进
Action: Weather
Action Input: 北京
Observation: 北京 今天晴朗,温度 25°C
Thought: 天气查询完成,现在需要控制机器人
Action: RobotControl
Action Input: 前进
Observation: 机器人已执行:前进
Thought: 所有任务完成
Final Answer: 北京今天晴朗,温度 25°C。机器人已经前进。
> Finished chain.
关键功能扩展
1. 多模态智能体(视觉 + 语言)
如果要用 BPU 做视觉理解,再交给 LLM 决策:
def analyze_image(image_path: str) -> str:
"""分析图片内容(调用 BPU 视觉模型)"""
# 1. 调用 BPU 视觉模型(YOLO/关键点检测等)
# 2. 返回检测结果描述
return "图片中检测到一个人,距离 2 米"
tools.append(Tool(
name="ImageAnalysis",
func=analyze_image,
description="分析图片内容,输入格式:图片路径"
))
2. RAG 知识库增强
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
# 加载本地知识库
embeddings = HuggingFaceEmbeddings(model_name="shibing624/text2vec-base-chinese")
vectorstore = FAISS.load_local("./knowledge_base", embeddings)
tools.append(Tool(
name="KnowledgeBase",
func=vectorstore.similarity_search,
description="检索本地知识库,输入格式:问题关键词"
))
3. 流式输出(打字机效果)
修改 FastAPI 支持 SSE 流式传输:
from fastapi.responses import StreamingResponse
@app.post("/v1/chat/completions/stream")
async def chat_stream(req: ChatRequest):
def generate():
# 逐字返回推理结果
for token in run_inference_streaming(req.messages):
yield f"data: {token}\n\n"
return StreamingResponse(generate(), media_type="text/event-stream")
常见问题排查
| 问题 | 解决方案 |
|---|---|
| Agent 不调用工具 | 检查 Tool 的 description 是否清晰,ReAct 模式需要明确描述 |
| 工具调用死循环 | 设置 max_iterations=5 限制最大尝试次数 |
| BPU 推理慢影响体验 | 使用量化模型(w8a8),或异步执行工具调用 |
| 多轮对话丢失上下文 | 确保 ConversationBufferMemory 正确传递 |
建议行动路径
- 先跑通基础 API:确保 LangChain 能调用 S100P 的 BPU 模型
- 添加 1-2 个简单工具:如天气查询、文件搜索
- 测试 ReAct 模式:观察 Agent 思考过程
- 扩展多模态能力:集成 BPU 视觉模型作为工具
- 沉淀到社区:将完整代码发到 Model Zoo 板块
社区资源
- LangChain Agent 文档:LangChain overview - Docs by LangChain
- ReAct 模式详解:agents | langchain | LangChain Reference
- 相关讨论:RDK s100p 跑 LLM 大语言模型
需要我帮你写一个完整的可运行 Demo(包含 API 服务 + Agent 代码)吗?可以打包成 GitHub 仓库方便复用。