我的第一个工具调用Agent:从零构建“知识库+计算器+时间+文件”四合一智能体
从RAG到Agent我用一个周末实现了AI从知道到做到的跃迁一、引言为什么从RAG升级到Agent作为制造业数字化转型从业者2026年上半年我完成了几个本地化AI应用实践——环境搭建、多模态图搜、RAG知识库问答甚至还把橘子洲头做成了AI客服。这些应用让AI知道了很多事但总感觉缺了点什么AI只能被动回答问题不能主动调用工具去解决问题。直到我开始接触AI Agent才真正理解了这个核心差异RAG检索增强生成AI 大脑模型 资料库知识库能知道并回答Agent智能体AI 大脑模型 资料库知识库 手脚工具能做到并完成本案例的目标是构建一个具备知识库检索、数学计算、时间查询、文件读写四项能力的Agent通过实践完整理解Agent的核心机制。这对于我们后续在制造企业落地数据质量巡检、主数据处理、数仓分层设计等场景具有直接的参考价值。运行效果图二、技术方案与选型我的开发环境比较特殊可能也代表了一部分开发者的现状Windows 11 WSL2Ubuntu 22.04 32GB内存 无独显大模型通过Ollama安装在Windows侧提供API服务代码在WSL中运行。组件选型说明大模型Qwen2.5:7BOllama中文友好7B参数量在CPU上可运行Agent框架LangChain 0.3.x社区成熟ReAct模式原生支持向量数据库Chroma轻量级与之前RAG案例无缝衔接嵌入模型all-MiniLM-L6-v2384维CPU友好中文效果尚可Web框架Flask轻量级快速构建交互界面工程化原则贯穿整个专栏配置与代码分离config.py工具函数独立封装tools/模块完整的错误处理与日志记录单元测试覆盖每个工具函数项目结构清晰可一键运行三、项目结构工程化的起点case1_tool_agent/ ├── config.py # 配置集中管理路径、模型、端口 ├── requirements.txt # 依赖锁定版本 ├── .env.example # 环境变量模板 ├── tools/ # 工具模块可复用 │ ├── __init__.py │ ├── calculator.py # 计算器工具 │ ├── time_tool.py # 时间工具 │ ├── file_tool.py # 文件读写工具 │ └── rag_retriever.py # 知识库检索工具 ├── agent/ # Agent核心 │ ├── __init__.py │ └── builder.py # Agent构建工厂 ├── web/ # Web服务 │ ├── app.py # Flask主应用 │ └── templates/ │ └── index.html # 极简Chat界面 ├── scripts/ # 辅助脚本 │ ├── test_tools.py # 工具单元测试 │ └── test_cli.py # 命令行交互测试 ├── chroma_db/ # 知识库复用已有 │ └── chroma.sqlite3 └── workspace/ # 文件工具工作目录工程心得我一直信奉好的项目结构是成功的一半。清晰的模块划分让工具可以在后续案例中直接复用配置集中管理避免硬编码单元测试保障每次修改不引入新Bug。四、核心实现四个工具的定义与编码4.1 计算器工具tools/calculator.py# -*- coding: utf-8 -*- # author: javy21 # blog: https://blog.csdn.net/javy21 计算器工具执行数学表达式计算 import logging from langchain.tools import tool logger logging.getLogger(__name__) tool def calculate(expression: str) - str: 执行数学计算输入数学表达式返回计算结果。 Args: expression: 数学表达式如 35 或 10*2/3 Returns: 计算结果字符串或错误信息 # 安全检查只允许数字、运算符、括号、空格 allowed_chars set(0123456789-*/().% ) if not all(c in allowed_chars for c in expression): error_msg f表达式包含非法字符{expression} logger.warning(error_msg) return f计算错误{error_msg} try: result eval(expression) logger.info(f计算成功: {expression} {result}) return f计算结果{result} except ZeroDivisionError: return 计算错误除数不能为零 except Exception as e: return f计算错误表达式格式错误 - {str(e)}设计要点使用tool装饰器将函数转换为LangChain工具输入校验防止代码注入生产环境建议用numexpr完整的异常处理返回友好信息而非堆栈4.2 时间工具tools/time_tool.py# -*- coding: utf-8 -*- # author: javy21 # blog: https://blog.csdn.net/javy21 时间工具获取当前日期和时间 import logging from datetime import datetime from langchain.tools import tool logger logging.getLogger(__name__) tool def get_current_time(format: str %Y-%m-%d %H:%M:%S) - str: 获取当前日期和时间可指定输出格式。 Args: format: 时间格式字符串默认 %Y-%m-%d %H:%M:%S Returns: 格式化后的当前时间字符串 now datetime.now() result now.strftime(format) logger.info(f获取当前时间: {result}) return result4.3 文件读写工具tools/file_tool.py# -*- coding: utf-8 -*- # author: javy21 # blog: https://blog.csdn.net/javy21 文件读写工具在workspace目录下读写文件防路径穿越 import logging from pathlib import Path from langchain.tools import tool from config import WORKSPACE_DIR logger logging.getLogger(__name__) tool def read_file(filename: str) - str: 读取指定文件的内容。 # 安全检查防止路径穿越攻击 if .. in filename or filename.startswith(/): return 读取失败非法文件名 filepath WORKSPACE_DIR / filename if not filepath.exists(): return f读取失败文件 {filename} 不存在 try: content filepath.read_text(encodingutf-8) logger.info(f读取文件成功: {filename}) return f文件内容\n{content} except Exception as e: return f读取失败{str(e)} tool def write_file(filename: str, content: str) - str: 将内容写入指定文件。 if .. in filename or filename.startswith(/): return 写入失败非法文件名 filepath WORKSPACE_DIR / filename try: filepath.write_text(content, encodingutf-8) logger.info(f写入文件成功: {filename}) return f成功写入文件{filename} except Exception as e: return f写入失败{str(e)}⚠️安全提醒文件工具是企业场景中最容易出安全问题的环节一定要做好路径穿越防护。4.4 知识库检索工具tools/rag_retriever.py# -*- coding: utf-8 -*- # author: javy21 # blog: https://blog.csdn.net/javy21 知识库检索工具基于Chroma向量库的语义检索 import logging from langchain.tools import tool from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings from config import CHROMA_DIR, EMBEDDING_MODEL, RETRIEVAL_TOP_K logger logging.getLogger(__name__) _vectordb None def _get_vectordb(): 懒加载向量数据库单例模式 global _vectordb if _vectordb is None: logger.info(f正在加载向量数据库: {CHROMA_DIR}) embeddings HuggingFaceEmbeddings(model_nameEMBEDDING_MODEL) _vectordb Chroma( persist_directorystr(CHROMA_DIR), embedding_functionembeddings, ) logger.info(向量数据库加载完成) return _vectordb tool def search_knowledge(query: str) - str: 从知识库中检索与查询相关的文档片段。 try: vectordb _get_vectordb() docs vectordb.similarity_search(query, kRETRIEVAL_TOP_K) if not docs: return 未找到相关信息。 contents [doc.page_content for doc in docs] result \n\n---\n\n.join(contents) logger.info(f检索成功: {query} - {len(docs)} 个片段) return f检索结果\n{result} except Exception as e: return f检索失败{str(e)}五、Agent构建让AI学会使用工具Agent构建是本案例的核心环节代码位于agent/builder.py# -*- coding: utf-8 -*- # author: javy21 # blog: https://blog.csdn.net/javy21 Agent构建器创建和配置LangChain Agent import logging from langchain_community.llms import Ollama from langchain.agents import initialize_agent, AgentType from langchain.memory import ConversationBufferMemory from config import OLLAMA_BASE_URL, MODEL_NAME, TEMPERATURE from tools import calculate, get_current_time, read_file, write_file, search_knowledge logger logging.getLogger(__name__) def create_agent(verbose: bool True): 创建并返回一个配置好的Agent实例 # 1. 初始化大模型 logger.info(f初始化模型: {MODEL_NAME} {OLLAMA_BASE_URL}) llm Ollama( modelMODEL_NAME, base_urlOLLAMA_BASE_URL, temperatureTEMPERATURE, ) # 2. 注册工具顺序影响决策优先级 tools [ search_knowledge, # 知识库检索 calculate, # 计算器 get_current_time, # 时间查询 read_file, # 文件读 write_file, # 文件写 ] # 3. 设置记忆对话缓冲 memory ConversationBufferMemory( memory_keychat_history, return_messagesTrue, ) # 4. 创建Agent使用支持多参数工具的Agent类型 agent initialize_agent( tools, llm, agentAgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, memorymemory, verboseverbose, handle_parsing_errorsTrue, max_iterations10, early_stopping_methodgenerate, ) logger.info(Agent创建成功) return agent关键决策我选择了STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION而非CONVERSATIONAL_REACT_DESCRIPTION因为前者支持多参数工具如write_file需要 filename content 两个参数后者只支持单参数工具。六、Web交互界面极简Chat风格Flask应用提供简洁的聊天界面用户在浏览器中输入问题Agent自动决策并调用相应工具核心路由逻辑web/app.pyapp.route(/api/chat, methods[POST]) def chat(): data request.get_json() user_input data.get(message, ).strip() if not user_input: return jsonify({error: 消息不能为空}), 400 try: response agent.run(user_input) return jsonify({response: response}) except Exception as e: logger.error(f处理失败{str(e)}) return jsonify({error: f处理失败{str(e)}}), 500七、运行效果展示7.1 单元测试通过$ python scripts/test_tools.py 开始工具单元测试 测试计算器... ✅ 计算器测试通过 测试时间工具... ✅ 当前时间: 2026-07-05 22:32:26 测试文件工具... ✅ 文件工具测试通过 测试知识库检索... ✅ 检索结果长度: 1024 字符 ✅ 所有测试通过 7.2 Web交互实测用户输入Agent行为结果现在几点了调用时间工具返回当前时间帮我算一下 123 * 456调用计算器返回 56088十五五规划中关于人工智能的内容调用知识库检索返回相关文档片段把 Hello Agent 写入 test.txt调用文件写工具返回成功信息读取 test.txt 的内容调用文件读工具返回文件内容明天上午10点我要开会帮我算一下还有多少秒组合调用时间计算器计算差值并返回八、踩坑记录与解决方案坑1ModuleNotFoundError: No module named tools.calculator现象运行测试脚本时Python找不到自定义模块。原因直接运行python scripts/test_tools.py时项目根目录不在sys.path中。解决在每个脚本开头添加路径处理python复制下载import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent))坑2向量库为空检索无结果现象search_knowledge总是返回未找到相关信息。原因从之前项目复制的chroma_db只包含空表没有实际向量数据。解决重新构建知识库用PDF文档填充向量数据python复制下载vectordb Chroma.from_documents( documentschunks, embeddingembeddings, persist_directorystr(CHROMA_DIR) )坑3ConversationalAgent does not support multi-input tool现象启动Web服务时报错提示write_file是多参数工具不被支持。原因ConversationalAgent要求所有工具都是单输入只有一个参数。解决更换为AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION该类型支持多参数工具。坑4Ollama连接失败Connection refused现象Agent调用大模型时返回HTTPConnectionPool(hostlocalhost, port11434)... Connection refused。原因我的Ollama安装在Windows上而代码在WSL中运行WSL中的localhost指向WSL自身而非Windows宿主机。解决在Windows上配置Ollama监听所有接口set OLLAMA_HOST0.0.0.0:11434 ollama serve修改config.py中的OLLAMA_BASE_URL为Windows的IP地址九、工程化改进方向让Demo走向生产改进方向实现建议优先级工具描述优化精炼每个工具的description提高模型调用准确率P0日志与监控集成结构化日志如JSON格式便于采集分析P0超时与重试对Ollama调用增加超时和重试机制P1环境变量管理使用.envpython-dotenv管理配置P1容器化部署编写Dockerfile实现一键部署P2十、小结与下篇预告通过本案例我们完整实现了从0到1构建一个工具调用Agent的全过程涵盖了工具定义、Agent构建、Web交互、单元测试、工程化组织等多个维度。在这个过程中我深刻体会到Agent的核心不是调用工具而是决定何时调用什么工具。ReAct模式让AI具备了自主决策的能力这是与传统自动化脚本的本质区别。下篇预告下一篇理论文章《从RAG到AgentAI应用范式的演进——兼谈工具调用在制造业数据管理的落地价值》我将从理论角度深入剖析RAG与Agent的本质区别与演进逻辑ReAct模式的深层理解工具调用的关键设计原则Agent在制造业数据管理数据质量、数仓分层、数据标准中的落地场景敬请期待欢迎在评论区交流您的实践心得或遇到的问题一起探讨、共同成长。作者javy21博客javy21-CSDN博客专栏AI Agent从入门到落地本文案例代码可在评论区获取完整项目源码如果您觉得本文有帮助欢迎交流分享您的支持是我持续输出的动力。

