大家好,我是何三,80后老猿,独立开发者
今天我来带大家用python手搓一个智能体,咱们先从简单入门介绍开始,这里假设你懂点python并且对OpenAi接口了解一点,让我们从一段简单的对话代码开始。在Python控制台里,我们初始化了一个OpenAI客户端,这个看似普通的对象将成为构建智能体的基石。当用户询问"北京现在多少度?"时,系统不会直接回答,而是触发了一个精密的决策过程——这正是智能体的核心奥秘所在。
智能体的首要任务是理解意图。我们为模型设计了一个三层提示结构:系统提示设定角色为"全能助手",要求先思考再行动;用户提示携带原始问题;工具提示描述可用的天气查询函数。这种分层设计让模型在不同阶段处理不同任务,就像导演在指挥多幕剧的演出:
messages = [
{"role": "system", "content": "你是一个全能助手,需要先思考再调用工具"},
{"role": "user", "content": "北京现在多少度?"},
{"role": "tool", "content": "可用工具: get_weather(city)->温度"}
]
当模型返回带有function_call字段的响应时,真正的魔法开始了。我们设计了一个工具路由机制,自动匹配函数名并执行对应代码。这个路由系统就像智能体的中枢神经,将语言模型的抽象思维转化为具体行动:
def route_function_call(name, arguments):
if name == "get_weather":
return weather_api(arguments["city"])
elif name == "web_search":
return search_engine(arguments["query"])
# 更多工具分支...
但智能体不应只是机械执行命令。我们在提示词中植入"思维链"指令,要求模型展示推理过程。这类似于给智能体安装了一个实时运行的诊断系统,让我们能观察其决策逻辑:
system_prompt = """
请按以下步骤思考:
1. 解析用户意图
2. 选择合适工具
3. 验证参数完整性
4. 执行并验证结果
最后用<answer>标签包裹最终回答
"""
当处理复杂查询时,比如"帮我比较特斯拉和比亚迪的电池技术",智能体需要启动RAG(检索增强生成)流程。我们构建了一个本地知识库,使用SentenceTransformer将技术文档转换为向量,存储在FAISS索引中。这个过程犹如为智能体装备了一个外部记忆库:
from sentence_transformers import SentenceTransformer
from langchain.vectorstores import FAISS
encoder = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
doc_vectors = encoder.encode(technical_docs)
vector_db = FAISS.from_embeddings(doc_vectors, technical_docs)
当用户查询进入时,智能体会先检索最相关的5个文档片段,将这些上下文注入到提示词中。这种动态知识注入机制,使得智能体可以突破训练数据的时效限制,就像学者随时查阅最新文献:
query_vector = encoder.encode(user_query)
results = vector_db.similarity_search(query_vector, k=5)
context = "\n".join([doc.page_content for doc in results])
在工具调用与知识检索的基础上,我们设计了自省机制。当模型对工具返回结果存疑时,会自动启动验证流程——可能调用第二个工具进行交叉验证,或在知识库中寻找佐证。这相当于给智能体装上了批判性思维:
if confidence < 0.7:
messages.append({
"role": "system",
"content": "当前结果置信度较低,请用其他方法验证"
})
return process_retry(messages)
错误处理是智能体成熟度的试金石。我们为每个工具调用包裹了异常捕获层,当API调用失败时,不仅记录日志,还会启动备用方案。这种容错设计让智能体在现实环境的波动中保持稳定:
try:
data = get_weather(city)
except APIError as e:
logger.error(f"天气API故障: {str(e)}")
return {"status": "retry", "fallback": web_search(f"{city} 天气")}
在信息整合阶段,智能体采用渐进式生成策略。先产出草稿,再对照工具结果和检索内容进行修订,最后进行事实性校验。这个过程模仿了人类写作时的反复推敲:
draft = client.chat.completions.create(
model="gpt-4",
messages=messages + [{"role": "user", "content": "生成回答草稿"}]
)
revised = client.chat.completions.create(
model="gpt-4",
messages=messages + [
{"role": "assistant", "content": draft},
{"role": "user", "content": "根据以下数据修订回答: " + tool_results}
]
)
为了让智能体具备个性化特征,我们设计了记忆持久化模块。使用SQLite存储对话历史,通过时间衰减算法计算历史权重,使智能体既能保持连贯对话,又不会被困在过去的上下文里:
class DialogueMemory:
def __init__(self):
self.db = sqlite3.connect(':memory:')
# 创建消息表包含时间戳和权重字段
def add_message(self, role, content):
# 插入新记录并更新衰减权重
在安全防护方面,我们实现了多层过滤系统:输入预处理层检测恶意指令,输出过滤层屏蔽敏感信息,工具调用验证层防止非法操作。这些防护机制如同智能体的免疫系统:
def security_check(content):
patterns = [r"(恶意关键词1)", r"(漏洞利用特征2)"]
for pattern in patterns:
if re.search(pattern, content):
return False
return True
性能优化是工程化落地的关键。我们采用异步IO处理工具调用,缓存常用检索结果,对知识库实现分片索引。实测显示,这些优化使响应延迟降低了40%:
async def async_tool_call(tool_name, params):
tool = get_tool(tool_name)
return await tool.execute(**params)
评估智能体的表现需要多维指标体系。我们设计了意图理解准确率、工具调用成功率、事实正确性等12个指标,每个对话回合生成评估报告。这种量化评估推动着智能体的持续进化:
class Evaluator:
def calculate_metrics(self, dialog_history):
accuracy = self._intent_accuracy()
relevance = self._response_relevance()
# 其他指标计算...
return ComprehensiveReport(accuracy, relevance, ...)
在整合所有模块时,我们构建了智能体核心类。这个类管理着对话状态,协调各组件工作,处理输入到输出的完整生命周期。观察其工作流程,就像观看交响乐团在指挥棒下奏响完美乐章:
class AIAgent:
def __init__(self):
self.llm = OpenAIClient()
self.tools = ToolManager()
self.memory = DialogueMemory()
self.retriever = VectorRetriever()
def process_query(self, user_input):
# 完整处理链条的实现
最后,我们为智能体设计了持续学习机制。每个对话回合的错误都会被记录分析,重要信息自动添加到知识库,工具调用模式不断优化。这使得智能体在投入使用后仍能不断成长,如同具备生命的有机体:
def self_improve(self, dialog_history):
errors = analyze_errors(dialog_history)
for error in errors:
if error.type == "knowledge_gap":
self.retriever.add_documents(error.context)
elif error.type == "tool_failure":
self.tools.update_registry(error.tool_name)
从最初的单轮对话到具备记忆、检索、自省的复杂系统,我们逐步搭建起智能体的每个功能模块。这趟代码之旅揭示了现代AI智能体的构造奥秘:它不是神秘的黑箱,而是由精心设计的提示工程、模块化工具调用、动态知识融合组成的精密系统。每个print()输出的背后,都跃动着算法与工程智慧交织的脉搏。
下面来实现一个完整的案例demo:
让我们通过一个可运行的完整案例,揭示智能体系统的构建奥秘。以下代码实现了一个具备工具调用、知识检索和思维链的智能体,仅使用基础库完成核心功能。(注意:需提前安装openai、faiss-cpu、sentence-transformers库)
import openai
import json
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer
# 初始化模型
encoder = SentenceTransformer('paraphrase-MiniLM-L6-v2')
client = openai.Client(api_key='your_api_key')
class KnowledgeBase:
def __init__(self):
self.index = faiss.IndexFlatL2(384) # 匹配MiniLM的向量维度
self.documents = []
def add_document(self, text):
vector = encoder.encode([text])[0]
self.index.add(np.array([vector]))
self.documents.append(text)
def search(self, query, k=3):
query_vec = encoder.encode([query])[0]
distances, indices = self.index.search(np.array([query_vec]), k)
return [self.documents[i] for i in indices[0]]
# 构建示例知识库
kb = KnowledgeBase()
kb.add_document("特斯拉采用21700圆柱锂电池,能量密度300Wh/kg")
kb.add_document("比亚迪刀片电池是磷酸铁锂技术,体积利用率提升50%")
kb.add_document("北京年平均气温12°C,一月最冷平均-3°C,七月最热平均26°C")
def get_weather(city):
"""模拟天气查询API"""
weather_data = {
"北京": {"temp": 22, "humidity": 65},
"上海": {"temp": 25, "humidity": 70}
}
return json.dumps(weather_data.get(city, {}))
def process_query(user_input):
# 构建思维链提示
messages = [
{"role": "system", "content": """你是一个工业级智能体,请按以下步骤处理问题:
1. [分析] 解析用户意图
2. [工具] 决定是否调用工具
3. [检索] 判断是否需要知识检索
4. [响应] 综合所有信息生成回答"""},
{"role": "user", "content": user_input}
]
# 第一轮:决策判断
decision_resp = client.chat.completions.create(
model="qwen-max",
messages=messages,
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取城市天气数据",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}}
}
}
}],
tool_choice="auto"
)
# 处理工具调用
tool_response = ""
if decision_resp.choices[0].message.tool_calls:
tool_call = decision_resp.choices[0].message.tool_calls[0]
if tool_call.function.name == "get_weather":
args = json.loads(tool_call.function.arguments)
tool_response = get_weather(args["city"])
messages.append({
"role": "tool",
"content": tool_response,
"tool_call_id": tool_call.id
})
# 知识检索
if "比较" in user_input or "差异" in user_input:
context = "\n".join(kb.search(user_input))
messages.append({
"role": "system",
"content": f"相关技术文档:\n{context}"
})
# 生成最终响应
final_resp = client.chat.completions.create(
model="qwen-max",
messages=messages,
max_tokens=500
)
return final_resp.choices[0].message.content
# 测试用例
if __name__ == "__main__":
questions = [
"北京现在多少度?",
"比较特斯拉和比亚迪的电池技术差异",
"上海的湿度如何?"
]
for q in questions:
print(f"用户问题:{q}")
answer = process_query(q)
print(f"智能体回答:{answer}\n{'-'*50}")
当运行这个智能体系统时,您会看到这样的处理流程:
- 意图解析阶段:系统首先分析"北京现在多少度?"需要天气数据,触发get_weather工具调用
- 数据获取阶段:模拟API返回JSON数据{"temp": 22, "humidity": 65}
- 知识增强阶段:处理"比较电池技术"时,从本地知识库检索出两条相关技术文档
- 综合生成阶段:将工具返回和检索结果注入上下文,生成最终回答
该实现包含几个关键技术点:
动态工具路由:通过检测tool_calls字段自动触发工具调用,并自动将结果注入对话历史。代码中get_weather函数的参数自动从用户问题中提取,展示出语义解析能力:
# 工具调用处理逻辑
if tool_call.function.name == "get_weather":
args = json.loads(tool_call.function.arguments) # 自动解析出{"city": "北京"}
tool_response = get_weather(args["city"])
混合检索策略:当检测到比较类问题时,自动触发向量检索。知识库使用FAISS实现毫秒级搜索,SentenceTransformer生成语义向量:
# 语义检索实现
context = "\n".join(kb.search(user_input))
messages.append({"role": "system", "content": f"相关技术文档:\n{context}"})
思维链可视化:系统提示中要求分步骤思考,虽然最终响应不展示中间过程,但开发者可以通过调整提示词要求模型输出思考过程:
system_prompt = """你是一个工业级智能体,请按以下步骤处理问题:
1. [分析] 解析用户意图
2. [工具] 决定是否调用工具
3. [检索] 判断是否需要知识检索
4. [响应] 综合所有信息生成回答"""
上下文管理:对话历史采用增量式构建,每个阶段都在修改消息列表。这种设计使得智能体具备多轮对话能力的基础架构:
messages = [初始提示]
messages.append(工具响应)
messages.append(检索上下文)
messages.append(最终回答)
当处理技术对比类问题时,系统会展现知识增强的威力。例如询问电池技术差异时,代码会执行以下关键步骤:
- 向量检索找出相关文档
- 将技术参数注入系统提示
- 要求模型基于准确数据进行比较
# 当用户输入包含"比较"时触发的检索
if "比较" in user_input:
context = "\n".join(kb.search(user_input))
# 注入提示词后的消息示例:
[
{"role": "system", "content": "相关技术文档:\n特斯拉采用21700圆柱锂电池...比亚迪刀片电池..."},
{"role": "user", "content": "比较电池技术差异"}
]
这个实现方案避免了使用任何高阶框架,却完整展示了智能体的核心架构。开发者可以在此基础上扩展以下功能:
- 增加更多工具函数(如股票查询、航班搜索)
- 实现对话历史持久化
- 添加结果验证模块
- 构建更复杂的检索策略
通过调整系统提示词,还能改变智能体的行为模式。例如添加以下约束条件:
system_prompt += "\n重要原则:\n- 数值信息必须标注数据来源\n- 技术术语需附带英文原文\n- 比较分析需包含至少三个维度"
这种从零构建的方式,让开发者深入理解智能体的每个决策环节。当控制台输出最终回答时,看似简单的文字背后,已经历了意图识别、工具调度、知识融合、生成约束等多个精密处理阶段。这正是现代AI智能体的精髓所在——将语言模型的推理能力,转化为可验证、可扩展、可控制的系统工程。
下面我们来实现一个完整的案例demo:
让我们通过一个可运行的完整案例,揭示智能体系统的构建奥秘。以下代码实现了一个具备工具调用、知识检索和思维链的智能体,仅使用基础库完成核心功能。(注意:需提前安装openai、faiss-cpu、sentence-transformers库)
import openai
import json
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer
# 初始化模型
encoder = SentenceTransformer('paraphrase-MiniLM-L6-v2')
client = openai.Client(base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',api_key='your_api_key')
class KnowledgeBase:
def __init__(self):
self.index = faiss.IndexFlatL2(384) # 匹配MiniLM的向量维度
self.documents = []
def add_document(self, text):
vector = encoder.encode([text])[0]
self.index.add(np.array([vector]))
self.documents.append(text)
def search(self, query, k=3):
query_vec = encoder.encode([query])[0]
distances, indices = self.index.search(np.array([query_vec]), k)
return [self.documents[i] for i in indices[0]]
# 构建示例知识库
kb = KnowledgeBase()
kb.add_document("特斯拉采用21700圆柱锂电池,能量密度300Wh/kg")
kb.add_document("比亚迪刀片电池是磷酸铁锂技术,体积利用率提升50%")
kb.add_document("北京年平均气温12°C,一月最冷平均-3°C,七月最热平均26°C")
def get_weather(city):
"""模拟天气查询API"""
weather_data = {
"北京": {"temp": 22, "humidity": 65},
"上海": {"temp": 25, "humidity": 70}
}
return json.dumps(weather_data.get(city, {}))
def process_query(user_input):
# 构建思维链提示
messages = [
{"role": "system", "content": """你是一个工业级智能体,请按以下步骤处理问题:
1. [分析] 解析用户意图
2. [工具] 决定是否调用工具
3. [检索] 判断是否需要知识检索
4. [响应] 综合所有信息生成回答"""},
{"role": "user", "content": user_input}
]
# 第一轮:决策判断
decision_resp = client.chat.completions.create(
model="qwen-max",
messages=messages,
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取城市天气数据",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}}
}
}
}],
tool_choice="auto"
)
# 处理工具调用
tool_response = ""
if decision_resp.choices[0].message.tool_calls:
tool_call = decision_resp.choices[0].message.tool_calls[0]
if tool_call.function.name == "get_weather":
args = json.loads(tool_call.function.arguments)
tool_response = get_weather(args["city"])
messages.append({
"role": "tool",
"content": tool_response,
"tool_call_id": tool_call.id
})
# 知识检索
if "比较" in user_input or "差异" in user_input:
context = "\n".join(kb.search(user_input))
messages.append({
"role": "system",
"content": f"相关技术文档:\n{context}"
})
# 生成最终响应
final_resp = client.chat.completions.create(
model="qwen-max",
messages=messages,
max_tokens=500
)
return final_resp.choices[0].message.content
# 测试用例
if __name__ == "__main__":
questions = [
"北京现在多少度?",
"比较特斯拉和比亚迪的电池技术差异",
"上海的湿度如何?"
]
for q in questions:
print(f"用户问题:{q}")
answer = process_query(q)
print(f"智能体回答:{answer}\n{'-'*50}")
当运行这个智能体系统时,您会看到这样的处理流程:
- 意图解析阶段:系统首先分析"北京现在多少度?"需要天气数据,触发get_weather工具调用
- 数据获取阶段:模拟API返回JSON数据{"temp": 22, "humidity": 65}
- 知识增强阶段:处理"比较电池技术"时,从本地知识库检索出两条相关技术文档
- 综合生成阶段:将工具返回和检索结果注入上下文,生成最终回答
该实现包含几个关键技术点:
动态工具路由:通过检测tool_calls字段自动触发工具调用,并自动将结果注入对话历史。代码中get_weather函数的参数自动从用户问题中提取,展示出语义解析能力:
# 工具调用处理逻辑
if tool_call.function.name == "get_weather":
args = json.loads(tool_call.function.arguments) # 自动解析出{"city": "北京"}
tool_response = get_weather(args["city"])
混合检索策略:当检测到比较类问题时,自动触发向量检索。知识库使用FAISS实现毫秒级搜索,SentenceTransformer生成语义向量:
# 语义检索实现
context = "\n".join(kb.search(user_input))
messages.append({"role": "system", "content": f"相关技术文档:\n{context}"})
思维链可视化:系统提示中要求分步骤思考,虽然最终响应不展示中间过程,但开发者可以通过调整提示词要求模型输出思考过程:
system_prompt = """你是一个工业级智能体,请按以下步骤处理问题:
1. [分析] 解析用户意图
2. [工具] 决定是否调用工具
3. [检索] 判断是否需要知识检索
4. [响应] 综合所有信息生成回答"""
上下文管理:对话历史采用增量式构建,每个阶段都在修改消息列表。这种设计使得智能体具备多轮对话能力的基础架构:
messages = [初始提示]
messages.append(工具响应)
messages.append(检索上下文)
messages.append(最终回答)
当处理技术对比类问题时,系统会展现知识增强的威力。例如询问电池技术差异时,代码会执行以下关键步骤:
- 向量检索找出相关文档
- 将技术参数注入系统提示
- 要求模型基于准确数据进行比较
# 当用户输入包含"比较"时触发的检索
if "比较" in user_input:
context = "\n".join(kb.search(user_input))
# 注入提示词后的消息示例:
[
{"role": "system", "content": "相关技术文档:\n特斯拉采用21700圆柱锂电池...比亚迪刀片电池..."},
{"role": "user", "content": "比较电池技术差异"}
]
这个实现方案避免了使用任何高阶框架,却完整展示了智能体的核心架构。开发者可以在此基础上扩展以下功能:
- 增加更多工具函数(如股票查询、航班搜索)
- 实现对话历史持久化
- 添加结果验证模块
- 构建更复杂的检索策略
通过调整系统提示词,还能改变智能体的行为模式。例如添加以下约束条件:
system_prompt += "\n重要原则:\n- 数值信息必须标注数据来源\n- 技术术语需附带英文原文\n- 比较分析需包含至少三个维度"
这种从零构建的方式,让开发者深入理解智能体的每个决策环节。当控制台输出最终回答时,看似简单的文字背后,已经历了意图识别、工具调度、知识融合、生成约束等多个精密处理阶段。这正是现代AI智能体的精髓所在——将语言模型的推理能力,转化为可验证、可扩展、可控制的系统工程。
以上,既然看到这里了,如果觉得不错,随手点个赞、在看、转发三连吧,如果想第一时间收到推送,也可以给我个星标⭐~谢谢你看我的文章,我们,下次再见。