16-day4-鲁棒性-外挂工具协作_实验3

📚 16-day4-鲁棒性-外挂工具协作_实验3

本教程面向开发者或技术使用者,
说明如何将一个独立的 Python 占卜程序作为“工具”接入智能体(Agent),
实现自然语言驱动的自动占卜功能。


一、项目目标

  • 将原有的命令行金钱卦程序(money_divination/main.py)改造为 可被智能体调用的函数模块
  • 在 LangChain Agent 中注册该功能为 @tool
  • 用户只需用自然语言提问(如“我该不该辞职?”),Agent 自动调用占卜工具并返回完整卦象分析

二、目录结构说明

你的项目采用模块化设计,结构如下:

your_project/
├── robust_agent_3.py          ← 主智能体程序(入口)
└── money_divination/          ← 外置占卜程序(作为独立模块)
    ├── core/
    │   ├── __init__.py        ← 使 core 成为 Python 包
    │   ├── coin_toss.py       ← 模拟掷铜钱
    │   ├── parse_gua.py       ← 解析爻线生成卦象
    │   ├── lookup.py          ← 查询卦辞与爻辞(读取 CSV)
    └── └── divination_tool.py ← ✨ 新增:纯函数接口,供 Agent 调用
    ├── data/
    │   ├── hexagrams.csv      ← 六十四卦数据
    │   └── yao_dict.csv       ← 爻辞数据
    └── main.py                ← 原始命令行版本(保留,可独立运行)

关键点
divination_tool.py 是连接两个系统的桥梁——它不包含任何交互逻辑,只提供 perform_divination(question: str) -> str 函数。


三、核心改造步骤