相关新闻

Midjourney企业版开通全流程(含SAML/SCIM/审计日志配置):技术负责人必须掌握的12项合规要点

Midjourney企业版开通全流程(含SAML/SCIM/审计日志配置):技术负责人必须掌握的12项合规要点

更多请点击: https://codechina.net 第一章:Midjourney企业版开通全流程(含SAML/SCIM/审计日志配置):技术负责人必须掌握的12项合规要点 开通Midjourney企业版不仅是账户升级,更是构建企业级AI治理能力的关…

2026/7/12 23:44:57阅读更多 →
WebWalker容器化部署:使用Docker简化LLM网页遍历系统搭建

WebWalker容器化部署:使用Docker简化LLM网页遍历系统搭建

WebWalker容器化部署:使用Docker简化LLM网页遍历系统搭建 引言 在当今数字化时代,大型语言模型(LLM)在网页遍历领域的应用越来越广泛。WebWalker作为一个专注于LLM网页遍历的基准测试系统,为研究人员和开发者提供了一…

2026/7/12 23:39:56阅读更多 →
从0到1部署WebWalker:LLM网页遍历智能体的本地化与规模化实践指南

从0到1部署WebWalker:LLM网页遍历智能体的本地化与规模化实践指南

从0到1部署WebWalker:LLM网页遍历智能体的本地化与规模化实践指南 WebWalker是一个专注于网页遍历的LLM智能体框架,旨在通过多智能体协作解决复杂的网页信息获取任务。本文将详细介绍如何从零开始在本地环境部署WebWalker,并探讨其规模化应用…

