# cliAPI-AIserver **Repository Path**: tianshenghuihui/cli-api-aiserver ## Basic Information - **Project Name**: cliAPI-AIserver - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-25 - **Last Updated**: 2026-03-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # cliAPI-AIserver ## 项目说明 本仓库用于承载“家庭服务系统”的独立 AI 模型 Python 服务设计与后续实现。 该服务的定位不是聊天产品,也不是通用低代码 AI 平台,而是家庭平台内部的统一 AI 能力服务,主要负责: - 模型调用统一入口 - Prompt / 角色 / 模型配置中心 - 文本处理能力承接 - 同步 AI 接口 - 异步 AI 任务执行 - 模型路由、限额、fallback 与成本治理 - 向内部调用方提供稳定可控的 API ## 当前状态 当前仓库已经进入第一阶段实现,不再只是方案文档。 当前已落地能力: - `FastAPI` 服务骨架、统一异常处理、`X-Request-Id` 中间件 - 内部鉴权已支持: - `X-Internal-Token` - 可配置请求签名 `X-Timestamp`、`X-Nonce`、`X-Signature` - `memory/redis` 两种 `nonce` 防重放后端 - 回调签名 header 生成与验签 helper - OpenAI 兼容模型网关接入,默认模型为 `gpt-5.2` - 模型 provider 路由已支持“注册中心优先,settings 回退” - Prompt / 角色配置中心已支持查询与管理接口: - `GET /api/v1/prompts` - `GET /api/v1/prompts/{prompt_code}` - `GET /api/v1/prompts/{prompt_code}/versions` - `POST /api/v1/prompts` - `PATCH /api/v1/prompts/{prompt_code}/versions/{version}` - `GET /api/v1/roles` - `GET /api/v1/roles/{role_code}` - `POST /api/v1/roles` - `PATCH /api/v1/roles/{role_code}` - Prompt / 角色配置中心第一版规则已落地: - Prompt 支持版本化、启停与单 `prompt_code` 唯一 `ACTIVE` 版本 - Prompt 支持 `default_locale + localized_contents` 多语种管理 - 运行态 `text_generate` / `chat` 可按请求 `locale` 命中对应 Prompt,未命中时回退默认语种 - 角色支持启停、默认 Prompt / 模型绑定与解绑 - 运行态 `text_generate` / `chat` 只消费 `ACTIVE` Prompt / Role - Prompt 素材登记与导入链路已补第一版: - Git 内 `scripts/prompt-registry.json` 作为提示词编目源 - `scripts/import_prompt_registry.py` 可按清单把全部登记语种导入 `ai_prompt_template` - 当前 `prompt-registry.json` 默认语种已统一切到 `en` - 同一内容重复导入会跳过,内容变化会自动生成新版本 - 模型注册中心内部管理接口已支持: - `POST /api/v1/model/providers` - `POST /api/v1/models` - 启动期已支持注册中心最小初始化校验: - 至少 1 个 `ENABLED` provider - 至少 1 个 `enabled=true` model - 默认仅告警,可通过 strict 配置阻断启动 - 模型治理已落地第一版: - `scene -> default model` 路由 - 场景白名单与 `max_tokens` 上限 - 仅默认路由允许 fallback - 请求日志与任务结果中落成本估算、fallback 元数据 - 同步接口:`POST /api/v1/ai/summarize` - 同步接口:`POST /api/v1/ai/extract/bill` - 同步接口:`POST /api/v1/ai/text/generate` - 同步接口:`POST /api/v1/ai/chat` - 异步接口:`POST /api/v1/ai/tasks` - 异步任务类型已支持: - `summarize_async` - `bill_extract_async` - `text_generate_async` - `chat_async` - 异步治理接口:`GET /api/v1/ai/dead-letters` - 异步治理接口:`POST /api/v1/ai/dead-letters/{task_id}/acknowledge` - 异步治理接口:`POST /api/v1/ai/dead-letters/{task_id}/redrive` - 查询接口:任务状态、任务结果、请求日志 - 持久化:`ai_task`、`ai_task_result`、`ai_request_log` - 异步二期能力: - 任务状态流转 `PENDING -> RUNNING -> SUCCESS/FAILED` - 基于 `Celery + Redis` 的后台投递与 worker 执行 - 队列拆分:`ai.default`、`ai.summary`、`ai.bill_extract` - 可重试错误自动退避重试,重试次数落 `retry_count` - `soft time limit` 超时收口为明确失败码 - 终态失败自动落 `ai_dead_letter_task` - 支持死信列表查询、单条详情查询、人工确认接管与人工重投 - 死信按规则动态计算 `P1/P2/P3` 严重级别 - 死信打开可选触发内部告警 webhook - 可选 `callback_url` 完成通知 - 回调请求自动追加 `X-Timestamp`、`X-Nonce`、`X-Signature` - 联调脚本: - `scripts/signed_request_smoke.py` - `scripts/signed_request_smoke.sh` - `scripts/remote_registry_smoke.py` - `scripts/remote_registry_smoke.sh` - `scripts/remote_registry_bootstrap_smoke.sh` - `scripts/remote_registry_summary_smoke.sh` - 运维脚本: - `scripts/seed_model_registry.py` - `scripts/run_celery_worker.sh` - `scripts/run_flower.sh` - 账单提取当前已支持文本窄链路: - 直接 `ocr_text` - 受控本地 `file_id -> 文本文件` - 受控 `file_url -> 文本内容` - 真实图片 / PDF / OCR / 文件中转链路暂未实现,已明确放到二期 现阶段重点工作: 1. 继续补齐 Prompt 运营侧能力和注册中心验收脚本。 2. 补异步任务监控细化、自动补偿和告警升级。 3. 继续收紧配额、缓存、幂等等治理能力。 4. OCR / 文件真实链路作为二期建设项单独推进。 ## 文档目录 项目文档统一收口到 `docs/` 目录。 - [AI 服务方案设计 v2](./docs/%E5%AE%B6%E5%BA%AD%E6%9C%8D%E5%8A%A1%E7%B3%BB%E7%BB%9F-AI%E6%A8%A1%E5%9E%8BPython%E6%9C%8D%E5%8A%A1%E6%96%B9%E6%A1%88%E8%AE%BE%E8%AE%A1-v2.md) - [AI 服务开发任务清单 v2](./docs/%E5%AE%B6%E5%BA%AD%E6%9C%8D%E5%8A%A1%E7%B3%BB%E7%BB%9F-AI%E6%A8%A1%E5%9E%8BPython%E6%9C%8D%E5%8A%A1%E5%BC%80%E5%8F%91%E4%BB%BB%E5%8A%A1%E6%B8%85%E5%8D%95-v2.md) - [AI 服务开发规范 v1](./docs/%E5%AE%B6%E5%BA%AD%E6%9C%8D%E5%8A%A1%E7%B3%BB%E7%BB%9F-AI%E6%A8%A1%E5%9E%8BPython%E6%9C%8D%E5%8A%A1%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83-v1.md) - [AI 服务最小联调样例 v1](./docs/%E5%AE%B6%E5%BA%AD%E6%9C%8D%E5%8A%A1%E7%B3%BB%E7%BB%9F-AI%E6%9C%8D%E5%8A%A1%E6%9C%80%E5%B0%8F%E8%81%94%E8%B0%83%E6%A0%B7%E4%BE%8B-v1.md) ## 建议仓库结构 当前阶段建议按如下结构演进: ```text cliAPI-AIserver/ ├── docs/ # 架构、接口、任务清单等文档 ├── app/ # FastAPI 应用代码 ├── tests/ # 测试代码 ├── migrations/ # 数据库迁移 ├── docker/ # 部署与容器配置 ├── pyproject.toml # Python 项目配置 └── README.md ``` ## 推荐实施顺序 建议不要一上来把 `Celery`、`Flower`、通用文件平台、复杂安全体系全堆进去,先把主干能力跑通。 推荐顺序: 1. 建立 `FastAPI` 项目骨架、配置、日志、异常处理。 2. 接入 OpenAI 兼容模型网关与最小模型白名单。 3. 落地 `summarize` 与窄链路 `bill extract`。 4. 建立 `ai_task`、`ai_task_result` 表与基础迁移。 5. 补齐 Prompt / 角色 / 模型注册中心与运行时路由。 6. 第二阶段引入 `Celery + Redis` 并拆分 worker 队列。 ## 本地启动 当前仓库已经具备可运行的同步 + Celery 异步服务。 示例步骤: 1. 复制 `.env.example` 为 `.env` 并填写内部鉴权 Token 与模型网关配置。 2. 安装依赖。 3. 执行数据库迁移:`python3 -m alembic upgrade head` 4. 初始化模型注册中心 provider/model 数据。 5. 如果要验证 `file_id` 文本链路,在 `data/bill_inputs/` 下准备文本文件。 6. 启动 `uvicorn`。 7. 启动 `Celery worker`。 示例命令: ```bash uvicorn app.main:app --reload ``` ```bash celery -A app.core.celery_app:celery_app worker -Q ai.default,ai.summary,ai.bill_extract -l INFO ``` 或直接使用脚本: ```bash ./scripts/run_celery_worker.sh ``` 如果要查看队列与任务状态: ```bash ./scripts/run_flower.sh ``` 说明: - `POST /api/v1/ai/tasks` 成功只代表任务已入队,不代表已执行完成。 - 如果没有启动 worker,异步任务会停留在 `PENDING`。 - 本地联调时建议至少同时开两个终端:一个跑 `uvicorn`,一个跑 `celery worker`。 - `Flower` 默认端口是 `5555`,可通过 `FLOWER_PORT` 覆盖。 ## 测试环境配置 当前已验证通过的远端测试环境建议使用独立数据库: - PostgreSQL host: `43.173.167.205` - PostgreSQL port: `5432` - database: `cliapi_aiserver_test` - Redis host: `43.173.167.205` - Redis port: `6379` - Redis: 共享实例,不建议把真实密码直接写入仓库 建议本地 `.env` 至少配置为: ```bash AI_SERVICE_DATABASE_URL=postgresql+psycopg://admin:your-password@43.173.167.205:5432/cliapi_aiserver_test AI_SERVICE_REDIS_HOST=43.173.167.205 AI_SERVICE_REDIS_PORT=6379 AI_SERVICE_REDIS_PASSWORD=your-redis-password AI_SERVICE_REDIS_DB=0 AI_SERVICE_MODEL_REGISTRY_STARTUP_CHECK_ENABLED=true AI_SERVICE_MODEL_REGISTRY_STARTUP_CHECK_STRICT=true ``` 说明: - 不要再把本项目数据落到 `postgres` 默认库。 - 当前真实联调已经确认 `postgres` 库中的本项目 `ai_*` 表已清理,后续统一使用 `cliapi_aiserver_test`。 - 如果启用签名防重放的 `redis` 后端,建议继续使用独立 `nonce key prefix`,避免和其他项目混淆。 如果要快速做一轮“注册中心 + 启动校验 + 真实模型 + 落库”的远端 smoke,可直接执行: ```bash ./scripts/remote_registry_smoke.sh \ --database-url 'postgresql+psycopg://admin:your-password@43.173.167.205:5432/cliapi_aiserver_test' \ --internal-token 'change-me' \ --provider-base-url 'https://lhgray-cli.lhgraydoc.de5.net' \ --provider-api-key 'replace-with-real-api-key' \ --redis-host '43.173.167.205' \ --redis-port 6379 \ --redis-password 'your-redis-password' ``` 脚本会自动完成: - 先对目标库执行 provider/model 幂等 seed - 再以 `startup_check_strict=true` 启动应用 - 调用 provider/model 查询与 upsert 接口 - 执行一次真实 `summarize` - 回读 `ai_task` / `ai_request_log` - 输出 `task_id`、`request_id`、`provider`、`resolved_model` 如果要按排障层次拆开执行,推荐用两条命令: 1. 只验证注册中心和启动校验: ```bash ./scripts/remote_registry_bootstrap_smoke.sh \ --database-url 'postgresql+psycopg://admin:your-password@43.173.167.205:5432/cliapi_aiserver_test' \ --internal-token 'change-me' \ --provider-base-url 'https://lhgray-cli.lhgraydoc.de5.net' \ --provider-api-key 'replace-with-real-api-key' \ --redis-host '43.173.167.205' \ --redis-port 6379 \ --redis-password 'your-redis-password' ``` 2. 在 bootstrap 已通过后,再验证真实 summarize 和落库: ```bash ./scripts/remote_registry_summary_smoke.sh \ --database-url 'postgresql+psycopg://admin:your-password@43.173.167.205:5432/cliapi_aiserver_test' \ --internal-token 'change-me' \ --provider-base-url 'https://lhgray-cli.lhgraydoc.de5.net' \ --provider-api-key 'replace-with-real-api-key' \ --redis-host '43.173.167.205' \ --redis-port 6379 \ --redis-password 'your-redis-password' ``` 说明: - `bootstrap` 模式会执行 seed、严格启动校验、provider/model 查询与 upsert。 - `summary` 模式不会重新 seed,要求目标库已经完成注册中心初始化。 - 如果 `summary` 模式一开始就失败,优先先跑 `bootstrap`,不要直接怀疑上游模型网关。 ## CI / 发布前验收 仓库已新增 GitHub Actions 工作流: - `.github/workflows/release-acceptance.yml` 当前策略: - 不默认在每次 `push` 上执行,避免共享远端环境被频繁消耗。 - 通过 `workflow_dispatch` 手动触发,或被后续发布流水线用 `workflow_call` 复用。 - 固定拆成两个 job: - `remote-registry-bootstrap` - `remote-registry-summary` 建议把它作为发布前固定验收项,顺序如下: 1. 本地单元测试通过。 2. 手动触发 `release-acceptance` workflow。 3. `bootstrap` 通过后,再由 workflow 自动执行 `summary`。 4. 两个 job 都通过,才允许继续发布。 GitHub Actions 需要预先配置这些 secrets: - `AI_REMOTE_DATABASE_URL` - `AI_INTERNAL_TOKEN` - `AI_PROVIDER_BASE_URL` - `AI_PROVIDER_API_KEY` - `AI_REDIS_HOST` - `AI_REDIS_PORT` - `AI_REDIS_PASSWORD` - `AI_REDIS_DB` - `AI_REDIS_USE_SSL` 其中建议: - `AI_REMOTE_DATABASE_URL` 指向 `cliapi_aiserver_test` - `AI_PROVIDER_BASE_URL` 使用当前代理地址 - `AI_PROVIDER_API_KEY`、`AI_REDIS_PASSWORD` 只放 GitHub Secrets,不要写入仓库 ## Prompt 素材登记方案 Prompt 素材当前采用“两层存储”: 1. Git 中的 `prompt-registry.json` 负责登记素材文件、默认语种和基础元数据。 2. 数据库中的 `ai_prompt_template` 负责运行态查询、版本、启停和默认模型绑定。 当前不采用 `MinIO` 作为 Prompt 主存储,原因很明确: - Prompt 是配置资产,不是大文件对象,最需要的是可 diff、可评审、可随代码变更审计。 - 当前运行态已经围绕 `ai_prompt_template` 建好了查询和管理能力,再引入对象存储只会增加同步复杂度。 - 多语种 Prompt 文件暂时仍保留在 Git 中,第一版导入只把 `defaultLocale` 对应文本写入数据库。 当前仓库内已补齐第一版清单文件: - `scripts/prompt-registry.json` 这个文件收口了当前已发现的 Prompt 素材,覆盖: - `novel-promotion` - `character-reference` 后续如果外部 Prompt 仓库继续新增文件,优先先更新这个清单,再执行导入脚本。 ## Prompt 素材导入 仓库内已提供导入脚本: ```bash python3 scripts/import_prompt_registry.py \ --prompt-root /Users/yjlh/Documents/code/agents/n8n-manju-workflow/prompts ``` 常用选项: - `--registry-file`:指定清单文件,默认使用 `scripts/prompt-registry.json` - `--prompt-root`:Prompt 文本根目录,必传或通过 `AI_SERVICE_PROMPT_SOURCE_ROOT` 提供 - `--prompt-code`:只导入某个指定 Prompt,可重复传入 - `--dry-run`:只预演,不提交数据库 导入规则: - 首次导入:创建 `version=1` - 清单和文本内容未变化:`skipped` - Prompt 文本或运行态关键元数据变化:自动创建新版本 - 仅状态或展示名称变化:原地更新最新版本 ## 模型注册中心初始化 当前模型路由优先级如下: 1. 按 `model_name` 查询 `ai_model`,再根据 `provider_id` 查询 `ai_model_provider` 2. 如果指定模型没有绑定 provider,则回退到数据库中的默认 provider 3. 如果数据库中还没有 provider 数据,则回退到 `.env/settings` 中的 `AI_SERVICE_MODEL_GATEWAY_*` 因此,部署后应尽快把实际使用的 provider/model 写入数据库,而不是长期依赖 settings 回退。 当前还提供了两类内部配套能力: - `POST /api/v1/model/providers`:按 `provider_code` 幂等创建/更新 provider - `POST /api/v1/models`:按 `provider_code + model_name` 幂等创建/更新 model - 启动期会自动检查注册中心是否存在最小可用配置 - `AI_SERVICE_MODEL_REGISTRY_STARTUP_CHECK_STRICT=true` 时,若 provider/model 未初始化会直接阻断服务启动 仓库内已提供幂等初始化脚本: ```bash python3 scripts/seed_model_registry.py ``` 脚本默认行为: - 按 `provider_code` 幂等创建或更新 provider - 按 `provider_id + model_name` 幂等创建或更新 model - 当 `provider_is_default=true` 时,自动清理其他 provider 的默认标记 - 当 `model_is_default=true` 时,自动清理同一 provider 下其他模型的默认标记 - 如果已有 provider 且本次没有传 `provider_api_key`,会保留数据库中的旧 key 推荐通过环境变量或命令行参数传入真实配置。示例: ```bash AI_SERVICE_SEED_PROVIDER_CODE=lhgray_proxy \ AI_SERVICE_SEED_PROVIDER_NAME="LHGray Proxy" \ AI_SERVICE_SEED_PROVIDER_BASE_URL="https://lhgray-cli.lhgraydoc.de5.net" \ AI_SERVICE_SEED_PROVIDER_API_KEY="replace-with-real-api-key" \ AI_SERVICE_SEED_MODEL_NAME="gpt-5.2" \ python3 scripts/seed_model_registry.py ``` 如果使用当前远端测试环境,推荐明确指定专用测试库: ```bash AI_SERVICE_DATABASE_URL=postgresql+psycopg://admin:your-password@43.173.167.205:5432/cliapi_aiserver_test \ AI_SERVICE_SEED_PROVIDER_CODE=lhgray_proxy \ AI_SERVICE_SEED_PROVIDER_NAME="LHGray Proxy" \ AI_SERVICE_SEED_PROVIDER_BASE_URL="https://lhgray-cli.lhgraydoc.de5.net" \ AI_SERVICE_SEED_PROVIDER_API_KEY="replace-with-real-api-key" \ AI_SERVICE_SEED_MODEL_NAME="gpt-5.2" \ python3 scripts/seed_model_registry.py ``` 如果只是预演,不真正写库,可以加: ```bash python3 scripts/seed_model_registry.py --dry-run ``` ## 联调脚本 仓库内已经提供带签名的 smoke 脚本,可直接用于内部接口联调。 示例: ```bash ./scripts/signed_request_smoke.sh summarize \ --internal-token change-me-internal-token \ --signature-key your-request-signature-key \ --dry-run \ --print-curl ``` 常用场景: - `summarize` - `bill_extract` - `task_submit` - `request_logs` - `task_status` - `task_result` - `custom` 说明: - `--dry-run` 只打印签名后的请求与 `curl` 命令,不真正发送。 - `custom` 模式可签任意内部 path,后续新接口也能复用。 ## 当前明确的架构原则 - Java 主系统只通过 HTTP / OpenAPI 调用 Python AI 服务。 - Java 可以指定模型,也可以不指定;默认模型决定权收口在 Python 服务。 - 不允许任意透传模型名,必须通过场景白名单治理。 - 重要任务与结果必须落库,不能只依赖 Redis。 - 当前鉴权仍以共享 Token 为基础,签名鉴权通过配置开关开启。 - 防重放后端可配置为 `memory` 或 `redis`;生产多实例应使用 Redis。 - 异步任务当前由 `Celery + Redis` 承接;HTTP 接口和队列协议解耦,Java 不直接接触 Redis 内部结构。 - 当前 worker 已拆分 `ai.default`、`ai.summary`、`ai.bill_extract` 三类队列,更多队列拆分还要继续演进。 ## 当前模型治理规则 - 不指定 `model` 时,按 `scene` 命中默认模型。 - 显式指定 `model` 时,只做白名单和场景校验,不自动 fallback。 - fallback 只在默认路由场景下生效,且仅针对可重试上游错误码 `50201`、`50202`。 - `max_tokens` 会受场景上限约束,超限直接返回 `scene_max_tokens_exceeded`。 - 请求日志与任务结果的 `usage` 中会带上 `estimated_cost`、`fallback_used`、`attempted_models`、`effective_max_tokens`。 ## 当前签名鉴权规则 - 开关:`AI_SERVICE_REQUEST_SIGNATURE_ENABLED=true` 时启用签名校验。 - Header:`X-Internal-Token`、`X-Timestamp`、`X-Nonce`、`X-Signature`。 - 签名串:`METHOD + "\\n" + path_with_query + "\\n" + sha256(body) + "\\n" + timestamp + "\\n" + nonce`。 - 算法:`HMAC-SHA256(request_signature_key, canonical_string)`,输出小写十六进制。 - `nonce` 存储后端由 `AI_SERVICE_REQUEST_SIGNATURE_NONCE_STORE_BACKEND` 控制,支持 `memory` / `redis`。 - 回调签名默认复用同一协议,`callback_signature_key` 未配置时回落到 `request_signature_key`。 - 回调超时时间由 `AI_SERVICE_TASK_CALLBACK_TIMEOUT_SECONDS` 控制。 - 死信告警 webhook 默认关闭,由 `AI_SERVICE_DEAD_LETTER_ALERT_ENABLED` 控制。 - 死信告警 webhook 使用 `AI_SERVICE_DEAD_LETTER_ALERT_WEBHOOK_URL` 指定地址,签名协议复用回调签名规则。 - 死信告警超时时间由 `AI_SERVICE_DEAD_LETTER_ALERT_TIMEOUT_SECONDS` 控制。 - 高优先级死信规则可通过 `AI_SERVICE_DEAD_LETTER_P1_ERROR_CODES`、`AI_SERVICE_DEAD_LETTER_P1_FAILURE_STAGES` 调整。 ## 当前异步任务规则 - `POST /api/v1/ai/tasks` 会先创建 `PENDING` 任务,再投递到 `Celery`。 - 当前队列路由: - `text_generate_async -> ai.default` - `chat_async -> ai.default` - `summarize_async -> ai.summary` - `bill_extract_async -> ai.bill_extract` - worker 消费后会把任务推进到 `RUNNING`,完成后进入 `SUCCESS` 或 `FAILED`。 - 当错误码命中 `AI_SERVICE_CELERY_RETRYABLE_ERROR_CODES` 且 `retry_count < max_retry_count` 时,会自动退避重试。 - 当前默认可重试错误码是 `50201`、`50202`。 - 当前退避参数由 `AI_SERVICE_CELERY_TASK_RETRY_BACKOFF_SECONDS`、`AI_SERVICE_CELERY_TASK_RETRY_BACKOFF_MAX_SECONDS` 控制。 - `soft time limit` 触发后会记为 `50311 async_task_soft_time_limit_exceeded`;如果你显式把 `50311` 放进可重试错误码列表,也可以继续自动重试。 - 任务进入终态 `FAILED` 后会自动写入 `ai_dead_letter_task`,供内部排障和人工重投。 - 死信详情会动态返回 `severity`,当前按失败阶段、错误码分为 `P1/P2/P3`。 - 对已进入死信的任务,可通过 `POST /api/v1/ai/dead-letters/{task_id}/acknowledge` 标记人工已接管。 - 对已进入死信的任务,可通过 `GET /api/v1/ai/dead-letters` 查询,通过 `POST /api/v1/ai/dead-letters/{task_id}/redrive` 触发一次人工重投。 - 人工确认接管必须显式提交 `operator` 和 `reason`,最近一次接管人、接管原因、接管时间会保留在死信记录中。 - 人工重投必须显式提交 `operator` 和 `reason`,最近一次重投人、重投原因、重投时间会保留在死信记录中。 - 死信任务如果后续执行成功,会自动标记为 `RESOLVED`,避免长期挂在待处理列表。 - 如果队列投递失败,任务会直接记为 `FAILED`,错误码为 `50321 async_task_dispatch_failed` 或 `50322 celery_not_enabled`。 ## 账单提取当前边界 - 当前已支持的是文本输入窄链路,不是通用文件平台。 - 输入优先级为:`ocr_text` > `file_id` > `file_url`。 - `file_id` 只允许解析到 `AI_SERVICE_BILL_INPUT_LOCAL_ROOT` 目录下的受控文本文件。 - `file_url` 只允许 `http/https` 且响应内容类型属于文本白名单。 - 当前明确不支持:图片 OCR、PDF 解析、Base64 文件、压缩包、对象存储签名下载链路。 ## 下一步建议 如果继续推进实现,建议优先补以下内容: 1. 自动补偿策略与告警升级链路。 2. `Flower` 访问鉴权与监控指标细化。 3. OCR / 文件处理真实链路。 4. 配额、幂等、缓存等治理能力。