Files
qiming/qiming-rcoder/.qoder/repowiki/zh/content/数据模型与类型/附件模型.md
2026-06-01 13:54:52 +08:00

18 KiB
Raw Permalink Blame History

附件模型

**本文引用的文件** - [attachment.rs](file://crates/shared_types/src/model/attachment.rs) - [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs) - [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs) - [content_builder.rs](file://crates/agent_runner/src/utils/content_builder.rs) - [file_utils.rs](file://crates/agent_runner/src/utils/file_utils.rs) - [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs) - [chat_handler.rsrcoder](file://crates/rcoder/src/handler/chat_handler.rs) - [chat_handler.rsagent_runner](file://crates/agent_runner/src/handler/chat_handler.rs) - [lib.rsshared_types](file://crates/shared_types/src/lib.rs) - [agent.proto](file://crates/shared_types/proto/agent.proto)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论

简介

本文件系统化阐述附件模型的设计与用途,覆盖以下方面:

  • Attachment 结构体族的组成与职责边界
  • 文件元数据路径、大小、MIME 类型)的存储方式与来源
  • 附件在聊天上下文中的引用机制、与提示词构造的关系
  • 安全检查策略(文件扩展名、大小限制、来源类型)
  • 资源清理流程(临时文件、会话与代理资源)
  • 实际用例:附件如何参与 AI 代理交互并影响提示词构造

项目结构

附件模型位于共享类型模块中,围绕该模型构建了聊天提示、内容转换、文件工具与代理交互链路。

graph TB
subgraph "共享类型"
A["attachment.rs<br/>定义 Attachment/AttachmentSource 及错误"]
B["chat_prompt.rs<br/>ChatPrompt 含 attachments 字段"]
C["chat_response.rs<br/>通用聊天响应结构"]
D["agent.proto<br/>gRPC ChatRequest 含 attachments 字段"]
end
subgraph "代理运行时"
E["content_builder.rs<br/>将 Attachment 转为 ContentBlock"]
F["file_utils.rs<br/>文件校验/读取/创建附件"]
G["acp_agent.rs<br/>构建 Prompt 并发送给代理"]
H["chat_handler.rsrcoder<br/>接收请求并转发"]
I["chat_handler.rsagent_runner<br/>接收请求并构建 ChatPrompt"]
end
A --> B
B --> G
E --> G
F --> E
H --> I
I --> G
D --> H

图表来源

章节来源

核心组件

  • 附件数据源类型支持文件路径、Base64、URL 三种来源,统一通过枚举承载
  • 附件类型:文本、图像、音频、文档四类,均包含 id、source、可选元数据如 filename、description、size、mime_type、dimensions、duration
  • 附件错误集中定义文件读取、类型不支持、Base64 解码、大小超限、URL 访问等错误
  • 聊天提示ChatPrompt 携带 attachments 与 data_source_attachments驱动代理侧提示词构建
  • 内容构建:将附件转换为 ACP ContentBlock支撑多模态提示词
  • 文件工具:校验扩展名、大小限制、读取与创建附件、清理临时文件
  • 代理交互:构建 PromptRequest将附件内容块注入提示词并携带 request_id 等元信息

章节来源

架构总览

附件在系统中的流转路径如下:

  • 客户端/上游服务通过 gRPC/HTTP 请求携带附件
  • 服务端解析请求,构建 ChatPrompt含 attachments 与 data_source_attachments
  • 代理侧将附件转换为 ContentBlock拼接到提示词中
  • 代理执行推理,返回结果;同时进行资源清理
sequenceDiagram
participant Client as "客户端"
participant Handler as "聊天处理器"
participant Prompt as "ChatPrompt"
participant Builder as "ContentBuilder"
participant Agent as "代理ACPI"
participant Resp as "响应"
Client->>Handler : "提交聊天请求含附件"
Handler->>Prompt : "构建 ChatPrompt包含 attachments"
Prompt->>Builder : "将附件转换为 ContentBlock"
Builder-->>Prompt : "返回内容块列表"
Prompt->>Agent : "构建 PromptRequest含附件内容块"
Agent-->>Resp : "返回聊天响应"
Resp-->>Client : "返回结果"

图表来源

详细组件分析

