Qwen-Agent学习总结:从ReAct到Function Call的Agent开发框架实践
1. 从一次工具调用失败说起Qwen-Agent 的 ReAct 与 Function Call 到底怎么选Qwen-Agent 是阿里通义千问团队开源的一套 Agent 开发框架它把大模型的指令遵循、工具调用、规划、记忆能力封装成可复用的组件让你用几十行代码就能搭出一个能读文档、能调工具、能多跳推理的智能体。它适合谁适合已经会写 Python、想快速验证 RAG 增强 Agent 的开发者也适合手里有一堆本地文档、想让模型自己决定“先查什么、再算什么”的工程同学。我最初接触它是因为一个很具体的需求手头有一批 PDF 报告想让模型回答跨文档的对比问题。直接塞进上下文会超长纯向量检索又经常召回不准。Qwen-Agent 给出的答案是把 Agent 分成三个复杂度级别——Lv1 检索、Lv2 分块阅读、Lv3 逐步推理每一层都建立在前一层之上。这个分层思路很实用因为它让你可以按问题难度选择成本。但真正上手时第一个卡点往往不是框架本身而是模型服务怎么接。Qwen-Agent 默认走 DashScope也支持 OpenAI 兼容接口。如果你本地跑的是 vLLM 或 Ollama或者想用一个统一的 Key 管理多个模型通道就需要一个稳定的 API 入口。我实测下来用 TaoToken 的统一通道接 Qwen-Agent 是可行的Base URL 填https://taotoken.net/apiKey 用平台生成的Model ID 按你实际调用的模型填。这样 ReAct 和 Function Call 两种模式都能跑通后面我会给出完整配置。ReAct 和 Function Call 的区别用一句话说ReAct 是让模型“边想边说”把推理过程写成文本框架再去解析动作Function Call 是模型直接输出结构化的函数调用参数框架按 schema 执行。前者对模型能力要求低、调试直观后者更稳定、更适合生产。Qwen-Agent 两种都支持你可以在同一个 Assistant 里混用。下面从环境准备开始一步步把链路跑通。2. TaoToken 前置准备统一 Key 与 API 通道接入 Qwen-Agent 的配置方法在写 Agent 代码之前先把模型通道准备好。Qwen-Agent 的llm_cfg支持两种写法一种是model_server: dashscope走 DashScope 原生协议另一种是 OpenAI 兼容模式填model_server为 base_url。后者通用性更强vLLM、Ollama、以及 TaoToken 的统一通道都走这个模式。你需要准备三样东西Base URL、API Key、Model ID。Base URL 用https://taotoken.net/api注意这里不带任何查询参数。API Key 在控制台的 API Keys 页面生成生成后复制保存页面关闭后不再完整显示。Model ID 取决于你要调用的模型比如qwen-max、qwen-plus或者你本地部署后映射到通道上的模型名。环境变量方式是最省事的避免把 Key 写进代码提交到仓库。在终端里执行export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你用.env文件管理记得把.env加进.gitignore。Windows PowerShell 下用$env:TAOTOKEN_API_KEYsk-...CMD 下用set TAOTOKEN_API_KEYsk-...。这一步看起来简单但后面 401 报错十有八九是环境变量没生效或者拼写错了。安装 Qwen-Agent 本身pip install -U qwen-agent如果你要用code_interpreter工具它依赖 Docker 或本地 Python 执行环境建议先确认docker命令可用。如果只是跑 ReAct 文本推理和自定义工具不装 Docker 也能跑。另外json5是自定义工具里解析参数的常用库pip install json5一并装上。配置模板我建议单独放一个llm_config.py这样多个 Agent 脚本可以复用import os llm_cfg { model: qwen-max, model_server: os.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api), api_key: os.getenv(TAOTOKEN_API_KEY), generate_cfg: { top_p: 0.8, temperature: 0.5, } }这里有个细节Qwen-Agent 在 OpenAI 兼容模式下model_server填的是 base_url框架会自动拼接/chat/completions。如果你填成https://taotoken.net/api/v1反而可能重复。实测填https://taotoken.net/api即可。Model ID 必须和通道上可用的模型一致填错会返回模型不存在的错误。注意不要把 API Key 硬编码在llm_cfg里然后提交到公开仓库。用环境变量或本地配置文件是成本最低的安全习惯。准备好之后先别急着写复杂 Agent用一段最小代码验证通道是否通。下一节给出可复制的配置和验证脚本。3. 可复制配置ReAct 与 Function Call 双模式 Agent 模板这一节给两份可直接跑的模板。第一份是 Function Call 模式用自定义工具my_image_gen演示结构化调用第二份是 ReAct 模式用Assistant的默认推理循环演示文本式工具选择。两份都走 TaoToken 通道。先看 Function Call 模板。核心是继承BaseTool并注册description和parameters决定了模型能不能正确调用import os import json5 import urllib.parse from qwen_agent.agents import Assistant from qwen_agent.tools.base import BaseTool, register_tool register_tool(my_image_gen) class MyImageGen(BaseTool): description AI 绘画服务输入文本描述返回图像 URL。 parameters [{ name: prompt, type: string, description: 期望的图像内容描述, required: True }] def call(self, params: str, **kwargs) - str: prompt json5.loads(params)[prompt] prompt urllib.parse.quote(prompt) return json5.dumps( {image_url: fhttps://image.pollinations.ai/prompt/{prompt}}, ensure_asciiFalse ) llm_cfg { model: qwen-max, model_server: os.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api), api_key: os.getenv(TAOTOKEN_API_KEY), generate_cfg: {top_p: 0.8} } system_instruction 你是一个乐于助人的AI助手。 收到用户请求后先绘制图像得到 URL再用中文回复用户。 bot Assistant( llmllm_cfg, system_messagesystem_instruction, function_list[my_image_gen] ) messages [] query 画一只在草地上奔跑的柯基 messages.append({role: user, content: query}) response [] for response in bot.run(messagesmessages): pass print(response[0][content])这段代码里function_list只放了my_image_gen模型会在需要时输出函数调用参数框架解析后执行call。如果你把code_interpreter也加进去模型可能会选择写代码而不是直接调工具这取决于 system message 的引导。再看 ReAct 模式。ReAct 的关键是让模型在文本里显式写出“思考—行动—观察”的循环。Qwen-Agent 的Assistant在function_list非空时会自动进入工具调用循环但你可以通过 system message 引导它先输出推理文本system_instruction 你是一个善于逐步推理的助手。 面对复杂问题时先写出你的思考过程再决定调用哪个工具。 可用工具my_image_gen。 每次只调用一个工具观察结果后再继续。 bot Assistant( llmllm_cfg, system_messagesystem_instruction, function_list[my_image_gen] )ReAct 和 Function Call 在 Qwen-Agent 里并不是互斥的。底层都是bot.run()返回一个生成器每次 yield 的是当前累积的消息列表。你可以通过打印response[0][content]看到模型是输出了文本推理还是输出了function_call字段。实测下来qwen-max在 Function Call 模式下更稳定qwen-plus在 ReAct 文本推理下响应更快、成本更低。如果你要接 RAG把检索结果作为files或 system message 的一部分传进去即可。Qwen-Agent 的Assistant支持files参数内部会做分块和检索。对于 Lv2 分块阅读框架会并行评估每个块的相关性对于 Lv3 逐步推理它会把 Lv2 封装成工具供上层调用。你不需要自己实现这套逻辑但需要理解它的成本——每个块都要过一次模型块多了费用会上去。提示先用小文档几页 PDF验证链路再换大文档。大文档下 Lv2 的并行调用会明显变慢建议加超时和重试。配置写好后下一步是验证请求是否真的成功以及成功结果长什么样。4. 验证请求与成功结果一次完整的工具调用链路测试验证分三步通道连通性、单工具调用、多轮工具链。第一步用最小请求确认 Key 和 Base URL 没问题from openai import OpenAI import os client OpenAI( api_keyos.getenv(TAOTOKEN_API_KEY), base_urlos.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api) ) resp client.chat.completions.create( modelqwen-max, messages[{role: user, content: 回复两个字通了}] ) print(resp.choices[0].message.content)如果这里报 401说明 Key 无效或没读到环境变量如果报连接错误检查 Base URL 是否多了/v1或末尾斜杠。这一步通了再跑 Qwen-Agent 的完整链路。第二步跑上一节的my_image_gen模板。成功时你会看到类似输出好的我已经为你生成图像URL 如下 https://image.pollinations.ai/prompt/...同时终端里可能打印出工具调用的中间消息。Qwen-Agent 的bot.run()每次 yield 的response是一个消息列表最后一条是模型的最终回复。你可以遍历打印每条消息的role和content观察工具调用发生在哪一轮。第三步测多轮工具链。把 system message 改成需要两步操作的指令比如“先画图再描述图中内容”。模型可能会先调my_image_gen拿到 URL 后再生成描述文本。如果你加了code_interpreter它甚至可能写代码去下载图片。这一步能跑通说明 Function Call 的循环机制是正常的。对于 RAG 场景验证方式是给Assistant传一个本地 PDFbot Assistant( llmllm_cfg, system_message根据文档回答问题引用原文。, function_list[], files[./docs/report.pdf] )然后问一个文档里明确有答案的问题看回复是否引用了正确段落。如果模型答非所问先检查 PDF 是否被正确解析——Qwen-Agent 内部用pdfplumber或类似库提取文本扫描版 PDF 可能提取为空。这种情况需要先做 OCR再喂给 Agent。成功结果的判断标准工具被正确调用、参数符合 schema、最终回复包含工具返回的信息。如果模型只是“假装”调用了工具实际没触发call通常是description写得太模糊或者parameters的required没设对。把工具描述写具体比如“输入英文 prompt返回图片 URL”模型的选择准确率会明显提升。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth 报错对照这一节按真实报错来。第一个高频错误是 401 Unauthorized。表现是请求直接返回{error: {message: Invalid API key}}。原因通常有三个环境变量名拼错、Key 复制时带了空格、或者用了已删除的 Key。排查方法是在 Python 里打印os.getenv(TAOTOKEN_API_KEY)[:8]确认前几位和平台上一致。如果用的是.env文件确认python-dotenv已加载。第二个是local proxy failed或连接超时。这类报错通常出现在 Base URL 写错、网络出口受限、或者本地开了某些网络工具导致请求被拦截。先确认https://taotoken.net/api能通用curl -I测一下。如果公司网络有出口限制换一个网络环境再试。注意不要在代码里配置任何代理地址保持直连即可。第三个是reading choices或KeyError: choices。这通常发生在响应体不是标准 OpenAI 格式时比如通道返回了错误 JSON但代码直接取resp.choices。排查方法是先打印原始响应import requests r requests.post( https://taotoken.net/api/chat/completions, headers{Authorization: fBearer {os.getenv(TAOTOKEN_API_KEY)}}, json{model: qwen-max, messages: [{role: user, content: hi}]} ) print(r.status_code, r.text[:500])如果返回的是{error: ...}根据错误信息定位。常见的是模型名不存在把 Model ID 换成通道上确认可用的。第四个是 OAuth 相关报错比如OAuth token expired或invalid_grant。如果你用的是某些需要 OAuth 的客户端比如 Claude Code 类工具注意 OAuth 和 API Key 是两套认证。Qwen-Agent 走的是 API Key不需要 OAuth。如果你在 CC Switch、Cline MCP 或 Codex 的auth.json里配置三件套要写全Base URL 填https://taotoken.net/apiKey 填生成的 API KeyModel ID 填实际模型名。缺任何一个都会认证失败。还有一个容易忽略的code_interpreter报 Docker 相关错误。如果你没装 Docker或者 Docker 服务没启动这个工具会失败。解决方法是启动 Docker Desktop或者把function_list里的code_interpreter去掉只保留自定义工具。注意报错信息里如果出现proxy字样先检查是不是环境变量HTTP_PROXY/HTTPS_PROXY被设置了。清掉这两个变量再跑。排查顺序建议先测通道连通性再测单工具最后测多轮。每步都打印原始响应不要只看异常堆栈。大部分问题出在配置层而不是框架层。6. 语义一致 CTA把 Qwen-Agent 接入你的日常开发流链路跑通之后下一步是把它用起来。如果你主要做模型能力验证和对话测试可以直接在模型对话页面里试不同 Model ID 的效果确认哪个模型在你的任务上表现最好。如果你要长期跑编码类 Agent或者需要稳定的工具调用通道Coding Plan 更适合它按周期提供额度不用每次手动充值。接入文档里有各语言和各客户端的配置示例包括 OpenAI SDK、LangChain、以及常见的 IDE 插件。API Keys 页面用来生成和管理 Key建议给不同项目建不同的 Key方便排查和吊销。如果你用 Claude Code 类工具做代码润色或重构注意它需要的是完整的 Base URL Key Model ID 三件套缺一不可。我自己的习惯是先用模型对话快速验证 prompt 和工具描述确认模型能正确选择工具后再写进 Qwen-Agent 脚本里跑批量任务。这样比直接写代码调试快很多因为对话页面能实时看到模型的推理过程。对于 RAG 场景先用小文档在对话里测检索质量再换大文档跑 Lv2/Lv3成本可控。最后留一个实用技巧Qwen-Agent 的bot.run()返回的是生成器你可以把每次 yield 的消息落盘成 JSONL方便回放和对比不同模型的表现。这个日志在调工具描述时特别有用能清楚看到模型是在哪一轮决定调用哪个工具的。

