从脚本到Agent:工具模式下的智能价值

📋 本文目录


一、前言

1.1 本节内容简介

我们已经有了5个好用的工具,但问题来了:用户怎么知道该调用哪个工具?

本文将对比两种使用工具的方式:

  • 方式1:写死的脚本,按固定流程调用所有工具

  • 方式2:用Agent,让它根据问题自动选择合适的工具

看完你会明白,为什么Agent能让工具的价值翻倍!

1.2 为什么要学习本节内容?

  • 理解差异:明白脚本和Agent各自适合什么场景

  • 智能选择:让Agent根据用户需求自动选择工具

  • 实战完整:从工具开发到智能应用的完整闭环


二、两种方式对比

在开始写代码之前,先让我们看看这两种方式的区别。

2.1 方式1:脚本调用(固定流程)

就像我们的 tool_chain_demo.py 那样:

复制代码
用户说:"帮我分析一下"
    ↓
脚本说:"好的,我按顺序来一遍"
    ↓
[工具1] → [工具2] → [工具3] → [工具4] → [工具5]
    ↓
输出:5个文件

特点:

  • ✅ 流程固定, predictable

  • ✅ 简单直接,不容易出错

  • ❌ 不管用户需要什么,都跑完所有工具

  • ❌ 浪费资源,效率不高

  • ❌ 用户需要自己知道该用什么工具

适用场景:

  • 固定的批量处理任务

  • 每天例行的报表生成

  • 标准化的数据处理流程

2.2 方式2:Agent智能调用

就像我们即将看到的那样:

复制代码
用户说:"帮我看看有多少错误"
    ↓
Agent思考:"这个问题需要分析错误,用工具3"
    ↓
[工具3]
    ↓
输出:错误统计结果

用户说:"生成一份完整报告"
    ↓
Agent思考:"这个需要先结构化,再生成报告"
    ↓
[工具1] → [工具5]
    ↓
输出:完整报告

特点:

  • ✅ 按需调用,不浪费

  • ✅ 自然语言交互,用户友好

  • ✅ 可以处理复杂、模糊的问题

  • ⚠️ 需要大模型,有一定成本

  • ⚠️ 可能选择错误的工具(需要调试)

适用场景:

  • 用户自助查询系统

  • 智能助手、客服机器人

  • 需要灵活应对各种问题的场景

2.3 对比总结表

维度 脚本调用 Agent调用
灵活性 低(固定流程) 高(按需选择)
易用性 需要技术知识 自然语言即可
资源使用 每次都跑完所有工具 只用需要的工具
开发成本 中(需要大模型)
适用场景 固定任务 多变的用户需求

三、工具链完整演示

3.1 工具链流程图

复制代码
原始日志
    ↓
[工具1] parse_log → 结构化JSON
    ↓
    ├─→ [工具3] analyze_errors → 错误统计
    ├─→ [工具5] generate_report → 完整报告
    ├─→ [工具2] convert_timestamps → 人类可读格式
    └─→ [工具4] summarize_communication → 通信汇总

3.2 完整工具链代码

复制代码
"""
工具链完整演示脚本
展示5个工具如何联动工作
"""
import sys
import os

# 添加当前目录到路径,方便导入工具
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from tool_1_parse_log import parse_log
from tool_2_convert_timestamps import convert_timestamps
from tool_3_analyze_errors import analyze_errors
from tool_4_summarize_communication import summarize_communication
from tool_5_generate_report import generate_report


def print_section(title):
    """打印分节标题"""
    print("\n" + "="*80)
    print(f"  {title}")
    print("="*80)


