fix: Gemini tool_call_id 跨 content 配对 + Ollama 请求侧 assistant 推理回放 - #6604
fix: Gemini tool_call_id 跨 content 配对 + Ollama 请求侧 assistant 推理回放#6604HandSonic wants to merge 2 commits into
Conversation
GeminiGenerateContentRequestToOpenAIChat assigned functionCall ids from a toolCalls slice scoped to the current content, so functionResponse parts in the following user content always computed len(toolCalls)==0 and received call_0, while the assistant tool calls started at call_1 — tool calls and tool messages never paired, and strict OpenAI-family upstreams reject the misaligned history. Assign ids from a request-wide sequence and pair functionResponse parts with earlier functionCall parts by function name (FIFO per name); unmatched responses get a fresh non-colliding id. Also buffer tool messages per content and emit them after the content-level message, so a content mixing functionCall and functionResponse parts no longer produces a tool message ahead of its assistant message. Refreshes the three gemini_to_* request golden snapshots to the correctly paired ids. AI-assisted: implementation and tests were produced with AI assistance.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
WalkthroughThe request conversion changes preserve assistant reasoning for Ollama and coordinate Gemini tool-call identifiers across calls and responses. Tests and golden fixtures validate pairing, ordering, fallback identifiers, and reasoning-field mapping. ChangesOllama reasoning replay
Gemini tool-call pairing
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@relaykit/relayconvert/internal/gemini_chat/to_oai_chat_req_test.go`:
- Around line 125-131: Add require.Len(t, toolIDs, 2) immediately after
obtaining toolIDs in the test, before the indexed assertions, so toolIDs[0] and
toolIDs[1] are accessed only after confirming both elements exist.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fc6d85a7-d705-459e-bd2b-711f6ddd54cc
📒 Files selected for processing (7)
relay/channel/ollama/relay-ollama.gorelay/channel/ollama/relay_ollama_req_test.gorelaykit/relayconvert/internal/gemini_chat/to_oai_chat_req.gorelaykit/relayconvert/internal/gemini_chat/to_oai_chat_req_test.gorelaykit/relayconvert/testdata/golden/request/gemini_to_claude.golden.jsonrelaykit/relayconvert/testdata/golden/request/gemini_to_openai.golden.jsonrelaykit/relayconvert/testdata/golden/request/gemini_to_openai_responses.golden.json
openAIChatToOllamaChat mapped role/content/images/tool_calls but never carried reasoning_content into OllamaChatMessage.Thinking (the response side already maps upstream thinking back to reasoning_content), so thinking-capable models served over the Ollama channel lost the previous assistant turn's reasoning on multi-turn tool-call continuations. Map GetReasoningContent() to Thinking for assistant messages. AI-assisted: implementation and tests were produced with AI assistance.
09ff415 to
7abe706
Compare
📝 变更描述 / Description
修复协议适配层两个独立缺陷(均可在单元测试级别 100% 复现,详见 #6602 与 #6603):
1. Gemini→Chat 转换 tool_call_id 配对失败(
relaykit/relayconvert/internal/gemini_chat/to_oai_chat_req.go)原实现中 functionCall 的 id 从当前 content 的
toolCalls切片长度推导(call_1起),而 functionResponse 属于下一个 content 迭代、切片恒为空,导致 tool 消息的tool_call_id恒为call_0—— tool_calls 与 tool 消息任何情况下都配对失败,严格校验配对的 OpenAI 兼容上游会直接报错;该错误值已被 golden 快照固化。修复方式:id 改为请求级递增序号分配;functionResponse 按 Gemini 协议的配对键(函数名)与先前的 functionCall 做 FIFO 配对;无法匹配的 response 分配不冲突的新 id。新增 4 组单测(单调用跨 content 配对、并行调用按名配对、同名重复调用 FIFO、未匹配回退),并重生 3 个
gemini_to_*golden 快照——diff 仅为响应位置call_0→call_1,证明无其他行为漂移。2. Ollama 渠道请求侧不回放 assistant 推理(
relay/channel/ollama/relay-ollama.go)openAIChatToOllamaChat构建OllamaChatMessage时映射了 role/content/images/tool_calls,但从不读取GetReasoningContent()、从不设置Thinking字段(响应侧已有上游 thinking → reasoning_content 的反向映射,即"拿得到、传不回")。修复方式:assistant 消息的
GetReasoningContent()映射到OllamaChatMessage.Thinking(仅 assistant 角色),与响应侧形成对称往返。新增单测覆盖 assistant 映射与非 assistant 角色不映射。🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
📸 运行证明 / Proof of Work
新增测试
构建与测试
Golden 快照:3 个
gemini_to_*请求快照更新,diff 仅为 tool 结果/响应位置的call_0→call_1(与 assistant 侧既有的call_1配对),证明行为变更严格收敛在 id 配对上。对抗审查:3 视角独立审查(配对算法逻辑攻击、无工具/无推理流量零回归验证、协议形状核对),全部通过。
Summary by CodeRabbit
Bug Fixes
Tests