Qwen3-Coder-Next 的 Agent 修 Segmentation Fault,Base URL 填 TaoToken
这篇记录 Qwen3-Coder-Next 的 LangChain Agent 修 Segmentation Fault 时,如何把模型请求从 vLLM localhost:8000 切到 TaoToken 兼容通道。TaoToken 官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,先创建 Key,再填 Base URL。原文第四、五章的链路是:vLLM 起 Qwen3-Coder-Next,在 main.py 的 ChatOpenAI 里写base_url="http://localhost:8000/v1"、api_key="EMPTY"、model="qwen-coder",靠execute_shell、read_file、overwrite_file做 ReAct 闭环。痛点在于 80B Int4 本地部署对双卡显存要求高,想先跑通 Agent 工具链时模型通道不好固定。这里不改 LangChain 工具层,也不拆 AgentExecutor 的 ReAct 循环,只把 main.py / llm_client.py 的模型请求改到 TaoToken:base_url填https://taotoken.net/api,api_key填刚创建的 Key,model按 TaoToken 通道支持的代码模型填写。TaoToken 只提供 Key 和 Base URL,不替代 vLLM、不替 Agent 执行 shell,也不解析 qwen3coder_tool_parser_vllm.py。验证方式是运行 main.py,让 Agent 先execute_shell编译/运行复现 Segmentation Fault,再read_file读 main.cpp,最后overwrite_file修正并复跑。
一、原问题与场景:main.cpp 报 Segmentation Fault,Agent 工具链却卡在模型通道
原始场景很具体:本地有一个 main.cpp,编译后运行会触发 Segmentation Fault。你想用 Qwen3-Coder-Next 作为 Agent 的推理核心,让它在 ReAct 循环里先执行 shell 复现问题,再读取源码,再重写文件,最后重新编译运行验证。
原文里 main.py 的模型连接方式大致是:
llm = ChatOpenAI( base_url="http://localhost:8000/v1", api_key="EMPTY", model="qwen-coder", temperature=0.1, max_tokens=4096, streaming=True )这套配置的前提是 vLLM 已经在localhost:8000把 Qwen3-Coder-Next 起好。vLLM 负责加载模型权重,负责推理,负责暴露 OpenAI 兼容接口。Agent 侧只关心 ChatOpenAI 的 base_url、api_key、model 三项。工具层则保持独立:execute_shell在本地执行g++ -g main.cpp -o app && ./app,read_file读取 main.cpp,overwrite_file覆盖修复后的文件。
问题不在工具层,而在模型通道的固定成本。80B Int4 对双卡显存要求高,下载权重、起 vLLM、调--tensor-parallel-size、处理 OOM、确认 chat template 和工具调用解析,任何一个环节都会打断“先练通 Agent 闭环”的节奏。你真正想先验证的是:LangChain 的create_tool_calling_agent能不能正确解析模型返回的 tool_calls,AgentExecutor能不能按 ReAct 顺序调用execute_shell、read_file、overwrite_file,最终把 main.cpp 里的 Segmentation Fault 修掉。
所以这个场景的目标不是替换 vLLM,也不是让 TaoToken 执行 shell。TaoToken 只提供 Key 和 Base URL。vLLM 仍然可以是本地推理层,但当你暂时不想把模型通道绑死在localhost:8000时,可以先把 main.py / llm_client.py 的 ChatOpenAI 指向 TaoToken,先把工具调用闭环跑起来。工具还是本地工具,AgentExecutor 还是原来的 ReAct 循环,变化只在模型请求的出口。
二、TaoToken 前置:创建 Key,确认 Base URL 与边界
接入前先明确三件事。
第一,打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 创建 Key。这个 Key 后面会填到api_key,不要把它写死在 main.py,也不要把真实 Key 提交到 Git。建议放进.env,再由python-dotenv读取。
第二,Base URL 按本篇场景填https://taotoken.net/api。不要在 ChatOpenAI 里额外再拼/v1,也不要写成http://localhost:8000/v1后忘记替换。原文里base_url="http://localhost:8000/v1"是 vLLM 本地通道;改到 TaoToken 后,模型请求出口变成https://taotoken.net/api。
第三,model 不要照抄qwen-coder。qwen-coder是原文中 vLLM 的--served-model-name,TaoToken 通道不一定使用同一个模型 ID。model 要按 TaoToken 通道支持的代码模型填写。最稳妥的方式是先在控制台或模型对话页面确认模型 ID,再写进环境变量。
TaoToken 的边界也要说清楚:TaoToken 只提供 Key 和 Base URL,不替代 vLLM,不替 Agent 执行 shell,也不解析 qwen3coder_tool_parser_vllm.py。execute_shell仍然在你的机器上执行g++,read_file仍然读本地 main.cpp,overwrite_file仍然写本地文件。qwen3coder_tool_parser_vllm.py 是 vLLM 侧的适配器,TaoToken 不负责解析它。如果你的模型通道返回的是标准 tool_calls,LangChain 就按标准 tool_calls 处理;如果通道返回的是文本,需要换支持工具调用的模型,或在 Agent 层调整 prompt 和解析逻辑。
三、可复制配置:在 llm_client.py 与 main.py 中改 ChatOpenAI
这一节直接给可复制配置。建议把模型连接收敛到core/llm_client.py,main.py 只导入llm和coder_tools,这样以后在 TaoToken 和本地 vLLM 之间切换时,只改一个文件。
先写.env:
TAOTOKEN_API_KEY=YOUR_API_KEY TAOTOKEN_BASE_URL=https://taotoken.net/api TAOTOKEN_MODEL=请按TaoToken通道支持的代码模型填写然后在core/llm_client.py中读取环境变量:
import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI load_dotenv() llm = ChatOpenAI( base_url=os.getenv("TAOTOKEN_BASE_URL", "https://taotoken.net/api"), api_key=os.getenv("TAOTOKEN_API_KEY", "YOUR_API_KEY"), model=os.getenv("TAOTOKEN_MODEL", "你的代码模型ID"), temperature=0.1, max_tokens=4096, streaming=True )注意api_key这里读的是TAOTOKEN_API_KEY,不是OPENAI_API_KEY。如果你在 LangChain 其他组件里也遇到 OpenAI Key 检查,可以额外保留一个占位变量,但真正请求 TaoToken 的 Key 要以.env里的TAOTOKEN_API_KEY为准。
工具层保持原文思路。core/tools_coder.py中继续定义execute_shell、read_file、overwrite_file:
import os import subprocess from langchain.tools import tool from config import WORKSPACE_DIR @tool def execute_shell(command: str) -> str: """执行 shell 命令,用于编译、运行和复现 Segmentation Fault。""" forbidden = ["rm -rf /", "mkfs", ":(){:|:&};:"] if any(x in command for x in forbidden): return "拒绝执行高危命令" try: result = subprocess.run( command, shell=True, cwd=WORKSPACE_DIR, capture_output=True, text=True, timeout=60 ) return f"STDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}" except Exception as e: return f"Execution Error: {str(e)}" @tool def read_file(filepath: str) -> str: """读取文件内容,返回带行号的文本。""" full_path = os.path.join(WORKSPACE_DIR, filepath) with open(full_path, "r", encoding="utf-8") as f: content = f.read() lines = [f"{i + 1} | {line}" for i, line in enumerate(content.split("\n"))] return "\n".join(lines) @tool def overwrite_file(filepath: str, content: str) -> str: """用完整内容覆盖文件,用于修复代码。""" full_path = os.path.join(WORKSPACE_DIR, filepath) os.makedirs(os.path.dirname(full_path), exist_ok=True) with open(full_path, "w", encoding="utf-8") as f: f.write(content) return f"Success: {filepath} updated" coder_tools = [execute_shell, read_file, overwrite_file]main.py 里继续用create_tool_calling_agent和AgentExecutor,不要因为换了 Base URL 就把 ReAct 循环改掉:
from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate from core.llm_client import llm from core.tools_coder import coder_tools prompt = ChatPromptTemplate.from_messages([ ("system", """你是一个 C/C++ 调试 Agent。 工作目录是 ./workspace/。 遇到 Segmentation Fault 时,不要凭空猜测。 先调用 execute_shell 编译并运行程序复现错误; 再调用 read_file 读取 main.cpp; 然后调用 overwrite_file 写入修复后的完整文件; 最后再次调用 execute_shell 编译并运行验证。"""), ("placeholder", "{chat_history}"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}") ]) agent = create_tool_calling_agent(llm, coder_tools, prompt) agent_executor = AgentExecutor( agent=agent, tools=coder_tools, verbose=True, max_iterations=12, handle_parsing_errors=True ) if __name__ == "__main__": result = agent_executor.invoke({ "input": "当前目录 main.cpp 编译后运行报 Segmentation Fault,请先编译复现,再读取源码,修复后复跑验证。" }) print(result["output"])这段配置的关键点只有三个:base_url是https://taotoken.net/api,api_key是YOUR_API_KEY替换后的真实 Key,model是按 TaoToken 通道支持的代码模型填写。工具执行、文件读写、ReAct 状态机都没有变。
四、验证请求与成功结果:运行 main.py 看 execute_shell/read_file/overwrite_file 闭环
配置完成后,直接运行:
python main.pyAgentExecutor 的 verbose 输出应该按类似顺序展开。
第一步,Agent 决定复现 Segmentation Fault:
Action: execute_shell Action Input: g++ -g main.cpp -o app && ./app Observation: STDOUT: STDERR: Segmentation fault (core dumped)这一步说明execute_shell正常执行了本地编译和运行,并且拿到了报错。如果这里没有 Segmentation Fault,说明 main.cpp 当前状态、编译参数或工作目录和预期不一致。
第二步,Agent 读取 main.cpp:
Action: read_file Action Input: main.cpp Observation: 1 | #include <iostream> 2 | int main() { 3 | int* p = nullptr; 4 | *p = 10; 5 | return 0; 6 | }第三步,Agent 写入修复后的完整文件:
Action: overwrite_file Action Input: { "filepath": "main.cpp", "content": "#include <iostream>\nint main() {\n int value = 10;\n int* p = &value;\n *p = 20;\n std::cout << value << std::endl;\n return 0;\n}\n" } Observation: Success: main.cpp updated第四步,Agent 再次编译并运行验证:
Action: execute_shell Action Input: g++ -g main.cpp -o app && ./app Observation: STDOUT: 20 STDERR:最后输出类似:
Final Answer: 已定位到空指针解引用导致的 Segmentation Fault,并覆盖修复 main.cpp。重新编译运行通过。成功结果不是“模型直接告诉你答案”,而是模型通过 TaoToken 通道返回 tool_calls,LangChain 在本地执行execute_shell、read_file、overwrite_file,再由 AgentExecutor 把 Observation 回传给模型,形成闭环。TaoToken 在这里只承担 Key 和 Base URL 的兼容请求,不执行 shell,不读本地文件,也不改 main.cpp。你看到的编译、运行、修复、复跑,全部发生在自己的环境里。
如果本地 vLLM 也在运行,你还可以做一次对照:把base_url切回http://localhost:8000/v1、api_key切回EMPTY、model切回qwen-coder,确认同一套工具链仍然能跑。这样就能区分问题在模型通道,还是在工具层或 main.cpp 本身。
五、本篇常见错排查:Base URL、model、工具调用与 Segmentation Fault 复现
第一类错误是 401/403。YOUR_API_KEY没有替换成真实 Key,或者.env没有被load_dotenv()加载,或者系统环境变量覆盖了.env。排查时先在 Python 里打印os.getenv("TAOTOKEN_API_KEY")是否存在,再看请求头是否正确。不要把真实 Key 写进 main.py 提交到仓库。
第二类错误是 404/Not Found。常见原因是base_url写成了https://taotoken.net/api/v1,或者在https://taotoken.net/api后又让 ChatOpenAI 重复拼了/v1。本篇按场景填https://taotoken.net/api。如果接入文档给出的路径不同,以接入文档为准,不要同时混用localhost:8000/v1和 TaoToken。
第三类错误是 model not found。model 不能照抄qwen-coder,因为那只是原文 vLLM 的 served-model-name。model 要按 TaoToken 通道支持的代码模型填写。最稳的方式是先到模型对话或控制台确认模型 ID,再写进TAOTOKEN_MODEL。
第四类错误是 Agent 不调用工具,只输出自然语言。检查create_tool_calling_agent是否传入工具列表,prompt是否保留{agent_scratchpad},工具函数的 docstring 是否清楚。更关键的是模型是否支持 tool calling。TaoToken 不解析 qwen3coder_tool_parser_vllm.py,如果所选模型通道不支持标准工具调用,就需要换支持工具调用的代码模型,或者在 Agent 层自己加 JSON 解析和重试。不要把 vLLM 侧的工具解析器逻辑硬套到 TaoToken 通道上。
第五类错误是 Segmentation Fault 没有复现。检查execute_shell的cwd是否指向 main.cpp 所在目录,编译命令是否真的执行了,程序是否在&&后面被运行。建议先在终端手动执行g++ -g main.cpp -o app && ./app,确认能稳定复现,再交给 Agent。如果 main.cpp 已经被修好,Agent 自然拿不到 Segmentation Fault,这时要么恢复问题版本,要么换一个复现用例。
第六类错误是 Agent 死循环。表现是反复overwrite_file同一文件,或者反复执行同一个 shell 命令。可以降低max_iterations,并在 system prompt 中要求:连续两次修复失败后停止,输出当前 main.cpp 完整内容和报错信息。handle_parsing_errors=True也可以减少解析异常导致的循环。
第七类错误是本地 vLLM 和 TaoToken 混用。你可能改了core/llm_client.py,但 main.py 里又新建了一个 ChatOpenAI,仍然指向localhost:8000。排查时全局搜索base_url、api_key、model,确认只有一处模型连接配置。切换通道时改环境变量,不要在多处硬编码。
第八类错误是 Key 和.env泄露。.env必须加入.gitignore。如果已经提交,先撤回 Key,再重新创建。接入配置可以复现,Key 不应该出现在文章、截图或日志里。
六、语义一致 CTA:从 API Keys 到接入文档,再到 Coding Plan
把 Qwen3-Coder-Next Agent 接到 TaoToken 的路径已经明确:创建 Key,把base_url填成https://taotoken.net/api,把api_key填成真实 Key,把model按 TaoToken 通道支持的代码模型填写,然后保留 LangChain 工具层和 AgentExecutor 的 ReAct 循环。这样你可以先跳过 80B Int4 双卡显存的部署压力,集中验证execute_shell、read_file、overwrite_file能否围绕 main.cpp 的 Segmentation Fault 形成闭环。
如果你正在做接入配置、排障或需要确认 API Keys 与接入参数,建议直接从 API Keys 和接入文档开始:
- API Keys:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite
- 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
如果你要先验证模型通道是否连通,可以到模型对话页面发一条最小请求,确认 Key、Base URL、model 三项一致:
- 模型对话:https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite
如果你准备把这种 LangChain Agent 长期用于仓库级调试、工具调用和本地代码修复,而不是只跑一次 Segmentation Fault 示例,可以继续看 Coding Plan:
- Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite
回到本篇场景,最小闭环就是:main.py 用 TaoToken 作为模型请求通道,Agent 先execute_shell复现 Segmentation Fault,再read_file读取 main.cpp,再overwrite_file修正,最后execute_shell复跑。TaoToken 只提供 Key 和 Base URL,不替代 vLLM,不替 Agent 执行 shell,也不解析 qwen3coder_tool_parser_vllm.py。把这套配置跑通后,你再决定是继续用兼容通道,还是切回本地 vLLM,都会比一开始就卡在双卡显存和模型通道上更可控。