Skip to content

【No.8】 Agentic 多协议一致性测试 - #341

Closed
yaoyao12345666 wants to merge 3 commits into
redai-studio:mainfrom
yaoyao12345666:test/agentic-protocol-consistency
Closed

yaoyao12345666 wants to merge 3 commits into
redai-studio:mainfrom
yaoyao12345666:test/agentic-protocol-consistency

Conversation

@yaoyao12345666

Copy link
Copy Markdown

Summary

  1. Add offline canonical request consistency coverage for Chat Completions, OpenAI Responses, and Anthropic Messages.
  2. Compare normalized messages, tools, and chat_template_kwargs from independently authored native fixtures.
  3. Cover text, multi-text blocks, assistant tool calls, tool results, valid HTTP and base64 image inputs, invalid roles/content/images, deterministic hashes, key-order independence, array order, and input immutability.
  4. Tighten normalization validation where malformed content or tool definitions could be silently dropped, and canonicalize equivalent pure text-block lists to one string.

Type of Change

Type Included Details
Tests Yes Adds cross-protocol golden fixtures and focused consistency, error-path, hash, and immutability tests.
Bug fix Yes Rejects malformed requests that were previously ignored or projected inconsistently.
Runtime behavior Limited Only request normalization and validation paths used by the three protocol adapters are adjusted.
Documentation Yes Documents fixture design, canonical fields, validation scope, and reproducible commands.
Refactor No No unrelated restructuring.
Build or tooling No No dependency, CI, or build configuration changes.

Test plan

$ pytest tests/agentic/test_protocol_canonicalization.py -q
91 passed

$ PYTHONHASHSEED=1 pytest tests/agentic/test_protocol_canonicalization.py -q
91 passed

$ PYTHONHASHSEED=777 pytest tests/agentic/test_protocol_canonicalization.py -q
91 passed

$ ruff format --check relax/agentic/session/state.py relax/agentic/session/service.py tests/agentic
3 files already formatted

$ ruff check relax/agentic/session/state.py relax/agentic/session/service.py tests/agentic
All checks passed

$ python .pre-commit-hooks/docformatter_compat.py --in-place --wrap-descriptions 79 ...
No changes

$ python .pre-commit-hooks/check_conflict_markers.py ...
Passed

$ python .pre-commit-hooks/gitleaks_tracked.py
no leaks found

$ git diff --check
Passed

Scope

This PR is limited to Agentic protocol request canonicalization and its test coverage. It does not modify scheduling, lifecycle management, training, model execution, GPU execution, or external services.

Related to #321

# 🐛 Bug Fix

## Validate canonical protocol inputs

- Reject malformed message blocks, image payloads, tool calls, tool results, and unsupported tool types with stable request paths
- Normalize multiple text blocks to one canonical string across protocol adapters
- Canonicalize JSON-backed tool schemas and template values before state hashing
- Preserve deterministic state hashes without stringifying unsupported values

---

# ✅ Tests

## Add independent three-protocol golden fixtures

- Cover Chat Completions, Responses, and Anthropic Messages through their public normalization paths
- Verify complete messages, tools, and chat template kwargs across text, multi-text, tool, and image scenarios
- Exercise invalid roles, missing identifiers, incomplete content, image failures, ordering, and input immutability

---

# 📝 Documentation

## Document the Task 8 test contract

- Record fixture structure, canonical fields, portable validation commands, and task boundaries
@rai-studio-bot

rai-studio-bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Nyanpasu 审查看板

审查状态: ✅ 已通过

审查版本: 2d0e920

复审通过(针对合并 main 后的新 head):PR 自身 11 个文件与上一轮已批准的 ac6c735 逐字节一致,合并未触及 PR 文件且经导入闭包核查无交互;此前三项发现仍保持修复。91 项协议测试在依赖隔离下通过,CI 全量单测(Python 3.10/3.11/3.12)、pre-commit 与多模态 GPU 集成均通过;H20 GPU 单测仍在运行,与本 PR 改动范围无关。