def main():
    print_section("LangChain 工具链完整演示")
    print("展示5个工具如何联动分析嵌入式设备日志")

    # 步骤1: 读取原始日志文件
    print_section("步骤 1: 读取原始日志")
    log_file = "sample_device.log"
    print(f"读取文件: {log_file}")

    with open(log_file, 'r', encoding='utf-8') as f:
        raw_log = f.read()
    print(f"日志行数: {len(raw_log.splitlines())}")

    # 步骤2: 使用工具1 - 结构化解析
    print_section("步骤 2: 工具1 - 日志结构化解析")
    print("调用 parse_log()...")
    parsed_json = parse_log.invoke(raw_log)
    parsed_file = "output_parsed.json"
    with open(parsed_file, 'w', encoding='utf-8') as f:
        f.write(parsed_json)
    print(f"结果已保存到: {parsed_file}")
    print(f"结果预览:\n{parsed_json[:300]}...")

    # 步骤3: 使用工具2 - 时间戳转换(给人看的格式)
    print_section("步骤 3: 工具2 - 时间戳格式转换")
    print("调用 convert_timestamps()...")
    readable_log = convert_timestamps.invoke(raw_log)
    readable_file = "output_readable.log"
    with open(readable_file, 'w', encoding='utf-8') as f:
        f.write(readable_log)
    print(f"结果已保存到: {readable_file}")
    print(f"结果预览:\n{readable_log[:300]}...")

    # 步骤4: 使用工具3 - 错误统计(使用工具1的输出)
    print_section("步骤 4: 工具3 - 错误统计分析")
    print("调用 analyze_errors() (使用工具1的输出)...")
    error_report = analyze_errors.invoke(parsed_json)
    error_file = "output_errors.txt"
    with open(error_file, 'w', encoding='utf-8') as f:
        f.write(error_report)
    print(f"结果已保存到: {error_file}")
    print(f"结果:\n{error_report}")

    # 步骤5: 使用工具4 - 通信汇总
    print_section("步骤 5: 工具4 - 通信记录汇总")
    print("调用 summarize_communication()...")
    comm_report = summarize_communication.invoke(raw_log)
    comm_file = "output_communication.txt"
    with open(comm_file, 'w', encoding='utf-8') as f:
        f.write(comm_report)
    print(f"结果已保存到: {comm_file}")
    print(f"结果:\n{comm_report}")

    # 步骤6: 使用工具5 - 生成完整报告(使用工具1的输出)
    print_section("步骤 6: 工具5 - 生成完整分析报告")
    print("调用 generate_report() (使用工具1的输出)...")
    final_report = generate_report.invoke(parsed_json)
    report_file = "output_final_report.md"
    with open(report_file, 'w', encoding='utf-8') as f:
        f.write(final_report)
    print(f"结果已保存到: {report_file}")
    print(f"结果:\n{final_report}")

    # 完成总结
    print_section("工具链演示完成")
    print("生成的文件列表:")
    output_files = [
        parsed_file,
        readable_file,
        error_file,
        comm_file,
        report_file
    ]
    for f in output_files:
        print(f"  - {f}")

    print("\n工具链流程回顾:")
    print("  原始日志 -> [工具1] -> 结构化JSON")
    print("                  |")
    print("                  +----> [工具3] -> 错误统计")
    print("                  |")
    print("                  +----> [工具5] -> 完整报告")
    print("                  |")
    print("                  +----> [工具2] -> 人类可读格式")
    print("                  |")
    print("                  +----> [工具4] -> 通信汇总")


if __name__ == "__main__":
    main()

3.3 运行工具链

复制代码
cd 01_tool_use
python tool_chain_demo.py

3.4 生成的输出文件

  • output_parsed.json(工具1的输出)

  • output_readable.log(工具2的输出)

  • output_errors.txt(工具3的输出)

  • output_communication.txt(工具4的输出)

  • output_final_report.md(工具5的输出)


四、Agent 整合实战

4.1 前置要求

  • 安装并启动 Ollama:访问 https://ollama.com

  • 拉取模型:ollama pull qwen2.5:3b-instruct

4.2 交互式 Agent 完整代码(简化可运行版)

复制代码
"""
交互式 Agent - 简化可运行版
直接调用 Ollama API,不依赖复杂框架
"""
import requests
import sys

# 导入我们的工具
from tool_1_parse_log import parse_log
from tool_2_convert_timestamps import convert_timestamps
from tool_3_analyze_errors import analyze_errors
from tool_4_summarize_communication import summarize_communication
from tool_5_generate_report import generate_report

OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "qwen2.5:3b-instruct"

# 工具定义
tools = {
    "parse_log": {
        "name": "parse_log",
        "description": "解析日志文件,把原始日志转换成结构化的JSON格式",
        "function": parse_log
    },
    "convert_timestamps": {
        "name": "convert_timestamps",
        "description": "把时间戳转换成人类可读的格式",
        "function": convert_timestamps
    },
    "analyze_errors": {
        "name": "analyze_errors",
        "description": "分析日志中的错误,统计错误出现的次数",
        "function": analyze_errors
    },
    "summarize_communication": {
        "name": "summarize_communication",
        "description": "汇总日志中的通信记录",
        "function": summarize_communication
    },
    "generate_report": {
        "name": "generate_report",
        "description": "生成完整的分析报告",
        "function": generate_report
    }
}