2026/7/12 23:39:56阅读更多 →
后端技术栈全面梳理:主流框架与选型建议

后端技术栈全面梳理:主流框架与选型建议

别听那些“全栈工程师”的忽悠,真正决定一个系统生死、一家公司技术负债的,从来都是后端技术栈的选型。前端换框架如同换衣服,后端换语言和基础设施,则无异于给飞行中的飞机换引擎。今天我们就把后端技术栈里那些关键、热门、甚至…

2026/7/13 0:45:07阅读更多 →
3D打印壳体设计对比:AutoCAD vs. 中望3D 2024 在STL导出上的3点差异

3D打印壳体设计对比:AutoCAD vs. 中望3D 2024 在STL导出上的3点差异

3D打印壳体设计深度对比:AutoCAD与中望3D 2024的STL导出实战解析引言在机械设计领域,壳体结构的3D建模与打印已成为产品原型开发的关键环节。AutoCAD作为行业老牌CAD软件,与国产新锐中望3D 2024在壳体设计和STL导出流程上存在显著差异。本文将…

2026/7/13 0:45:07阅读更多 →
从单轮问答到全流程自治:ChatGPT多步骤任务构建的3个分水岭阶段(仅0.3%高级用户掌握的SOP)

从单轮问答到全流程自治:ChatGPT多步骤任务构建的3个分水岭阶段(仅0.3%高级用户掌握的SOP)