步骤 1:创建纯函数接口(divination_tool.py

# money_divination/core/divination_tool.py
from datetime import datetime
from .coin_toss import toss_six_times_with_text
from .parse_gua import parse_gua
from .lookup import get_hexagram_meaning, get_all_moving_yao_texts

def perform_divination(question: str) -> str:
    """执行一次完整占卜,返回格式化结果字符串(无副作用)"""
    # ...(内部逻辑:摇卦 → 解析 → 查询 → 拼接结果)
    return "\n".join(output_lines)

🔒 该函数:

  • 不使用 input()print()pyperclip
  • 不依赖全局状态
  • 输入仅为问题字符串,输出仅为结果字符串
  • 完全可测试、可复用、可被 Agent 安全调用

步骤 2:在智能体中注册为工具(robust_agent_3.py

# 导入外置模块
from money_divination.core.divination_tool import perform_divination

@tool
def divination(query: str):
    """
    使用《周易》金钱卦进行占卜。
    示例:divination("我今年财运如何?")
    """
    try:
        return perform_divination(query)
    except Exception as e:
        return f"占卜失败:{str(e)}"

✅ 注意:

  • 工具名 divination 会出现在 Agent 的可用工具列表中
  • Docstring 是 Agent 决定是否调用此工具的关键依据

步骤 3:加入工具列表并运行

tools = [get_current_time, divide, is_leap_year, search_web, divination]

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, ...)

完整示例

pip install pyperclip
cd day4   
wget http://10.7.164.5/money_divination.tar . 
tar -xf money_divination.tar
tee robust_agent_3.py <<'EOF'
# robust_agent_3.py
import os
from datetime import datetime
from dotenv import load_dotenv
from langchain_core.tools import tool
from langchain.agents import AgentExecutor, create_react_agent
from langchain import hub
from langchain_openai import ChatOpenAI

from money_divination.core.divination_tool import perform_divination

# 加载 API Key
load_dotenv()

@tool
def get_current_time(dummy: str = ""):
    """获取当前日期和时间"""
    return datetime.now().strftime("%Y年%m月%d日 %H:%M")

@tool
def divide(a_str: str) -> str:
    """
    安全除法计算:输入格式为 'a,b',返回 a / b 的结果。
    示例输入: "10,3" → 输出: "3.333..."
    """
    try:
        parts = a_str.split(",")
        if len(parts) != 2:
            return "错误:请输入两个数字,用逗号分隔,如 '10,2'"
        a = float(parts[0].strip())
        b = float(parts[1].strip())
        if b == 0:
            return "错误:除数不能为零!"
        result = a / b
        return str(result)
    except ValueError:
        return "错误:请输入有效的数字"
    except Exception as e:
        return f"计算失败: {str(e)}"

@tool
def is_leap_year(year_str: str):
    """
    判断指定年份是否为闰年。
    输入:年份(字符串),如 "2024"
    输出:"2024年是闰年" 或 "2023年不是闰年"
    """
    try:
        year = int(year_str.strip())
        is_leap = (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
        if is_leap:
            return f"{year}年是闰年"
        else:
            return f"{year}年不是闰年"
    except ValueError:
        return "错误:请输入有效的年份(如 2024)"
    except Exception as e:
        return f"判断失败: {str(e)}"

@tool
def search_web(query: str):
    """
    模拟网页搜索(仅返回固定摘要,避免真实爬虫问题)
    实际项目应替换为合法搜索引擎 API(如 SerpAPI)
    """
    return f"(模拟)关于 '{query}' 的搜索结果摘要:这是一个演示响应。"

@tool
def divination(query: str):
    """
    使用《周易》金钱卦进行占卜。
    输入:用户想问的问题(字符串)
    输出:完整的占卜结果(包含卦象、卦辞、爻辞等)
    示例:divination("我今年能升职吗?")
    """
    try:
        return perform_divination(query)
    except Exception as e:
        return f"占卜失败:{str(e)}"

# 初始化 Qwen 模型
llm = ChatOpenAI(
    model="qwen-max",
    temperature=0,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=os.getenv("DASHSCOPE_API_KEY")
)

# 注册所有工具
tools = [get_current_time, divide, is_leap_year, search_web, divination]

# 加载 ReAct 提示模板
prompt = hub.pull("hwchase17/react")

# 创建 Agent
agent = create_react_agent(llm, tools, prompt)

# 创建执行器
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    handle_parsing_errors=True,
    max_iterations=6
)

# 交互式主循环
print("🛡️ Day 4:鲁棒智能体(多工具 + 错误处理)")
print("尝试提问:")
print("- 计算 100 除以 0")
print("- 2024年是闰年吗?")
print("- 现在几点?再算一下 2024 除以 4")
print("- 工具里面有一个周易,可以问建议")
print("- 输入 quit 退出\n")

while True:
    try:
        user_input = input("💬 问题: ").strip()
        if not user_input:
            continue
        if user_input.lower() in {"quit", "exit", "q"}:
            print("👋 再见!")
            break

        result = agent_executor.invoke({"input": user_input})
        print("\n" + "=" * 60)
        print("🤖 回答:")
        print(result["output"])
        print()

    except KeyboardInterrupt:
        print("\n👋 被中断,再见!")
        break
    except Exception as e:
        print(f"❌ 系统错误: {e}\n")

EOF

四、使用示例

python robust_agent_3.py

用户输入:

💬 问题: 我该接受这份新工作 offer 吗?

Agent 行为:

  1. 分析问题语义,识别出涉及“决策”“未来”“建议”
  2. 决定调用 divination 工具
  3. 执行 perform_divination("我该接受这份新工作 offer 吗?")
  4. 返回完整卦象(含本卦、之卦、动爻、卦辞、爻辞)

输出片段示例:

🔮 金钱卦占卜结果 (2026年01月28日 22:15)
所问之事:我该接受这份新工作 offer 吗?
本卦(现状):水火既济
之卦(趋势):地火明夷
动爻:[3]
📜 卦辞(水火既济):
既济:亨小,利贞;初吉终乱。
⚡ 动爻爻辞:
  第3爻:高宗伐鬼方,三年克之,小人勿用。
💡 提示:有动爻,动爻表示变化的关键,需特别关注。

五、优势与设计理念

特性 说明
解耦设计 占卜逻辑完全独立于智能体,便于单独测试或替换
可维护性 修改数据(CSV)无需改动 Agent 代码
安全性 无网络请求、无文件写入、无用户输入阻塞
扩展性 未来可轻松添加其他工具

六、常见问题(FAQ)

Q1:为什么不能直接调用 main.py

A:main.py 包含 input()print(),会在 Agent 调用时卡住或产生混乱输出。必须改造成无副作用的纯函数

Q2:如果占卜模块路径变了怎么办?

A:只要保持 money_divination/ 在项目根目录,并从根目录运行脚本,Python 就能自动找到它。不要随意移动目录。

Q3:能否让 Agent 自动判断何时需要占卜?

A:是的!关键在于 @tool 的 docstring 描述。你可以优化描述,例如:

"""当用户询问关于人生决策、运势、未来趋势等问题时,调用此工具进行《周易》占卜。"""

七、后续优化建议

  • ✅ 添加单元测试(test_divination_tool.py
  • ✅ 支持自定义铜钱正反面规则(通过参数)
  • ✅ 将结果转为 JSON 格式,便于前端展示
  • ✅ 集成真实搜索引擎(替换 search_web

🌟 总结
通过“外置模块 + 纯函数接口 + LangChain Tool”,将传统文化智慧融入现代 AI 智能体,实现了 “问事即占,有分析过程,有简明扼要的解释” 的体验!


📄 附:运行前提

  • Python ≥ 3.9
  • 安装依赖:pip install langchain langchain-openai python-dotenv pyperclip
  • 设置环境变量:DASHSCOPE_API_KEY=your_key(在 .env 文件中)
posted @ 2026-01-28 22:01  船山薪火  阅读(22)  评论(0)    收藏  举报
![image](https://img2024.cnblogs.com/blog/3174785/202601/3174785-20260125205854513-941832118.jpg)