审查阶段进度范围与结果
常规审查 ✅ 已完成 已核查 ac6c735..2d0e920 增量(纯 main 合并):PR 文件 0 行变化、无冲突解决、main 变更模块均不在 PR 文件导入闭包内;F1/F2/F3 三项修复在新 head 复验仍在;91 项协议测试以真实归一化函数(依赖隔离)通过,F1 回归用例以真实 _sample_messages+check_messages 通过;ruff 与 CI(三版本 Python 全量单测、pre-commit、多模态 GPU)通过。未发现新问题。
深度审查 ✅ 已完成 未派发子任务:设计已经两轮审查验证且本轮代码未变,改为父审直接完成生产与测试必要性审计(范围小),结论均为保留,无简化建议。

审查发现

待处理
编号 严重性 问题状态规则来源
暂无待处理的记录。
已解决或已取代
编号 严重性 问题状态规则来源
F1 High severity 先转换数据集图片再执行 canonical 校验 ✅ 已解决 —
F2 Medium severity 保留无参数函数省略 parameters 的合法写法 ✅ 已解决 —
F3 Medium severity 允许 Anthropic 空工具结果省略 content ✅ 已解决 —
提交范围 · 接收 11 · 建议移出 0 · 待确认 0

接收 11 个文件 · 建议移出 0 个文件 · 待确认 0 个文件。移出与待确认部分暂停深审,不代表审查通过。