附件数据模型与元数据

  • 数据源类型
    • 文件路径:相对项目路径,便于在工作区定位
    • Base64携带数据与 MIME 类型,适合内联传输
    • URL远程资源需网络访问
  • 附件类型与元数据
    • 文本附件id、source、filename、description
    • 图像附件id、source、mime_type、filename、description、dimensions
    • 音频附件id、source、mime_type、filename、description、duration
    • 文档附件id、source、mime_type、filename、description、size
  • 元数据来源
    • MIME 类型:由创建时指定或从扩展名推断
    • 大小:文档附件可选 size 字段
    • 尺寸/时长:图像/音频附件可选 dimensions/duration
  • 访问与查询
    • 提供 id()、mime_type()、source() 等便捷方法
classDiagram
class AttachmentSource {
<<enum>>
+FilePath(path)
+Base64(data,mime_type)
+Url(url)
}
class TextAttachment {
+string id
+AttachmentSource source
+string? filename
+string? description
}
class ImageAttachment {
+string id
+AttachmentSource source
+string mime_type
+string? filename
+string? description
+ImageDimensions? dimensions
}
class AudioAttachment {
+string id
+AttachmentSource source
+string mime_type
+string? filename
+string? description
+f64? duration
}
class DocumentAttachment {
+string id
+AttachmentSource source
+string mime_type
+string? filename
+string? description
+u64? size
}
class Attachment {
<<enum>>
+Text(TextAttachment)
+Image(ImageAttachment)
+Audio(AudioAttachment)
+Document(DocumentAttachment)
+id() &str
+mime_type() &str?
+source() &AttachmentSource
}
Attachment --> AttachmentSource : "包含"
Attachment --> TextAttachment : "分支"
Attachment --> ImageAttachment : "分支"
Attachment --> AudioAttachment : "分支"
Attachment --> DocumentAttachment : "分支"

图表来源

章节来源

文件元数据存储与验证规则

  • 存储方式
    • MIME 类型:显式传入或通过扩展名推断
    • 大小:文档附件可选 size 字段;文件工具在读取时校验大小
    • 尺寸/时长:图像/音频附件可选 dimensions/duration 字段
  • 验证规则
    • 扩展名白名单:仅允许预设扩展名集合
    • 文件大小上限:默认 50MB可通过配置调整
    • 来源类型约束:
      • 文本附件:禁止压缩文件作为文本附件
      • 图像/音频/文档:按来源类型分别读取或下载
  • 错误类型
    • 文件读取失败、不支持的文件类型、Base64 解码失败、文件大小超限、URL 访问失败
flowchart TD
Start(["开始"]) --> Ext["校验扩展名"]
Ext --> ExtOK{"扩展名合法?"}
ExtOK -- 否 --> ErrExt["返回不支持的文件类型错误"]
ExtOK -- 是 --> Size["校验文件大小"]
Size --> SizeOK{"未超限?"}
SizeOK -- 否 --> ErrSize["返回文件大小超限错误"]
SizeOK -- 是 --> Read["按来源类型读取/解码"]
Read --> Done(["结束"])
ErrExt --> Done
ErrSize --> Done

图表来源

章节来源

附件在聊天上下文中的引用机制

  • 请求结构
    • rcoder 与 agent_runner 的聊天处理器均支持 attachments 字段
    • ChatPromptBuilder 用于组装 ChatPrompt包含 attachments 与 data_source_attachments
  • 引用与传递
    • ChatRequest/ChatPrompt 持有附件列表
    • gRPC ChatRequest 也包含 attachments 字段,便于跨服务传递
  • 会话与请求追踪
    • request_id 可选,若未提供则自动生成
    • 构建 PromptRequest 时将 request_id 放入 meta便于后续追踪
sequenceDiagram
participant RC as "rcoder 聊天处理器"
participant AR as "agent_runner 聊天处理器"
participant CP as "ChatPromptBuilder"
participant PR as "PromptRequest"
RC->>AR : "转发聊天请求含 attachments"
AR->>CP : "构建 ChatPromptproject_id/session_id/prompt/attachments"
CP-->>AR : "返回 ChatPrompt"
AR->>PR : "构建 PromptRequest附加附件内容块"
PR-->>AR : "返回 PromptRequest"

图表来源

章节来源

安全检查策略

  • 文件扩展名校验:仅允许白名单扩展名,避免恶意文件
  • 文件大小限制:防止过大附件导致内存压力与网络开销
  • 来源类型安全:
    • 文本附件禁止压缩文件
    • URL 读取采用网络客户端,失败即忽略并记录告警
  • 附件转换容错:读取失败或网络异常时静默忽略,不影响主流程