相关新闻

用Python搭建实时股票主力监控系统,自动识别主力与量化资金

用Python搭建实时股票主力监控系统,自动识别主力与量化资金

做短线盯盘的朋友都清楚,盘面上最让人焦虑的不是指数涨跌,而是明明看到有大单进场,却不清楚这些钱到底是真金白银的主力,还是量化资金在自营高抛。我花了一个周末,用300行Python代码搭了个实时股票主力监控系统&#x…

2026/10/12 19:47:03 阅读更多 →
墨菲定律不是倒霉学,而是风险预演的工程思维

墨菲定律不是倒霉学,而是风险预演的工程思维

1. 墨菲定律不是“倒霉学”,而是系统性风险识别的底层思维工具很多人第一次听说墨菲定律,是在某次电脑蓝屏前脱口而出的那句“如果一件事有可能出错,它就一定会出错”。接着顺手转发一条配图是“咖啡洒在键盘上”表情包的朋友圈,配…

2026/10/12 19:46:03 阅读更多 →
CentOS glibc升级难题与七种安全解决方案

CentOS glibc升级难题与七种安全解决方案

1. 项目概述:为什么glibc升级在CentOS上总像走钢丝?“CentOS安装glibc问题”——这七个字背后,是成千上万运维工程师、嵌入式开发者、科研计算人员深夜盯着终端报错时的真实写照。我第一次遇到这个问题,是在给某高校实验室部署一个…