文件结论仓库维护必要性依据替代去向或方案
relax/agentic/pipeline/runtime.py
relax/agentic/session/service.py
relax/agentic/session/state.py
接收 三个协议入口(Chat Completions / Responses / Anthropic Messages)的请求归一化与校验是既有服务的生产行为:service.py 的 HTTP handler 调用 state.py 的 normalize/check 链路,runtime.py 的 _sample_messages 决定数据集消息进入会话的顺序。本 PR 修复校验顺序与静默丢弃畸形请求的问题,均由真实调用方触发。 PR 描述(Related to #321);调用方:relax/agentic/session/service.py 的请求 handler、relax/agentic/pipeline/runtime.py 的 _sample_messages。 不改动生产代码则无法修复畸形请求被静默投影和数据集图片先校验后转换的顺序缺陷;作为外部实验保留不能交付该行为。
tests/agentic/__init__.py
tests/agentic/README.md
tests/agentic/fixtures/anthropic_messages.json
tests/agentic/fixtures/canonical.json
tests/agentic/fixtures/chat_completions.json
tests/agentic/fixtures/responses.json
tests/agentic/test_protocol_canonicalization.py
tests/test_agentic_rollout.py
接收 离线确定性回归测试直接执行真实归一化入口并对照独立编写的金标 fixtures,覆盖三协议一致性、错误路径、hash 稳定性与输入不可变性;test_agentic_rollout.py 补充数据集图片先转换后校验的回归(对应上轮 P1 修复)。fixtures 被测试模块直接消费,README 记录 fixtures 设计与复现命令,属于测试套件自身文档。 PR 描述 Test plan;测试模块 tests/agentic/test_protocol_canonicalization.py 与 tests/test_agentic_rollout.py 的实际断言。 将 fixtures 移为外部 PR artifact 会使 CI 无法离线复现一致性校验;仅保留 smoke 测试无法覆盖错误路径与 hash 稳定性边界。
精简审查与验证依据
审查范围进度结论
生产代码 ✅ 已完成 三个生产文件的校验与归一化改动均有真实调用方与回归覆盖;考察过的替代方案均不能同时保住离线确定性哈希、跨协议一致性与带字段路径的报错,全部保留。
测试 ✅ 已完成 测试套件直接执行真实归一化入口并以手写 canonical 预期对照;上轮已裁剪过度收紧用例,本轮复核无重复或可合并的维护负担,全部保留。

生产代码的必要性与替代方案

范围必须保留的契约更简单的方案结论依据与限制
relax/agentic/session/state.py 的内容块/工具定义校验与 canonical 序列化(_normalize_content_blocks、normalize_tools、_canonical_json_value、状态哈希) 三协议请求进入 Agentic Session 前归一化为唯一 canonical 形态并拒绝畸形输入;调用方为 relax/agentic/session/service.py 的协议 handler 与 relax/agentic/pipeline/runtime.py 的 _sample_messages。 仅依赖下游模型服务端校验,或引入 pydantic 模型统一校验。 保留 下游校验无法提供离线确定性哈希与跨协议一致性(PR 目标);pydantic 引入新抽象且与现有显式校验风格不符。上轮曾发现过度收紧(无参数工具、空 tool result)并已修复,当前边界由 91 项测试与 CI 三版本单测覆盖。
relax/agentic/session/service.py 三协议请求归一化路径的校验收紧 Chat Completions / Responses / Anthropic Messages 的 HTTP 入口对畸形请求返回带字段路径的 400;调用方为 FastAPI 路由。 把全部校验集中到 state.py 的 check_messages。 保留 Anthropic 块投影(tool_result/image 块到 messages)只存在于 service.py,内容形状校验需与投影同址;集中校验会丢失协议侧字段路径并拆散投影逻辑。
relax/agentic/pipeline/runtime.py 的 _normalize_prompt 新增 transport_dataset_media 参数 _sample_messages 先转换数据集媒体再校验(上轮 P1 修复);调用方 _build_session_specs。 让 check_messages 容忍 {"type":"image"} 数据集块,转换后再二次校验。 保留 4 行最小改动修复顺序缺陷;容忍未定义块会削弱校验强度;有 test_sample_messages_transports_dataset_images_before_validation 回归覆盖并在 CI 通过。

测试的必要性与替代方案

范围必须保留的契约更简单的方案结论依据与限制
tests/agentic/test_protocol_canonicalization.py 与四份 fixtures(含手写 canonical.json) 语义相同的跨协议请求得到相同 canonical 状态、hash 与键序无关、输入不可变、错误路径带字段路径与 400。 用属性测试生成请求,或合并为单一参数化用例。 保留 PR 目标即独立编写的原生协议 fixtures(防止从一协议转换生成而掩盖作者侧差异);canonical.json 手写避免用待测函数生成预期值。91 项测试在本轮依赖隔离运行与 CI 三版本 Python 下均通过。
tests/test_agentic_rollout.py 新增 _sample_messages 图文数据集回归用例 数据集图片先转换后校验(P1 修复的直接回归覆盖)。 在协议一致性测试中模拟该路径。 保留 协议测试不经过 _sample_messages 的数据集路径;该用例直接调用真实入口,本轮以依赖隔离真实函数复验通过,CI 全量单测亦通过。
tests/agentic/README.md(81 行 fixtures 设计文档) 记录 fixtures 编写原则(各协议独立编写、canonical 手写)与复现命令。 移至 docs/ 双语文档,或仅保留在 PR 描述。 保留 文档与测试套件同址、随套件演进维护;PR 描述不构成持久维护载体;docs/ 面向终端用户而非测试贡献者。属可接受的测试局部文档。
Powered by Nyanpasu with glm-5.3[1m] xhigh, please check the suggestions carefully.

@rai-studio-bot rai-studio-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要修改:新的内容校验会阻断全局数据集的多模态 Agentic 会话构建,另有工具请求的兼容性回归,详见行级意见。

新增 91 项测试通过,另以依赖隔离的实际函数验证了基线与当前提交的行为差异。现有 Agentic 回归测试因缺少 numpy 无法收集;尚无 CI 结果,未运行需要多节点 GPU 的集成测试。

Powered by Nyanpasu with gpt-6-astra medium, please check the suggestions carefully.

Comment on lines +173 to +174
else:
raise ValueError(f"{field}.type must be one of: image_url, text")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 优先级:P1

请在执行这项 canonical 校验前先转换数据集图片。build_messages(relax/utils/data/data_utils.py:260)在 --multimodal-keys 路径生成 {"type":"image","image":...},而 _sample_messages(relax/agentic/pipeline/runtime.py:741)先 _normalize_prompt → check_messages,之后才 _transport_dataset_message_media。因此使用全局图文数据集时,这里会在合法内部图片转为 image_url 之前抛错,使 _build_session_specs 失败。

用实际源码函数做依赖隔离验证:对含 {"type":"image","image":"https://example.com/image.png"} 的 user prompt,基线成功生成 image_url,当前提交抛出 messages[0].content[0].type must be one of: image_url, text。请调整转换/校验顺序,并补充 _sample_messages 的图文数据集回归用例;只测三种 HTTP 请求入口无法覆盖这条路径。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 ac6c735 修复:_sample_messages 现在先转换数据集媒体,再调用 check_messages。原图文复现已成功生成 image_url;新增 test_sample_messages_transports_dataset_images_before_validation 也通过依赖隔离的实际函数执行验证。完整测试模块仍因环境缺少 numpy 无法收集,此项代码问题已解决。

Comment thread relax/agentic/session/state.py Outdated
Comment on lines +272 to +274
parameters = function.get("parameters")
if not isinstance(parameters, dict):
raise TypeError(f"tools[{index}].function.parameters must be a dict, got {type(parameters)}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 优先级:P2

请保留 Chat Completions 无参数函数省略 parameters 的合法写法。OpenAI 的函数定义 明确允许省略该字段,表示空参数列表。现在普通 user 消息配合 tools=[{"type":"function","function":{"name":"get_time"}}] 会在 _normalized_chat_request 返回 400;基线可通过归一化。这会使已有无参数工具请求失效,新增 MISSING_TOOL_SCHEMA_CASES 反而固定了该回归。请区分字段缺省与字段类型错误,为缺省值保留/定义稳定的无参数表示,并改为正向覆盖。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 ac6c735 修复:省略 parameters 的无参数函数现在归一化为 {},显式传入错误类型仍会被拒绝。原请求复现和新增正向用例均通过。

Comment thread relax/agentic/session/service.py Outdated
Comment on lines +820 to +825
elif block_type == "tool_result":
if "content" not in block:
raise AgenticChatRequestError(
f"{block_field}.content is required",
param="messages",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 优先级:P2

请继续接受省略 content 的空工具结果。Anthropic 官方文档 将该字段标为可选,并给出了只有 type 和 tool_use_id 的示例。在此前存在匹配 tool_use 时,基线会通过下方 block.get("content", "") 将这种结果归一化为空字符串;新增检查却返回 400,导致无输出工具执行后的合法下一轮请求失败。删除这项必填限制,并将省略字段的形式加入已有空工具结果一致性测试。

Suggested change
elif block_type == "tool_result":
if "content" not in block:
raise AgenticChatRequestError(
f"{block_field}.content is required",
param="messages",
)
elif block_type == "tool_result":

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 ac6c735 修复:移除了 content 必填检查,省略该字段的匹配工具结果恢复归一化为空字符串。原请求复现及 test_anthropic_empty_tool_result_may_omit_content 均通过。

@rai-studio-bot rai-studio-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复查通过:此前问题均已修复,本轮未发现新的需修改问题。

91 项协议测试通过;新增数据集图片回归用例通过依赖隔离验证。完整 Agentic 测试模块仍因缺少 numpy 无法收集,暂无 CI 结果;未运行需要多节点 GPU 的集成测试。

Powered by Nyanpasu with gpt-6-astra medium, please check the suggestions carefully.

@rai-studio-bot rai-studio-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审通过(合并 main 后的新 head 2d0e9203)

本轮针对 merge commit 复查:PR 自身 11 个文件与上一轮已批准的 ac6c735 逐字节一致,合并未触及 PR 文件;经导入闭包核查,main 新变更的模块均不在 PR 改动文件的依赖范围内,无交互影响。此前三项发现(数据集图片转换顺序、无参数工具 schema 省略、Anthropic 空 tool result 省略 content)在新 head 复验均保持修复。91 项协议一致性测试以真实归一化函数复跑通过,CI 全量单测(Python 3.10/3.11/3.12)、pre-commit 与多模态 GPU 集成亦全部通过;H20 GPU 单测仍在运行,与本 PR 改动范围无关。

三条行级线程在上轮已有验证回复;本账号缺少线程 resolve 权限,烦请作者或维护者确认后点击 resolved。

审查详情、范围裁定与必要性审计见看板:#341 (comment)

Powered by Nyanpasu with glm-5.3[1m] xhigh, please check the suggestions carefully.

@SigureMo

SigureMo commented Oct 4, 2026

Copy link
Copy Markdown
Member

如果完成了,记得按照流程「提交」哦

@SigureMo

SigureMo commented Oct 8, 2026

Copy link
Copy Markdown
Member

本赛题已经由 #335 合入并锁定,感谢参与~

@SigureMo SigureMo closed this Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants