Files
姚章浩 693cd952cd feat(asset): 清理被截断的结尾图片引用,修复整单 502
仓库首次入库(此前仅存在于本地工作区与测试服构建产物中,未上传)。

改动(src/knowledge_adapter/asset_content_processor.py):
- 新增 _TRUNCATED_TRAILING_MARKDOWN_RESOURCE_IMAGE 规则,清除 chunk 末尾被截断的
  ![](resource://xxxx 残片(WeKnora 分块在图片引用中间截断时产生,旧逻辑无法匹配完整引用,
  残留 resource:// 触发 ContentProcessingError,导致整单 502)
- 回归测试 tests/test_asset_content_processor.py::
  test_truncated_trailing_markdown_resource_image_is_removed

验证证据:
- 测试服 120.76.217.51,镜像 knowledge-adapter-service:reviewed-test-aeab4b5fca2d
  (release aeab4b5fca2d8661):KB d015d05c-25c8-4d63-b2ab-e8590d3c2dfb 5 个查询全部
  http=200、records=5、残留 resource:// = 0;KB b9dacd62 无退化;容器日志无 error/exception
- 本地:pytest 141 项全通过、ruff 全通过
- 该文件与 258c31e0fe07fd08 源码的差异经逐文件 md5 比对,为唯一变更文件
2026-09-16 10:01:27 +08:00

88 lines
2.6 KiB
Plaintext

map $http_x_request_id $adapter_request_id {
"~^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$" $http_x_request_id;
default $request_id;
}
limit_req_zone $binary_remote_addr zone=adapter_retrieval:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=adapter_assets:10m rate=30r/s;
server {
listen 80;
server_name assets.example.com;
access_log off;
return 404;
}
server {
listen 443 ssl;
http2 on;
server_name assets.example.com;
ssl_certificate /etc/letsencrypt/live/assets.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/assets.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:adapter_tls:10m;
ssl_session_timeout 1d;
server_tokens off;
access_log off;
error_log /var/log/nginx/knowledge-adapter-error.log error;
client_max_body_size 64k;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy no-referrer always;
location = /retrieval {
limit_except POST {
deny all;
}
limit_req zone=adapter_retrieval burst=20 nodelay;
proxy_pass http://127.0.0.1:18080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_set_header X-Request-ID $adapter_request_id;
proxy_set_header X-Forwarded-Proto https;
proxy_connect_timeout 3s;
proxy_send_timeout 20s;
proxy_read_timeout 20s;
proxy_intercept_errors off;
proxy_hide_header Server;
proxy_hide_header X-Powered-By;
}
location ~ ^/i/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ {
limit_except GET {
deny all;
}
limit_req zone=adapter_assets burst=60 nodelay;
proxy_pass http://127.0.0.1:18080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_set_header X-Request-ID $adapter_request_id;
proxy_set_header X-Forwarded-Proto https;
proxy_connect_timeout 3s;
proxy_send_timeout 10s;
proxy_read_timeout 10s;
proxy_intercept_errors off;
proxy_hide_header Server;
proxy_hide_header X-Powered-By;
}
location = /healthz {
allow 127.0.0.1;
allow ::1;
deny all;
proxy_pass http://127.0.0.1:18080;
proxy_set_header X-Request-ID $adapter_request_id;
proxy_connect_timeout 2s;
proxy_read_timeout 2s;
proxy_intercept_errors off;
}
location / {
return 404;
}
}