章节来源

资源清理流程

  • 临时文件清理:文件工具提供批量清理临时文件的能力
  • 代理与会话资源:代理侧通过生命周期守卫与连接池管理,结合定时清理任务,确保代理进程、会话与 SSE 消息得到回收
  • 清理策略要点:
    • 基于 RAII 的自动清理:移除映射后由生命周期守卫触发资源回收
    • 超时保护:清理过程设置超时,避免阻塞
    • 统计与日志:记录清理统计,便于运维监控

章节来源

附件与 AI 代理交互及提示词构造

  • 附件到内容块的转换
    • 文本:优先按文本读取,失败则忽略
    • 图像/音频:按来源读取为 Base64附带 URI
    • 文档:按 MIME 类型区分文本/二进制,文本走 TextResourceContents二进制走 BlobResourceContentsURL 走 ResourceLink
  • 提示词构造
    • 将最终提示词与附件内容块合并为 ContentBlocks
    • 若存在 data_source_attachments则在构建时加入数据源信息
    • 将 request_id 放入 meta便于通道层追踪
flowchart TD
P["ChatPrompt.attachments"] --> CB["ContentBuilder.attachments_to_content_blocks"]
CB --> Blocks{"每种附件类型?"}
Blocks --> |文本| T["TextContent"]
Blocks --> |图像| I["ImageContent(Base64)"]
Blocks --> |音频| A["AudioContent(Base64)"]
Blocks --> |文档| D{"MIME 类型为 text/* ?"}
D --> |是| DT["TextResourceContents"]
D --> |否| DB["BlobResourceContents"]
T --> Merge["合并为 ContentBlocks"]
I --> Merge
A --> Merge
DT --> Merge
DB --> Merge
Merge --> PR["PromptRequest含附件内容块"]

图表来源

章节来源

依赖分析

  • 低耦合高内聚
    • shared_types 的附件模型独立于具体实现,便于跨服务复用
    • 代理侧通过 ContentBuilder 与 file_utils 解耦附件读取与转换
  • 关键依赖关系
    • ChatPrompt 依赖 Attachment/AttachmentSource
    • ContentBuilder 依赖 agent_client_protocol 的 ContentBlock 类型
    • file_utils 依赖 base64、tokio fs、reqwest
    • 聊天处理器依赖 ChatPromptBuilder 与模型提供商配置
graph LR
Shared["shared_types: attachment.rs"] --> Prompt["chat_prompt.rs"]
Prompt --> Builder["content_builder.rs"]
Builder --> Utils["file_utils.rs"]
HandlerR["chat_handler.rsrcoder"] --> HandlerA["chat_handler.rsagent_runner"]
HandlerA --> Prompt
Proto["agent.proto"] --> HandlerR

图表来源

章节来源

性能考虑

  • 附件读取与转换
    • 优先使用 Base64 内联传输,减少磁盘 IO对大文件建议使用 URL 或文件路径
    • 文档附件优先按文本读取,失败再降级为二进制,避免不必要的解码
  • 网络访问
    • URL 读取采用异步客户端,失败即短路,避免阻塞
  • 大小限制
    • 默认 50MB 上限,可根据部署环境调优,平衡吞吐与稳定性
  • 清理与回收
    • 定时清理代理与会话资源,避免长期运行导致资源泄漏

故障排查指南

  • 常见错误与定位
    • 文件读取失败:检查路径是否存在、权限是否足够
    • 不支持的文件类型:确认扩展名在白名单中
    • Base64 解码失败:确认数据格式正确且未被截断
    • 文件大小超限:调整上传策略或增大阈值
    • URL 访问失败:检查网络连通性与目标可达性
  • 日志与追踪
    • 附件转换失败会记录告警日志,建议结合 request_id 追踪
    • 清理任务输出统计信息,便于发现异常增长

章节来源

结论

附件模型通过统一的数据源与类型抽象,为多模态聊天提供了清晰的扩展点。配合严格的验证规则与容错转换,既保证了安全性,又提升了可用性。在代理交互层面,附件被无缝注入提示词,显著增强了 AI 的上下文理解能力。建议在生产环境中合理设置大小阈值与扩展名白名单,并持续监控清理任务与日志,确保系统稳定高效运行。