def load_log():
    """加载日志文件"""
    with open('sample_device.log', 'r', encoding='utf-8') as f:
        return f.read()

def call_ollama(prompt, max_tokens=200):
    """调用 Ollama API"""
    try:
        response = requests.post(
            OLLAMA_URL,
            json={
                "model": MODEL_NAME,
                "prompt": prompt,
                "stream": False,
                "options": {
                    "temperature": 0.1,
                    "num_predict": max_tokens
                }
            },
            timeout=60
        )
        if response.status_code == 200:
            return response.json().get('response', '')
        else:
            return f"Error: {response.status_code}"
    except Exception as e:
        return f"Error: {e}"

def select_tool(user_question):
    """根据问题选择合适的工具"""
    tool_names = list(tools.keys())
    tool_descriptions = "\n".join([f"- {name}: {tools[name]['description']}" for name in tool_names])
    
    prompt = f"""你是一个日志分析助手。用户问了一个问题,请根据问题选择最合适的工具。

可用工具:
{tool_descriptions}

用户问题:{user_question}

请只返回工具名称(不要返回其他内容),例如:analyze_errors"""

    response = call_ollama(prompt, max_tokens=30)
    response = response.strip()
    
    # 确保返回的是有效的工具名
    for tool_name in tool_names:
        if tool_name in response:
            return tool_name
    
    # 默认返回错误分析
    return "analyze_errors"

def main():
    print("="*80)
    print("交互式 Agent - 简化可运行版")
    print("="*80)
    print("\n可用工具:")
    for name, info in tools.items():
        print(f"  - {name}: {info['description']}")
    
    print("\n" + "="*80)
    print("加载日志文件...")
    log_content = load_log()
    print(f"[OK] 日志加载成功,共 {len(log_content.splitlines())} 行")
    
    print("\n" + "="*80)
    print("开始对话!")
    print("="*80)
    print("--- 你可以尝试 ---")
    print("1. 帮我分析一下日志中的错误")
    print("2. 把时间戳转换成人类可读格式")
    print("3. 统计一下通信记录")
    print("4. 生成一份完整的分析报告")
    print("5. 退出: q 或 quit")
    print("="*80)
    
    while True:
        try:
            user_input = input("\n请输入你的问题: ").strip()
            
            if user_input.lower() in ['q', 'quit', 'exit']:
                print("再见!")
                break
                
            if not user_input:
                print("请输入一个问题")
                continue
            
            print(f"\n[1/3] 理解问题...")
            selected_tool = select_tool(user_input)
            print(f"[OK] 选择工具: {selected_tool}")
            
            print(f"\n[2/3] 调用工具...")
            tool_func = tools[selected_tool]['function']
            
            # 根据工具决定输入
            if selected_tool in ['analyze_errors', 'generate_report']:
                # 需要结构化输入
                parsed = parse_log.invoke(log_content)
                result = tool_func.invoke(parsed)
            else:
                # 直接用原始日志
                result = tool_func.invoke(log_content)
            
            print(f"[OK] 工具调用完成")
            
            print(f"\n[3/3] 整理结果...")
            summary_prompt = f"""用户问:{user_input}

工具执行结果:
{result}

请用自然语言总结这个结果。"""
            
            summary = call_ollama(summary_prompt, max_tokens=300)
            
            print("\n" + "="*80)
            print("Agent 回答:")
            print("="*80)
            print(summary)
            print("\n--- 原始结果 ---")
            print(result[:500])
            if len(result) > 500:
                print("... (结果太长,已截断)")
            
        except KeyboardInterrupt:
            print("\n再见!")
            break
        except Exception as e:
            print(f"\n执行出错: {e}")
            import traceback
            traceback.print_exc()

if __name__ == "__main__":
    main()

4.3 运行交互式 Agent

步骤1:启动 Ollama 服务
复制代码
ollama serve
步骤2:运行交互式 Agent(推荐)
复制代码
cd 01_tool_use
python working_interactive_agent.py
你可以尝试的问题:
  1. "帮我分析一下日志中的错误"

  2. "把时间戳转换成人类可读格式"

  3. "统计一下通信记录"

  4. "生成一份完整的分析报告"

运行演示:
复制代码
请输入你的问题: 帮我分析下日志中的错误