更多请点击: https://kaifayun.com 第一章:从单轮问答到全流程自治:ChatGPT多步骤任务构建的演进本质 交互范式的根本跃迁 早期大语言模型以单轮问答为核心能力,用户输入一个问题,模型返回一个静态响应。而现代ChatG…

2026/7/13 0:45:07阅读更多 →
ChatGPT长程任务失效真相:上下文溢出、状态漂移、意图衰减——3类致命故障的实时拦截方案

ChatGPT长程任务失效真相:上下文溢出、状态漂移、意图衰减——3类致命故障的实时拦截方案

更多请点击: https://intelliparadigm.com 第一章:ChatGPT长程任务失效真相:上下文溢出、状态漂移、意图衰减——3类致命故障的实时拦截方案 当ChatGPT处理超过8–10轮交互的复杂任务(如多阶段代码调试、跨文档合同比对、渐进式需…

2026/7/13 0:45:07阅读更多 →
影刀RPA 医药行业自动化:药品信息采集与价格监控

影刀RPA 医药行业自动化:药品信息采集与价格监控

影刀RPA 医药行业自动化:药品信息采集与价格监控作者:林焱一、什么情况用影刀处理医药数据 医药行业的信息管理痛点很明显:国家医保局每季度更新医保目录,各省市的药品挂网价格频繁调整,药企的市场部门需要实时掌握竞品…

2026/7/13 0:45:07阅读更多 →
Java 大厂面试高频题:别再只会 new 了!Java 创建对象竟然有这么多种方式

Java 大厂面试高频题:别再只会 new 了!Java 创建对象竟然有这么多种方式

在学习 Java 时,我们最先接触的对象创建方式通常是: Person person new Person();因此,很多初学者会认为 Java 创建对象只能使用 new。 实际上,Java 中常见的对象创建方式不止一种。除了直接使用 new,还可以通过反射、…

2026/7/13 0:40:07阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/12 0:02:11阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/12 0:02:11阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/12 0:02:11阅读更多 →
卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

研究痛点提出(提出问题)重组肠激酶是融合标签切除核心工具酶,当前原核表达体系存在三大标准化难题,直接阻碍可复现的蛋白质分离纯化流程搭建:Trx、GST、单 SUMO 标签融合产物绝大多数为包涵体,沉淀占比超 9…

2026/7/13 0:04:58阅读更多 →
语音转文字工具AsrTools:让音频整理变得简单高效

语音转文字工具AsrTools:让音频整理变得简单高效

语音转文字工具AsrTools:让音频整理变得简单高效 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurate text …

2026/7/13 0:04:58阅读更多 →
Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools 你是否曾经想要调整Palwor…

2026/7/13 0:04:58阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/11 16:20:28阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/11 23:15:38阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/12 21:43:43阅读更多 →