文章目录
-
- 前言
- 一、感知模块进阶:从"被动收集"到"主动探索",信息不遗漏
-
- [1. 核心痛点:信息缺失导致决策失误](#1. 核心痛点:信息缺失导致决策失误)
- [2. 进阶技巧1:基于规则的主动提问,补全关键信息](#2. 进阶技巧1:基于规则的主动提问,补全关键信息)
- [3. 进阶技巧2:跨源信息融合,打破信息孤岛](#3. 进阶技巧2:跨源信息融合,打破信息孤岛)
- 二、记忆模块进阶:从"简单存储"到"智能检索",记的准、找的快
-
- [1. 核心痛点:记忆太多,找不到有用的](#1. 核心痛点:记忆太多,找不到有用的)
- [2. 进阶技巧1:用向量数据库实现"语义检索",匹配更准](#2. 进阶技巧1:用向量数据库实现“语义检索”,匹配更准)
- [3. 进阶技巧2:记忆分级与过期机制,减轻存储压力](#3. 进阶技巧2:记忆分级与过期机制,减轻存储压力)
- 三、决策模块进阶:从"固定拆分"到"动态调整",步骤更合理、策略更灵活
- 四、工具调用模块进阶:从"固定映射"到"智能选择",调用更稳、适配性更强
- 五、总结:模块进阶的核心是"更智能、更容错、更适配"
目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步。想要系统学习AI知识的朋友可以看看我的教程http://blog.csdn.net/jiangjunshow,教程通俗易懂,风趣幽默,从深度学习基础原理到各领域实战应用都有讲解。
前言
上一节咱们拆解了Agent的四大核心模块------感知、记忆、决策、工具调用,知道了每个模块的基本工作原理和简单实现。但实际开发中,简单版本的模块肯定满足不了复杂需求:比如感知模块收集的信息不全、记忆模块检索太慢、决策模块拆的步骤不合理、工具调用经常失败......
这一节咱们就来聊每个模块的"进阶技巧",不用讲复杂的算法原理,全是能直接落地的实战方法,帮你把每个模块从"能用"升级到"好用、智能",让你的Agent真正具备解决复杂问题的能力。
一、感知模块进阶:从"被动收集"到"主动探索",信息不遗漏
基础版的感知模块,只能收集"用户明确提供"和"预设好的关联信息",但实际场景中,很多关键信息用户不会主动说,预设的关联信息也可能不全------这时候就需要让感知模块具备"主动探索"能力,像侦探一样主动找线索。
1. 核心痛点:信息缺失导致决策失误
举个例子:用户让Agent"帮我优化一下项目的数据库性能",基础版感知模块只会收集"用户需求+项目数据库类型",但关键信息比如"数据库当前的QPS、慢查询日志、表结构设计"用户没说,感知模块也没主动问,导致决策模块只能给出"加索引、优化SQL"这种通用建议,没法针对性优化。
2. 进阶技巧1:基于规则的主动提问,补全关键信息
解决思路很简单:提前定义"关键信息清单",如果感知模块没收集到,就主动向用户提问。比如数据库性能优化的关键信息清单是"数据库类型(MySQL/PostgreSQL)、QPS、慢查询日志、表结构、当前索引情况",只要有一项缺失,就主动问用户。
代码实现思路(Python):
python
def perception_module_advanced(user_input, project_path):
# 1. 基础信息收集(和之前一样)
raw_info = collect_information(user_input, project_path)
processed_info = process_information(raw_info)
# 2. 定义当前任务的关键信息清单(可根据任务类型动态切换)
task_type = judge_task_type(user_input) # 先判断任务类型:数据库优化、代码生成、数据分析等
if task_type == "数据库性能优化":
required_info = [
"数据库类型", "QPS", "慢查询日志路径", "表结构设计", "当前索引情况"
]
# 3. 检查哪些关键信息缺失
missing_info = []
for info in required_info:
if info not in processed_info or processed_info[info] is None:
missing_info.append(info)
# 4. 主动向用户提问,补全缺失信息
if missing_info:
question = f"为了给你提供更精准的优化建议,需要你补充以下信息:{', '.join(missing_info)}"
return {"status": "need_more_info", "question": question, "collected_info": processed_info}
# 5. 信息齐全,返回给决策模块
return {"status": "complete", "data": processed_info}
# 使用示例
result = perception_module_advanced("帮我优化项目的数据库性能", "./project")
if result["status"] == "need_more_info":
print(result["question"]) # 输出:为了给你提供更精准的优化建议,需要你补充以下信息:QPS、慢查询日志路径、表结构设计、当前索引情况
这个技巧的核心是"任务类型→关键信息清单→缺失检查→主动提问",能确保感知模块收集到的信息足够全,避免决策模块"巧妇难为无米之炊"。
3. 进阶技巧2:跨源信息融合,打破信息孤岛
很多时候,关键信息分散在多个地方(比如数据库、日志文件、API接口、文档),基础版感知模块只能从一个地方收集信息,进阶版需要支持"跨源信息融合"------同时从多个来源收集信息,然后整合在一起。
例子:智能运维Agent的感知模块
用户说"服务器响应变慢",感知模块需要同时收集:
- 服务器监控数据(CPU、内存、磁盘IO):从Prometheus接口获取;
- 应用日志:从ELK系统获取;
- 数据库状态:从MySQL的show status命令获取;
- 最近的部署记录:从Jenkins接口获取。
然后把这些跨来源的信息整合,比如发现"CPU使用率正常,但数据库连接数满了,且最近刚部署了新功能",就能给决策模块提供更全面的线索。
代码实现思路(Python):
python
# 跨源信息采集工具
class MultiSourceCollector:
# 从Prometheus获取服务器监控数据
def get_prometheus_data(self, server_ip, metrics):
prometheus_url = f"http://{server_ip}:9090/api/v1/query"
params = {"query": ",".join(metrics)}
response = requests.get(prometheus_url, params=params)
return response.json()["data"]["result"]
# 从ELK获取应用日志
def get_elk_logs(self, app_name, start_time):
elk_url = "http://elk-server:9200/_search"
query = {
"query": {
"bool": {
"must": [
{"match": {"app": app_name}},
{"range": {"@timestamp": {"gte": start_time}}}
]
}
}
}
response = requests.post(elk_url, json=query)
return [hit["_source"] for hit in response.json()["hits"]["hits"]]
# 从MySQL获取数据库状态
def get_mysql_status(self, db_conn):
cursor = db_conn.cursor()
cursor.execute("show status like 'Threads_used'") # 查询当前连接数
return cursor.fetchone()
# 感知模块整合跨源信息
def perception_multi_source(user_input, server_ip, db_conn):
collector = MultiSourceCollector()
# 1. 收集跨源信息
monitor_data = collector.get_prometheus_data(server_ip, ["cpu_usage", "memory_usage", "disk_io"])
app_logs = collector.get_elk_logs("user-service", "now-1h")
mysql_status = collector.get_mysql_status(db_conn)
# 2. 信息整合:提取关键指标
processed_info = {
"cpu_usage": monitor_data[0]["value"][1],
"memory_usage": monitor_data[1]["value"][1],
"disk_io": monitor_data[2]["value"][1],
"error_log_count": len([log for log in app_logs if log["level"] == "ERROR"]),
"mysql_connections": mysql_status[1]
}
return processed_info
这个技巧的核心是"统一信息采集接口+多源数据整合",让感知模块能像"蜘蛛"一样,从各个角落收集信息,形成完整的信息闭环。
二、记忆模块进阶:从"简单存储"到"智能检索",记的准、找的快
基础版的记忆模块,只能按"关键词"检索,而且长期记忆存储在普通数据库里,检索速度慢、准确率低------进阶版需要解决两个问题:检索更快、匹配更准,让Agent能快速找到最相关的记忆。
1. 核心痛点:记忆太多,找不到有用的
比如你的Agent长期记忆里存储了1000篇技术文档,当用户问"Spring Boot怎么处理跨域问题",基础版记忆模块只会检索包含"Spring Boot"和"跨域"关键词的文档,但可能会返回很多不相关的(比如"Spring Boot跨域的历史版本问题"),而进阶版需要精准返回"当前版本的跨域解决方案"。
2. 进阶技巧1:用向量数据库实现"语义检索",匹配更准
传统的关键词检索,只能匹配"字面上的相同",而语义检索能匹配"意思上的相同"------比如用户问"怎么解决前后端数据交互的跨域问题",即使文档里写的是"Spring Boot跨域配置方案",语义检索也能精准匹配到。
实现方式很简单:把长期记忆的内容转换成向量(Embedding),存储到向量数据库(比如Milvus、Chroma),检索时把用户的问题也转换成向量,找最相似的向量对应的记忆。
代码实现思路(Python+Chroma):
python
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
# 初始化向量数据库和Embedding模型
embeddings = OpenAIEmbeddings(api_key="你的API密钥")
# 持久化存储向量数据库(避免每次重启都重新生成向量)
vector_db = Chroma(
persist_directory="./agent_vector_db", # 存储路径
embedding_function=embeddings,
collection_name="technical_docs" # 集合名,方便分类存储
)
# 进阶版长期记忆:向量数据库存储
class AdvancedLongTermMemory:
def __init__(self):
self.vector_db = vector_db
# 存储记忆:把文本转换成向量存储
def store(self, type_, content):
# 给记忆加标签,方便后续过滤(比如"技术文档""业务规则")
metadata = {"type": type_}
self.vector_db.add_texts(texts=[content], metadatas=[metadata])
self.vector_db.persist() # 持久化
# 检索记忆:语义检索,返回最相似的前3条
def retrieve(self, query, type_=None):
# 构建检索条件:如果指定类型,只检索该类型的记忆
filter_condition = {"type": type_} if type_ else None
# 语义检索:找最相似的3条
docs = self.vector_db.similarity_search(
query=query,
k=3, # 返回前3条最相似的
filter=filter_condition
)
return [doc.page_content for doc in docs]
# 使用示例
long_term_memory = AdvancedLongTermMemory()
# 存储记忆:把技术文档存入向量数据库
long_term_memory.store("技术文档", "Spring Boot 2.7+ 跨域配置:在Application类中添加@CrossOrigin注解,或配置WebMvcConfigurer")
long_term_memory.store("技术文档", "Spring Boot 2.0-2.6 跨域配置:通过继承WebMvcConfigurerAdapter实现")
# 检索记忆:用户问"Spring Boot怎么处理跨域问题"
results = long_term_memory.retrieve("Spring Boot怎么处理跨域问题", type_="技术文档")
print(results)
# 输出:两条最相关的跨域配置文档,即使用户没说"配置""注解"等关键词
这个技巧的核心是"Embedding转换+向量数据库存储",让记忆检索从"关键词匹配"升级到"语义理解匹配",准确率提升一个档次。而且向量数据库的检索速度比普通数据库快10倍以上,即使存储10万条记忆也能秒级返回结果。
3. 进阶技巧2:记忆分级与过期机制,减轻存储压力
Agent的记忆会越来越多,如果不清理,会导致存储压力大、检索速度变慢------进阶版需要给记忆"分级",并设置"过期机制",自动清理没用的记忆。
记忆分级策略:
- 一级记忆(核心记忆):永远不清理,比如业务核心规则、常用技术文档、用户的核心偏好;
- 二级记忆(重要记忆):长期保留(比如6个月),比如历史执行记录、项目配置信息;
- 三级记忆(临时记忆):短期保留(比如7天),比如临时的对话历史、一次性的任务数据。
代码实现思路:
python
class AdvancedMemoryModule:
def __init__(self):
# 一级记忆:核心记忆,存储在向量数据库(永久)
self.core_memory = AdvancedLongTermMemory()
# 二级记忆:重要记忆,存储在MySQL(6个月过期)
self.important_memory = MySQLMemory(expire_days=180)
# 三级记忆:临时记忆,存储在Redis(7天过期)
self.temp_memory = RedisMemory(expire_days=7)
# 存储记忆:根据记忆类型选择存储方式
def store(self, memory_level, type_, content):
if memory_level == "core":
self.core_memory.store(type_, content)
elif memory_level == "important":
self.important_memory.store(type_, content)
elif memory_level == "temp":
self.temp_memory.store(type_, content)
# 检索记忆:先查临时记忆,再查重要记忆,最后查核心记忆
def retrieve(self, query, type_=None):
# 1. 查临时记忆
temp_results = self.temp_memory.retrieve(query, type_)
if temp_results:
return temp_results
# 2. 查重要记忆
important_results = self.important_memory.retrieve(query, type_)
if important_results:
return important_results
# 3. 查核心记忆
core_results = self.core_memory.retrieve(query, type_)
return core_results
这个技巧的核心是"分级存储+过期清理",既保证了核心记忆不丢失,又减轻了存储和检索压力,让记忆模块运行更高效。
三、决策模块进阶:从"固定拆分"到"动态调整",步骤更合理、策略更灵活
基础版的决策模块,只能按大模型的输出拆分步骤,而且步骤一旦确定就不能改------进阶版需要具备"动态调整"能力,能根据执行结果、环境变化调整步骤和策略,避免"一条路走到黑"。
1. 核心痛点:步骤不合理或执行失败,无法调整
比如用户让Agent"下载某网站的图片并压缩",基础版决策模块拆的步骤是"1. 下载图片;2. 压缩图片",但执行时发现"网站需要登录才能下载",基础版就会卡住,而进阶版需要动态添加"登录网站"步骤。
2. 进阶技巧1:加入"步骤校验",避免不合理步骤
在决策模块生成步骤后,先进行"规则校验",过滤掉不合理的步骤,比如"步骤数量不能超过5个""必须先执行前置步骤(比如先登录再下载)""不能调用危险工具(比如删除系统文件)"。
代码实现思路:
python
def make_decision_advanced(goal, context, memory):
# 1. 调用大模型生成初始决策(和基础版一样)
initial_decision = llm.predict(prompt)
structured_decision = _parse_decision(initial_decision)
# 2. 步骤校验规则
validation_rules = [
# 规则1:步骤数量在2-5个之间
lambda steps: 2 <= len(steps) <= 5,
# 规则2:如果有"下载"步骤,必须有"登录"步骤(如果网站需要登录)
lambda steps: "登录网站" in [step["步骤"] for step in steps]
if "下载图片" in [step["步骤"] for step in steps] and context.get("need_login")
else True,
# 规则3:不能调用危险工具
lambda steps: not any("删除" in step["策略"] for step in steps)
]
# 3. 执行校验
valid = all(rule(structured_decision) for rule in validation_rules)
if not valid:
# 校验失败,让大模型重新生成决策
prompt = f"你之前生成的步骤不符合要求,请重新生成:{structured_decision}\n要求:步骤数量2-5个,需要登录的网站先登录,不能调用删除类工具"
revised_decision = llm.predict(prompt)
return _parse_decision(revised_decision)
return structured_decision
这个技巧的核心是"先校验后执行",用规则过滤掉不合理的决策,避免Agent做无用功或危险操作。
3. 进阶技巧2:加入"反馈调整机制",动态修改步骤
决策模块不是"一锤子买卖",而是要根据工具调用的结果,动态调整步骤------比如某个步骤执行失败,就重新生成该步骤的策略;某个步骤执行后有新的信息,就新增后续步骤。
代码实现思路:
python
def dynamic_decision_adjust(decision, execution_results, context):
"""
动态调整决策
:param decision: 初始决策(步骤列表)
:param execution_results: 已执行步骤的结果(成功/失败+返回数据)
:param context: 最新的上下文信息
:return: 调整后的决策
"""
# 1. 分析执行结果,找到问题
adjusted_steps = []
for i, (step, result) in enumerate(zip(decision, execution_results)):
if result["status"] == "success":
# 执行成功,保留该步骤,把结果加入上下文
adjusted_steps.append(step)
context[f"step_{i+1}_result"] = result["data"]
else:
# 执行失败,让大模型重新生成该步骤的策略
prompt = f"""
步骤"{step['步骤']}"执行失败,原因:{result['message']}
当前上下文:{context}
请重新生成该步骤的执行策略,要求:
1. 解决失败原因;
2. 基于当前上下文信息;
3. 只返回新的策略,不要其他内容。
"""
new_strategy = llm.predict(prompt)
adjusted_steps.append({"步骤": step["步骤"], "策略": new_strategy})
# 2. 检查是否需要新增步骤(根据已执行结果)
prompt = f"""
已执行步骤的结果:{execution_results}
当前上下文:{context}
原目标:{goal}
请判断是否需要新增步骤才能达成目标?如果需要,返回新增的步骤和策略(格式:步骤X:xxx,策略X:xxx),不需要则返回"无需新增"。
"""
add_steps = llm.predict(prompt)
if add_steps != "无需新增":
adjusted_steps.extend(_parse_decision(add_steps))
return adjusted_steps
# 使用示例
# 初始决策:[{'步骤': '下载图片', '策略': '直接调用requests下载'}]
# 执行结果:{'status': 'fail', 'message': '网站需要登录,返回401'}
# 动态调整后,决策变成:[{'步骤': '下载图片', '策略': '先调用登录接口获取cookie,再用cookie下载'}]
这个技巧的核心是"执行反馈→问题分析→策略调整/步骤新增",让决策模块具备"自我修正"能力,能应对各种突发情况,而不是死板地执行初始步骤。
四、工具调用模块进阶:从"固定映射"到"智能选择",调用更稳、适配性更强
基础版的工具调用模块,只能按"策略→工具"的固定映射调用,而且不处理异常------进阶版需要解决三个问题:选对工具、处理异常、适配多工具,让工具调用成功率大幅提升。
1. 核心痛点:工具选错、调用失败、不会切换工具
比如用户让Agent"读取Excel文件",基础版工具调用模块只会调用"pandas.read_excel",但如果文件是加密的,就会调用失败;而进阶版需要先判断文件是否加密,如果是,就先调用"解密工具",再调用"读取工具"。
2. 进阶技巧1:工具优先级与智能选择,选对最合适的
同一个任务可能有多个工具可用,比如"数据分析"可以用pandas,也可以用Spark,进阶版需要根据"任务规模、环境限制、执行效率"选择最合适的工具。
实现方式:给每个工具设置"优先级+适用条件",调用时先判断适用条件,再按优先级选择。
代码实现思路:
python
# 工具注册与管理:定义每个工具的适用条件和优先级
tool_registry = [
{
"name": "pandas_analyze",
"strategy": "数据分析",
"applicable_conditions": lambda context: context.get("data_size") < 100000, # 数据量小于10万行
"priority": 1, # 优先级1(高)
"function": Tools.pandas_analyze
},
{
"name": "spark_analyze",
"strategy": "数据分析",
"applicable_conditions": lambda context: context.get("data_size") >= 100000, # 数据量大于等于10万行
"priority": 2, # 优先级2(低)
"function": Tools.spark_analyze
}
]
# 进阶版工具调用模块
class AdvancedToolCallingModule:
def __init__(self):
self.tool_registry = tool_registry
def call_tool(self, strategy, context, params):
# 1. 筛选出适用于当前策略和上下文的工具
suitable_tools = [
tool for tool in self.tool_registry
if tool["strategy"] in strategy and tool["applicable_conditions"](context)
]
# 2. 按优先级排序(优先级数字越小,优先级越高)
suitable_tools.sort(key=lambda x: x["priority"])
if not suitable_tools:
return {"status": "fail", "message": f"没有找到适用的工具:{strategy}"}
# 3. 依次调用工具,直到成功(容错机制)
for tool in suitable_tools:
try:
result = tool["function"](**params)
if result["status"] == "success":
return result
else:
print(f"工具{tool['name']}调用失败,原因:{result['message']},尝试下一个工具")
except Exception as e:
print(f"工具{tool['name']}抛出异常,原因:{str(e)},尝试下一个工具")
# 所有工具都调用失败
return {"status": "fail", "message": f"所有适用工具都调用失败:{strategy}"}
# 使用示例
context = {"data_size": 150000} # 数据量15万行
tool_module = AdvancedToolCallingModule()
result = tool_module.call_tool("数据分析", context, {"df": large_df})
# 会优先调用spark_analyze工具,因为数据量超过10万行
这个技巧的核心是"适用条件筛选+优先级排序+容错机制",确保工具调用的成功率和效率。
3. 进阶技巧2:异常处理与重试机制,调用更稳
工具调用失败是常有的事(比如网络超时、参数错误、文件损坏),进阶版需要加入"异常处理+重试机制"------比如网络超时就重试3次,参数错误就自动修正参数,文件损坏就提示用户。
代码实现思路:
python
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
class RobustTools:
# 带重试机制的CSV读取工具
@staticmethod
@retry(
stop=stop_after_attempt(3), # 最多重试3次
wait=wait_exponential(multiplier=1, min=2, max=10), # 重试间隔:2秒、4秒、8秒
retry=retry_if_exception_type((requests.exceptions.Timeout, IOError)) # 只对超时和IO异常重试
)
def read_csv_robust(file_path: str, encoding: str = "utf-8") -> dict:
try:
# 尝试用utf-8编码读取
df = pd.read_csv(file_path, encoding=encoding)
return {"status": "success", "data": df, "message": "读取成功"}
except UnicodeDecodeError:
# 编码错误,自动尝试gbk编码
try:
df = pd.read_csv(file_path, encoding="gbk")
return {"status": "success", "data": df, "message": "编码错误,自动切换gbk编码读取成功"}
except Exception as e:
return {"status": "fail", "data": None, "message": f"编码错误,尝试utf-8和gbk均失败:{str(e)}"}
except Exception as e:
# 其他异常,交给重试机制处理
raise e
# 工具调用模块整合健壮工具
class AdvancedToolCallingModule:
def __init__(self):
self.tools = RobustTools()
def call_tool(self, strategy, params):
if "读取CSV文件" in strategy:
return self.tools.read_csv_robust(**params)
# 其他工具同理...
这个技巧的核心是"针对性异常处理+指数退避重试",能解决大部分工具调用失败的问题,让Agent的工具调用更稳定、更可靠。
五、总结:模块进阶的核心是"更智能、更容错、更适配"
聊完四个模块的进阶技巧,咱们可以总结一下核心思路:
- 感知模块:从"被动收集"到"主动探索+跨源融合",解决"信息不全"的问题;
- 记忆模块:从"简单存储"到"向量数据库+语义检索",解决"检索不准、速度慢"的问题;
- 决策模块:从"固定拆分"到"规则校验+动态调整",解决"步骤不合理、不会修正"的问题;
- 工具调用模块:从"固定映射"到"智能选择+异常处理",解决"工具选错、调用失败"的问题。
其实每个模块的进阶,都是围绕"更贴近实际场景"------实际场景中信息是分散的、记忆是海量的、决策是需要调整的、工具调用是可能失败的,进阶技巧就是为了应对这些"不确定性",让Agent从"实验室Demo"变成"能落地的实用工具"。
下一节,咱们就进入实战环节,用LangChain+向量数据库,手把手教你开发一个完整的"代码生成与优化Agent",把前面学的模块进阶技巧全部落地,让你真正做到"学以致用"。
咱们下一节不见不散!