2026/10/12 19:46:03 阅读更多 →

最新新闻

从零手写Shellcode:理解栈、寄存器与位置无关代码

从零手写Shellcode:理解栈、寄存器与位置无关代码

1. 从一段"看起来像乱码"的字节说起第一次接触 Shellcode 的人,多半会有一种强烈的违和感:屏幕上那一串\x31\xc0\x50\x68...到底是个什么东西?它既不像正常的汇编指令那样有助记符,也不像高级语言那样有结构&#xff0c…

2026/10/12 20:30:55 阅读更多 →
自建推理 API 开放测试:用 TaoToken 统一 Key 接入 vLLM + Qwen2.5 的 OpenAI 兼容实践

自建推理 API 开放测试:用 TaoToken 统一 Key 接入 vLLM + Qwen2.5 的 OpenAI 兼容实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 20:30:55 阅读更多 →
轻量级多模态生物表征建模:面相手相图像的鲁棒特征提取与健康初筛

轻量级多模态生物表征建模:面相手相图像的鲁棒特征提取与健康初筛

简介:这是一套基于PHP实现的AI面相与手相智能分析系统开源项目,面向人工智能初学者、Web开发者及对传统命理数字化感兴趣的实践者,提供可上线运行的完整解决方案。资源包含1730个文件,主体为935个PHP后端逻辑文件、360个DAT模型/配…

