feat(dingtalk): enable secure multimodal image QA
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,34 @@
|
||||
from pathlib import Path
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
OUT = Path(__file__).with_name("dingtalk-vision-acceptance.png")
|
||||
FONT_PATH = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
|
||||
|
||||
image = Image.new("RGB", (1280, 720), "#F7FAFC")
|
||||
draw = ImageDraw.Draw(image)
|
||||
font_title = ImageFont.truetype(FONT_PATH, 46)
|
||||
font_code = ImageFont.truetype(FONT_PATH, 58)
|
||||
font_label = ImageFont.truetype(FONT_PATH, 34)
|
||||
font_question = ImageFont.truetype(FONT_PATH, 38)
|
||||
|
||||
# Header and unique OCR target.
|
||||
draw.rounded_rectangle((50, 40, 1230, 190), radius=24, fill="#E6F4FF", outline="#1677FF", width=4)
|
||||
draw.text((85, 65), "WeKnora 钉钉多模态验收图", font=font_title, fill="#102A43")
|
||||
draw.text((85, 120), "唯一验收码:WK-VISION-7264", font=font_code, fill="#C53030")
|
||||
|
||||
# Three visually distinct objects.
|
||||
draw.ellipse((120, 280, 340, 500), fill="#1677FF", outline="#0B4F9C", width=8)
|
||||
draw.text((160, 520), "蓝色圆形", font=font_label, fill="#0B4F9C")
|
||||
|
||||
draw.polygon([(520, 500), (650, 275), (780, 500)], fill="#FFD43B", outline="#9C7600", width=8)
|
||||
draw.text((548, 520), "黄色三角形", font=font_label, fill="#725500")
|
||||
|
||||
draw.rounded_rectangle((940, 295, 1140, 495), radius=12, fill="#2FB344", outline="#176B2A", width=8)
|
||||
draw.text((958, 520), "绿色方形", font=font_label, fill="#176B2A")
|
||||
|
||||
question = "问题:蓝色圆形右侧紧邻的图形是什么颜色和形状?"
|
||||
draw.rounded_rectangle((80, 610, 1200, 690), radius=18, fill="#FFF4E6", outline="#E67700", width=3)
|
||||
draw.text((110, 625), question, font=font_question, fill="#7C3E00")
|
||||
|
||||
image.save(OUT, format="PNG", optimize=True)
|
||||
print(OUT)
|
||||
@@ -0,0 +1,170 @@
|
||||
# 阶段2:钉钉图片传输与多模态识别验收计划
|
||||
|
||||
## 1. 验收目标
|
||||
|
||||
验证图片从钉钉用户消息进入 WeKnora,并由视觉模型真实读取图片内容后返回结果;不得把“图片已上传”“图片作为知识文件入库”或“删除图片后按纯文字回答”判定为多模态通过。
|
||||
|
||||
## 2. 当前自动化验证基线
|
||||
|
||||
测试分支:`feature/dingtalk-image-only`
|
||||
|
||||
生产基线:`4022040e`(不包含阶段3~5提交)
|
||||
|
||||
阶段2提交:待本轮代码审查通过后创建。
|
||||
|
||||
已执行的目标测试:
|
||||
|
||||
```bash
|
||||
GOTOOLCHAIN=local GOPROXY=off GOMAXPROCS=4 \
|
||||
/home/zheromiku/.local/toolchains/go1.26.0/bin/go test -p 1 \
|
||||
./internal/im/dingtalk \
|
||||
-run 'Test(ParseCallbackMessagePicture|AdapterDownloadFileUsesMessageFilesAPI|ValidateDingTalkDownloadURLRejectsUnsafeTargets|ParseDingTalkStreamPayloadPicture|ParseDingTalkStreamPayloadPictureJSONString)$' \
|
||||
-count=1
|
||||
|
||||
GOTOOLCHAIN=local GOPROXY=off GOMAXPROCS=4 \
|
||||
/home/zheromiku/.local/toolchains/go1.26.0/bin/go test -p 1 \
|
||||
./internal/im -run 'Test(PrepareIMImageForQA|IMQAErrorReply|FailClosedIMImageAnswer)' -count=1
|
||||
|
||||
GOTOOLCHAIN=local GOPROXY=off GOMAXPROCS=4 \
|
||||
/home/zheromiku/.local/toolchains/go1.26.0/bin/go test -p 1 \
|
||||
./internal/models/chat \
|
||||
-run '^TestRemoteAPIChat_MultimodalUnsupportedDoesNotStripImages$' \
|
||||
-count=1
|
||||
```
|
||||
|
||||
结果:钉钉图片解析、两段式下载、Token请求禁重定向、DNS解析后固定IP拨号、保留/Teredo/受限6to4地址拒绝、签名URL错误脱敏、所有data URI及图片调试日志全量脱敏、JPEG/PNG格式/大小/维度校验、Worker延迟下载、`QARequest.ImageURLs`传递,以及视觉失败/流式部分输出时禁止删图或伪成功,全部通过。
|
||||
|
||||
已执行相关包回归:
|
||||
|
||||
```bash
|
||||
GOTOOLCHAIN=local GOPROXY=off GOMAXPROCS=4 \
|
||||
/home/zheromiku/.local/toolchains/go1.26.0/bin/go test -p 1 \
|
||||
./internal/agent ./internal/im/dingtalk ./internal/im ./internal/models/chat ./internal/utils ./internal/logger \
|
||||
./internal/application/service/chat_pipeline ./internal/application/service -count=1
|
||||
```
|
||||
|
||||
结果:八个相关包全部通过,八包 `go vet` 同步通过。
|
||||
|
||||
## 3. 真实验收前置条件
|
||||
|
||||
- 采用已授权的 App-only 可回滚部署:先备份当前 App 镜像标签,仅重建 `app`,不重建 PostgreSQL、Redis、前端、DocReader 或 MinerU。
|
||||
- 部署后先检查 `WeKnora-app` 健康状态;失败立即恢复备份镜像并仅重建 `app`。
|
||||
- 钉钉应用已开通机器人消息文件下载权限。
|
||||
- WeKnora Agent 已开启“图片上传/多模态”。
|
||||
- Agent 当前问答模型支持视觉输入,或配置了明确的独立 VLM;VLM不可用或未返回图片描述时必须失败关闭。
|
||||
- 不允许在视觉能力不足时静默删除图片并继续生成答案。
|
||||
|
||||
## 4. 测试数据
|
||||
|
||||
标准测试图:
|
||||
|
||||
```text
|
||||
docs/test-plans/assets/dingtalk-vision-acceptance.png
|
||||
```
|
||||
|
||||
图片包含:
|
||||
|
||||
- 唯一验收码:`WK-VISION-7264`
|
||||
- 蓝色圆形
|
||||
- 黄色三角形
|
||||
- 绿色方形
|
||||
- 明确问题:蓝色圆形右侧紧邻的图形是什么颜色和形状?
|
||||
|
||||
标准答案必须同时包含:
|
||||
|
||||
```text
|
||||
WK-VISION-7264
|
||||
黄色三角形
|
||||
```
|
||||
|
||||
## 5. 人工验收用例
|
||||
|
||||
### DT-IMG-01:PNG图片真实识别
|
||||
|
||||
操作:在钉钉中把标准测试图发送给测试机器人。
|
||||
|
||||
通过标准:
|
||||
|
||||
- 机器人成功回复;
|
||||
- 回复包含 `WK-VISION-7264`;
|
||||
- 回复包含“黄色三角形”;
|
||||
- 回复不是“请用文字描述”“当前不支持图片”或无关答案。
|
||||
|
||||
### DT-IMG-02:普通截图OCR
|
||||
|
||||
操作:发送一张包含中文、英文和数字的实际设备截图。
|
||||
|
||||
通过标准:
|
||||
|
||||
- 能提取截图里的关键文字;
|
||||
- 能结合图片回答具体问题;
|
||||
- 不编造截图中不存在的错误码、型号或参数。
|
||||
|
||||
### DT-IMG-03:纯文字回归
|
||||
|
||||
操作:向同一机器人发送普通文字问题。
|
||||
|
||||
通过标准:正常进入原知识库问答,图片功能不影响文字消息。
|
||||
|
||||
### DT-IMG-04:伪图片拒绝
|
||||
|
||||
操作:将非图片内容伪装为 `.png` 后发送。
|
||||
|
||||
通过标准:拒绝处理,提示图片格式校验失败;伪图片不得进入模型。
|
||||
|
||||
### DT-IMG-05:超限图片拒绝
|
||||
|
||||
操作:发送超过10MB的JPG/PNG。
|
||||
|
||||
通过标准:明确提示10MB限制,不进入模型请求。
|
||||
|
||||
### DT-IMG-06:模型不支持视觉
|
||||
|
||||
操作:测试环境临时选择不支持图片的问答模型后发送标准图。
|
||||
|
||||
通过标准:明确提示视觉模型未配置或不支持;禁止删除图片后继续给出看似正常的答案。
|
||||
|
||||
### DT-IMG-07:钉钉权限缺失
|
||||
|
||||
操作:在没有消息文件下载权限的测试应用中发送图片,或使用接口模拟对应403响应。
|
||||
|
||||
通过标准:日志记录脱敏后的权限错误,用户收到可理解提示;不得记录 access token、downloadCode 或临时下载URL。
|
||||
|
||||
## 6. 日志观察点
|
||||
|
||||
发送标准图后,检查测试环境日志:
|
||||
|
||||
```bash
|
||||
sudo docker logs WeKnora-app --since 5m 2>&1 | \
|
||||
grep -E '\[DingTalk\]|Failed to prepare image|message file|multimodal|vision|image'
|
||||
```
|
||||
|
||||
日志不得出现:
|
||||
|
||||
- access token明文;
|
||||
- `downloadCode`明文;
|
||||
- 完整临时下载URL;
|
||||
- 完整Base64图片。
|
||||
|
||||
## 7. 数据检查
|
||||
|
||||
阶段2只验收图片传输和模型识别。消息审计字段的完整性、Token统计、知识库命中片段和渠道统计属于阶段3,本阶段不提前判定通过。
|
||||
|
||||
本阶段允许确认:
|
||||
|
||||
- 用户消息以默认视觉问题进入原有会话历史;
|
||||
- 图片只作为瞬态 `QARequest.ImageURLs` 传给模型;
|
||||
- 数据库不保存完整Base64、临时下载码和临时签名URL。
|
||||
|
||||
## 8. 通过门槛
|
||||
|
||||
必须同时满足:
|
||||
|
||||
1. 图片自动化测试全部通过;
|
||||
2. 相关IM包回归通过;
|
||||
3. `DT-IMG-01`和`DT-IMG-02`真实钉钉测试通过;
|
||||
4. `DT-IMG-03`文字回归通过;
|
||||
5. `DT-IMG-04`~`DT-IMG-07`至少完成目标验证或提供自动化等价证据;
|
||||
6. 用户确认验收。
|
||||
|
||||
在以上条件完成前,阶段2状态保持“进行中”,不得启动阶段3。
|
||||
Reference in New Issue
Block a user