[1/3] 理解问题...
[OK] 选择工具: analyze_errors

[2/3] 调用工具...
[OK] 工具调用完成

[3/3] 整理结果...

================================================================================
Agent 回答:
================================================================================
在分析的日志中,共检测到5个错误,其中 "scheme type[1] id[1] not found!!" 出现了4次,"scheme type[1] id[2] not found!!" 出现了1次。

--- 原始结果 ---
错误统计:
总计:5个错误
  4次:scheme type[1] id[1] not found!!
  1次:scheme type[1] id[2] not found!!
快速测试(不用交互):
复制代码
python quick_demo.py

五、Agent 的价值在哪里

看到这里,你可能会问:Agent不就是自动调用工具吗?有什么了不起的?

让我用一个真实的场景来说明Agent的价值:

5.1 场景对比:客服处理问题

传统方式(没有Agent):

复制代码
用户:"我的设备连接不上了"
    ↓
客服:"好的,请按以下步骤操作:
    1. 先把日志发给我
    2. 我用工具1解析一下
    3. 然后用工具3看看有没有错误
    4. 再用工具4检查通信
    ..."
    ↓
(需要10分钟,客服需要懂技术)

有Agent的方式:

复制代码
用户:"我的设备连接不上了"
    ↓
Agent:[自动调用工具1 → 工具3 → 工具4]
    ↓
Agent:"我帮你分析了日志,发现3个错误:
    1. scheme type[1] id[1] not found(出现3次)
    2. 建议检查设备ID配置"
    ↓
(需要30秒,用户不需要懂技术)

5.2 Agent 的核心价值

价值点 说明
降低使用门槛 用户不需要知道该调用哪个工具,用自然语言提问就行
按需调用 不会浪费资源调用不需要的工具,只做必要的事
自然交互 可以处理模糊、不完整的问题,不需要严格格式
上下文理解 可以基于对话历史,持续跟进处理复杂问题
解释能力 可以解释为什么选择这个工具,让结果更可信

5.3 什么时候该用Agent?

✅ 适合用Agent的场景:

  • 面向非技术用户的系统

  • 问题多样,无法预知所有情况

  • 需要自然语言交互

  • 工具之间有多种组合方式

❌ 不适合用Agent的场景:

  • 非常固定的批量处理任务

  • 对性能有极致要求(Agent有额外开销)

  • 完全不能容忍错误的场景


六、总结与展望

6.1 本系列要点总结

要点 说明
✅ 理解了 Agent 工具模式 工具是 Agent 的核心扩展能力
✅ 掌握了工具四要素 装饰器、文档字符串、类型注解、实现逻辑
✅ 实现了 5 个实用工具 从日志解析到报告生成
✅ 掌握了工具链整合 多个工具联动工作
✅ 理解了两种方式的区别 脚本 vs Agent,各有所长
✅ 实现了 Agent 调用工具 让 Agent 智能选择和调用工具

6.2 系列结束

感谢你学习完本系列!希望这些内容对你有帮助。记住:工具本身只是基础,如何用Agent让它们智能化,才是真正的价值所在。


📚 参考资源

资源 链接
LangChain Tools 文档 https://python.langchain.com/docs/modules/tools/
Ollama 官方网站 https://ollama.com

点赞 + 关注,更新不迷路!🚀

相关推荐
weixin_436182424 小时前
工业 AI 芯片如何选型?告别纸质手册,实现快速比对
人工智能·ai芯片·ai助手
糖果店的幽灵4 小时前
Part 2: Models(模型)
microsoft·langchain
searchforAI4 小时前
视频画面里的PPT怎么提取?视频转图文讲义的实操教程
人工智能·学习·ai·aigc·powerpoint·音视频·贴图
Rain5094 小时前
mini-cc:一个轻量级 AI 编程助手的诞生
人工智能·typescript·ai编程
hyunbar4 小时前
Fish Audio(鱼声)+ Python:零门槛用自己声音合成任何文本
人工智能
厚国兄4 小时前
Agent_Skills_万千应用_第03篇_PPT 生成 Skill:从资料到可演示幻灯片
人工智能·powerpoint·agent
o561路6o623o74 小时前
陈,跳台记录仪 大鼠跳台记录仪 小鼠跳台记录仪
人工智能
Swift社区4 小时前
AI + 鸿蒙 App:下一代应用架构
人工智能·架构·harmonyos