十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用 Iris 35B 做搜索代理,TaoToken 记录谁在烧 Token

用 Iris 35B 做搜索代理,TaoToken 记录谁在烧 Token 1. 用 Iris 35B 做搜索代理前先把 TaoToken 的 Key 和 base_url 固定下来TaoToken 的拿 Key 入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_intro 。用 Iris 35B 做搜索代理的本地评测时真正难排查的不是模型会不会搜而是 Search Agent 在搜索规划与答案汇总两个阶段各自调用了多少次模型、每次返回的 usage 是什么、哪一次请求把上下文撑大。AllSpark 把 Iris 这个 Search Agent 模型开源出来权重和评测代码公开这让本地跑评测变得可行但评测脚本一旦把 OpenAI 兼容调用散落在多个文件base_url、api_key、模型名不一致日志就会失真。所以第一步不是跑全量 case而是把出口统一base_urlhttps://taotoken.net/apiKey 用YOUR_API_KEY占位模型 ID 从 TaoToken 模型对话页或控制台复制。这样 Iris 的评测代码不用重写业务逻辑只需要把 Search Agent 内部两次 LLM 调用改到同一网关就能记录谁在烧 Token。先把环境变量固定下来后续所有脚本、Claude Code、Codex、CC Switch 都只认这几个值避免出现“规划阶段走一个 Key汇总阶段走另一个 Key”的情况export TAOTOKEN_API_KEYYOUR_API_KEY export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODELMODEL_ID_FROM_TAOTOKEN注意TAOTOKEN_BASE_URL不要加 UTM 参数也不要随手拼/v1或尾斜杠。本文统一使用产品配置给出的 OpenAI 兼容 Base URLhttps://taotoken.net/api先用最小请求验证 Key、Base URL、模型名三件套是否可用。下面这段 Python 不涉及搜索代理只做一次普通对话确认 TaoToken 网关可以返回内容和 usageimport os from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api), ) resp client.chat.completions.create( modelos.environ[TAOTOKEN_MODEL], messages[{role: user, content: 只回复 pong}], temperature0, ) print(resp.choices[0].message.content) print(resp.usage)如果这一步返回 401不要继续跑 Iris 评测先回到 TaoToken 官网检查 Key 是否复制完整、环境变量是否在当前 shell 生效。如果返回模型不存在把TAOTOKEN_MODEL换成模型对话页中实际可用的模型 ID。如果返回 404优先检查base_url是否被改成了带/v1或带尾斜杠的地址。把这三类基础错误排掉后面的 Search Agent 日志才有参考价值。2. 在 TaoToken 控制台创建 Key 并验证 OpenAI 兼容端点创建 Key 的步骤不要散落在各种旧笔记里统一走 TaoToken 官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_console 。进入控制台后找到 API Keys 相关入口创建一个只给 Iris 评测用的 Key。建议按用途命名例如iris-search-agent-eval这样后续如果发现某段时间 Token 消耗异常可以快速判断是评测脚本、Claude Code 还是 Codex 在调用。拿到 Key 后按下面的顺序回填export TAOTOKEN_API_KEYYOUR_API_KEY export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODELMODEL_ID_FROM_TAOTOKEN python - PY import os from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], ) resp client.chat.completions.create( modelos.environ[TAOTOKEN_MODEL], messages[ {role: system, content: 你是配置验证助手。}, {role: user, content: 返回 JSON{\ok\: true}}, ], temperature0, ) print(resp.model) print(resp.usage) print(resp.choices[0].message.content) PY这里要特别区分两个概念搜索接口本身通常不消耗大模型 Token真正消耗 Token 的是 Search Agent 把用户问题改写成检索 query、判断是否需要二次搜索、把多段搜索结果汇总成答案时的 API 调用。所以日志里必须至少记录stage字段明确区分planner和summarizer。否则你只看到总 Token 变多却不知道是规划阶段反复拆 query还是汇总阶段把过多检索片段塞进上下文。验证阶段还要确认 usage 是否稳定返回。OpenAI 兼容接口在非流式模式下通常会返回prompt_tokens、completion_tokens、total_tokens。如果你后续开启流式输出需要在请求里显式要求包含 usage否则日志里的 Token 字段可能为空resp client.chat.completions.create( modelos.environ[TAOTOKEN_MODEL], messages[{role: user, content: 用一句话说明搜索代理的规划阶段。}], streamTrue, stream_options{include_usage: True}, ) for chunk in resp: if getattr(chunk, usage, None): print(chunk.usage)如果你发现流式请求没有 usage不要先怀疑 TaoToken 网关先检查客户端是否真的传了stream_options。很多评测脚本是从旧代码复制来的只改了base_url却忘了流式 usage 需要额外参数。3. 给 Iris 35B Search Agent 的规划与汇总两阶段埋点现在回到 Iris 35B 的本地评测。Search Agent 的典型链路可以拆成四步读取评测问题、规划检索 query、执行本地搜索工具、把检索结果汇总成答案。本文不假设 Iris 官方评测代码的具体函数名只把其中所有 OpenAI 兼容调用替换成同一个call_model封装。这样无论你用的是官方评测脚本还是自己写的 harness都可以照这个结构接入 TaoToken。下面是一份可运行的评测骨架。它读取本地 JSONL 问题集调用模型做规划再用本地函数模拟搜索工具最后调用模型汇总。日志按 JSONL 写入logs/iris_search_agent.jsonl每行一条模型调用记录import json import os import time import uuid import logging from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api), ) MODEL os.environ[TAOTOKEN_MODEL] LOG_PATH os.environ.get(IRIS_EVAL_LOG, logs/iris_search_agent.jsonl) os.makedirs(os.path.dirname(LOG_PATH), exist_okTrue) logging.basicConfig(filenameLOG_PATH, levellogging.INFO, format%(message)s) def call_model(stage, messages, temperature0.0): call_id str(uuid.uuid4()) started time.time() resp client.chat.completions.create( modelMODEL, messagesmessages, temperaturetemperature, ) usage resp.usage record { call_id: call_id, stage: stage, model: getattr(resp, model, MODEL), response_id: getattr(resp, id, None), latency_ms: round((time.time() - started) * 1000, 2), prompt_tokens: getattr(usage, prompt_tokens, None), completion_tokens: getattr(usage, completion_tokens, None), total_tokens: getattr(usage, total_tokens, None), } logging.info(json.dumps(record, ensure_asciiFalse)) return resp.choices[0].message.content def search_local(query): # 只读本地脱敏样本不要让 Agent 直连 Oracle/生产库。 # SQL 或数据命令由读者在本地执行这里返回模拟检索结果。 return [ { title: f本地样本{query}, snippet: 这里是本地评测用的脱敏片段用于验证汇总阶段上下文长度。, } ] def plan_queries(question): messages [ { role: system, content: 你是搜索代理的规划器。只输出 JSON 数组每项是一个检索 query。, }, { role: user, content: f问题{question}\n请给出 1-3 个检索 query。, }, ] text call_model(planner, messages) try: queries json.loads(text) return queries if isinstance(queries, list) else [question] except Exception: return [question] def summarize(question, hits): context \n.join([f- {h[title]}{h[snippet]} for h in hits]) messages [ { role: system, content: 你是搜索代理的汇总器。只基于给定材料回答不要编造。, }, { role: user, content: f问题{question}\n材料\n{context}\n请给出简洁答案。, }, ] return call_model(summarizer, messages) def run_case(case): question case[question] queries plan_queries(question) hits [] for q in queries: hits.extend(search_local(q)) answer summarize(question, hits) return {question: question, queries: queries, answer: answer} if __name__ __main__: import sys cases_path sys.argv[1] if len(sys.argv) 1 else eval_cases.jsonl with open(cases_path, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue case json.loads(line) result run_case(case) print(json.dumps(result, ensure_asciiFalse))准备一个最小问题集eval_cases.jsonl{question: Iris 35B 适合做搜索代理的哪些评测场景} {question: Search Agent 的规划阶段和汇总阶段分别消耗什么} {question: 为什么搜索代理的 Token 日志要按 stage 拆分}运行评测命令时先把三件套回填再执行脚本export TAOTOKEN_API_KEYYOUR_API_KEY export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODELMODEL_ID_FROM_TAOTOKEN python eval_iris_search_agent.py eval_cases.jsonl如果你已经在本地用其他方式启动了 Iris 35B 的 OpenAI 兼容服务也可以把本地服务和 TaoToken 作为两个 provider 分开记录。关键不是把所有调用混在一起而是让每条日志都能回答这次调用属于哪个 stage、走的是哪个 provider、用了哪个模型、消耗了多少 prompt/completion Token。只要call_model是统一入口后面切换 provider 不需要改业务代码。4. 跑评测命令并对照日志按阶段、模型、请求 ID 统计 Token跑完评测后不要只看终端最后输出的答案。搜索代理最容易出现的问题是答案看起来还行但规划阶段为了一个简单问题生成了过多 query或者汇总阶段把大量无关片段拼进上下文导致 Token 消耗集中在某一类 case 上。下面这段脚本按stage聚合日志快速看出planner和summarizer各自的调用次数与 Token 分布import json from collections import defaultdict stats defaultdict(lambda: { calls: 0, prompt: 0, completion: 0, total: 0, }) with open(logs/iris_search_agent.jsonl, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue record json.loads(line) stage record.get(stage, unknown) item stats[stage] item[calls] 1 item[prompt] record.get(prompt_tokens) or 0 item[completion] record.get(completion_tokens) or 0 item[total] record.get(total_tokens) or 0 for stage, item in stats.items(): print(stage, item)日志字段建议至少保留这些call_id本地生成的调用 ID方便和业务日志关联。stageplanner或summarizer后续加retry、verifier也可以。model实际返回的模型名避免配置漂移。response_id服务端返回的响应 ID排查单次请求时有用。latency_ms耗时区分“贵”和“慢”是两件事。prompt_tokens、completion_tokens、total_tokens核心消耗字段。如果你要做更细的对照可以再按question做二次聚合。最简单的做法是在run_case里把当前问题 ID 传给call_model日志中增加case_id。这样你可以回答“哪一类问题让规划器反复调用”“哪些问题的汇总上下文特别长”而不是只看到一个笼统的总量。另外搜索工具本身也要做本地化。评测阶段不要让 Agent 直接连生产库也不要把数据库连接串塞进 prompt。更稳妥的方式是先在本地把脱敏数据导出成 JSONL 或 SQLiteSQL 由你在本地执行Agent 只读结果片段。这样即使 Search Agent 规划出奇怪的 query也不会影响线上数据。5. 把 Claude Code、Codex 与 CC Switch 接到同一套 TaoToken 配置Iris 评测链路跑通后你可能会用 Claude Code 改评测脚本、用 Codex 辅助看配置、用 CC Switch 在多个供应商之间切换。这里必须把配置分开写Claude Code 用settings.json和ANTHROPIC_*变量Codex 用config.toml和TAOTOKEN_API_KEY。不要把ANTHROPIC_*套到 Codex否则 Codex 不会按你预期的 OpenAI 兼容方式读取配置。Claude Code 的settings.json可以这样写。注意ANTHROPIC_BASE_URL使用 TaoToken 的 Base URLANTHROPIC_AUTH_TOKEN填YOUR_API_KEY模型名从模型对话页复制{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: MODEL_ID_FROM_TAOTOKEN } }Codex 使用config.toml配置方式不同。下面这份配置使用TAOTOKEN_API_KEY环境变量不要在这里写ANTHROPIC_*model MODEL_ID_FROM_TAOTOKEN model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat对应环境变量仍然只设一次export TAOTOKEN_API_KEYYOUR_API_KEY如果你使用 CC Switch 这类切换工具可以把“三件套”理解为Base URL、API Key、模型名。切换供应商时只改这三项不要同时改业务脚本里的base_url。推荐做法是让评测脚本、Claude Code、Codex 都从环境变量或各自配置文件中读取同一个https://taotoken.net/api避免出现“终端里是 TaoTokenIDE 里还是旧地址”的混合状态。需要查看或重新创建 Key 时统一走 TaoToken 官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_tools 。切换完成后做一次最小验证Claude Code 里发一句普通对话Codex 里发一句普通对话Iris 评测脚本跑一条 case然后检查三处是否都在日志或控制台中留下记录。这样你才能确认“谁在烧 Token”这个问题的答案是来自同一套配置而不是多个旧 Key 混用。6. 常见报错与排查401、404、429、流式无 usage、模型名不匹配Search Agent 接入 TaoToken 时报错通常集中在几个固定位置。下面按现象排查现象优先检查处理方式401 UnauthorizedKey 是否来自 TaoToken环境变量是否生效回到官网重新创建 Key确认YOUR_API_KEY已替换重新打开 shell 或重新加载配置404 Not Foundbase_url是否被加了/v1、尾斜杠或旧域名统一改为https://taotoken.net/api不要在代码里手写完整路径429 Too Many Requests评测并发是否过高是否有重试风暴降低并发增加指数退避先跑单条 case 验证usage 为空是否开启流式但没传stream_options加stream_options{include_usage: True}或先用非流式跑通埋点模型名不存在模型 ID 是否从模型对话页复制不要手写猜测模型名以 TaoToken 页面显示为准日志只有总 Tokencall_model是否被绕过把所有 OpenAI 兼容调用收口到统一函数强制写stage汇总阶段上下文过长检索结果是否全部拼接先做截断、去重、按相关性排序再传给 summarizer还有一个容易被忽略的问题搜索代理的重试。规划阶段如果返回的 JSON 解析失败很多脚本会直接重试一重试就多一次 API 调用。建议在日志中把stage写成planner_retry或增加attempt字段否则你只看到planner调用次数多却不知道是正常多 query还是解析失败导致的反复重试。最后再强调一次数据边界评测 Search Agent 时搜索工具读取本地脱敏样本即可SQL 和命令由你在本地执行不要让 Agent 直连 Oracle 或生产库。TaoToken 记录的是模型调用侧的 Token 消耗数据库安全边界仍然由你的本地评测环境控制。7. 文末 CTA把 Iris 评测链路接到 TaoToken 的推荐路径如果你准备把上面的 Iris 35B Search Agent 评测脚本真正跑起来建议按这个顺序操作先进入模型对话页确认当前可用的模型 ID 和调用效果https://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_chat如果要把 Claude Code、Codex 和评测脚本一起用起来查看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_coding创建或管理评测专用 Key回填到TAOTOKEN_API_KEYhttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_keysClaude Code 用户按文档配置settings.json与ANTHROPIC_*https://taotoken.net/doc/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_claudecode如果你还没有拿 Key也可以先从官网入口进入https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentiris35b_cta 。整个链路的核心只有一句话把 Search Agent 的规划调用和汇总调用都收口到https://taotoken.net/api用YOUR_API_KEY回填跑评测命令按stage对照 JSONL 日志。这样 Iris 35B 的本地评测就不再是一笔糊涂账谁在烧 Token、烧在哪个阶段、下一次该优化 planner 还是 summarizer都能从日志里直接看出来。
返回列表