2026/10/12 20:30:55 阅读更多 →
RT-Thread Studio RTC实战:从时钟源到低功耗唤醒的避坑指南

RT-Thread Studio RTC实战:从时钟源到低功耗唤醒的避坑指南

1. 为什么RTC在嵌入式项目里总被当成"最后才碰的模块"RTC这东西,在大多数嵌入式项目里的存在感其实挺尴尬的。项目排期紧的时候,它永远排在显示屏驱动、通信协议、电机控制这些"看得见摸得着"的功能后面;等到产品快量产了…

2026/10/12 20:30:55 阅读更多 →
8086寻址方式底层原理:从CPU硬件执行到调试实战

8086寻址方式底层原理:从CPU硬件执行到调试实战

1. 这不是背诵口诀,而是理解CPU“找东西”的底层逻辑“微机原理——寻址方式总结”这个标题,乍一看像教科书里的章节名,甚至有点让人下意识想划走。但如果你正在啃8086汇编、调试单片机启动代码、或者被嵌入式系统中一条mov ax, [bxsi10h]卡住…

2026/10/12 20:30:55 阅读更多 →
手写词法与LL(1)/LR(1)分析器:深入编译原理底层逻辑

手写词法与LL(1)/LR(1)分析器:深入编译原理底层逻辑

简介:本资源是面向高校计算机专业本科生的编译原理课程实验配套源码包,完整实现词法分析器、LL(1)语法分析器与LR(1)语法分析器三大核心模块,覆盖编译前端基础能力训练。压缩包共52个文件,含4个C源文件(cpp&#xff09…

2026/10/12 20:29:54 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →