145 lines
5.7 KiB
Markdown
145 lines
5.7 KiB
Markdown
# Agent LLM Config Implementation Plan
|
||
|
||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||
|
||
**Goal:** 将 `system_agents.config` 中的 `temperature` / `max_tokens` 以受约束方式加载到运行时,并在调用 LiteLLM 时按需透传。
|
||
|
||
**Architecture:** 在应用层 `RunService` 读取模型选择时同步读取并校验 `SystemAgents.config`;将校验后的 `SystemAgentLLMConfig` 传入 `CrewAIRuntime`;由 runtime 将配置转交给 LiteLLM client,client 仅在值非 `None` 时向 `completion()` 传参,避免不必要的 provider 兼容风险。
|
||
|
||
**Tech Stack:** FastAPI, SQLAlchemy (async), Pydantic v2, LiteLLM, pytest
|
||
|
||
---
|
||
|
||
## 背景与修正点
|
||
|
||
- 当前真实调用链为:`RunService._load_agent_model_selection()` -> `create_runtime()` -> `CrewAIRuntime.execute()` -> `run_completion()`,并非 `load_stage_models()`。
|
||
- `SystemAgentLLMConfig` 已存在:`backend/src/core/agent/domain/system_agent_config.py`。
|
||
- `system_agents.config` 目前在初始化 YAML 侧有约束,但运行时 DB 读取仍需二次校验,防止脏数据绕过。
|
||
|
||
## 规则约束
|
||
|
||
- 严格 TDD:先写失败测试,再做实现。
|
||
- Python 命令统一使用 `uv run ...`。
|
||
- 仅做增量改动,不回滚或覆盖与本任务无关的已有变更。
|
||
|
||
## 字段映射与透传策略
|
||
|
||
| 配置字段 | LiteLLM 参数 | 规则 |
|
||
|---|---|---|
|
||
| `temperature` | `temperature` | `None` 不透传;非空直接透传 |
|
||
| `max_tokens` | `max_tokens` | `None` 不透传;非空直接透传 |
|
||
|
||
---
|
||
|
||
### Task 1: 应用层加载并校验 Agent LLM Config
|
||
|
||
**Files:**
|
||
- Modify: `backend/src/core/agent/application/run_service.py`
|
||
- Test: `backend/tests/unit/core/agent/test_run_resume_service.py`
|
||
|
||
**Step 1: 写失败测试(RED)**
|
||
|
||
新增单测覆盖以下行为:
|
||
1. `_load_agent_model_selection()` 返回三元组:`(model_code, provider_name, llm_config)`。
|
||
2. 当 DB `config` 为 `{}` 时,`llm_config.temperature/max_tokens` 为 `None`。
|
||
3. 当 DB `config` 含非法值(如 `temperature=3`)时抛 `ValueError`。
|
||
|
||
**Step 2: 运行测试确认失败**
|
||
|
||
Run: `uv run pytest backend/tests/unit/core/agent/test_run_resume_service.py -q`
|
||
Expected: 新增断言失败(返回值结构/异常行为不匹配)。
|
||
|
||
**Step 3: 最小实现(GREEN)**
|
||
|
||
在 `run_service.py`:
|
||
1. 查询 `SystemAgents.config`。
|
||
2. 用 `SystemAgentLLMConfig.model_validate(config or {})` 校验。
|
||
3. 将 `_load_agent_model_selection()` 改为返回三元组。
|
||
4. 在 `run()` 中把 `llm_config` 传递到 `create_runtime(...)`。
|
||
|
||
**Step 4: 运行测试确认通过**
|
||
|
||
Run: `uv run pytest backend/tests/unit/core/agent/test_run_resume_service.py -q`
|
||
Expected: PASS。
|
||
|
||
---
|
||
|
||
### Task 2: Runtime 与 LiteLLM Client 支持可选参数透传
|
||
|
||
**Files:**
|
||
- Modify: `backend/src/core/agent/infrastructure/crewai/factory.py`
|
||
- Modify: `backend/src/core/agent/infrastructure/crewai/runtime.py`
|
||
- Modify: `backend/src/core/agent/infrastructure/litellm/client.py`
|
||
- Test: `backend/tests/unit/core/agent/test_crewai_runtime.py`
|
||
|
||
**Step 1: 写失败测试(RED)**
|
||
|
||
在 `test_crewai_runtime.py` 增加用例:
|
||
1. 传入 `temperature/max_tokens` 时,`run_completion` 收到对应参数。
|
||
2. 参数为 `None` 时,不应被透传到 LiteLLM。
|
||
|
||
必要时新增 `backend/tests/unit/core/agent/test_litellm_client.py`,单测 `run_completion` 的 kwargs 组装逻辑。
|
||
|
||
**Step 2: 运行测试确认失败**
|
||
|
||
Run: `uv run pytest backend/tests/unit/core/agent/test_crewai_runtime.py -q`
|
||
Expected: 新增断言失败(参数未透传或未过滤 `None`)。
|
||
|
||
**Step 3: 最小实现(GREEN)**
|
||
|
||
1. `create_runtime()` 增加 `llm_config` 参数并传给 `CrewAIRuntime`。
|
||
2. `CrewAIRuntime` 保存 `llm_config`,执行时调用:
|
||
- `run_completion(..., temperature=llm_config.temperature, max_tokens=llm_config.max_tokens)`
|
||
3. `run_completion()` 改为支持可选 `temperature/max_tokens`,内部仅在非 `None` 时加入 kwargs 再调用 `completion()`。
|
||
|
||
**Step 4: 运行测试确认通过**
|
||
|
||
Run: `uv run pytest backend/tests/unit/core/agent/test_crewai_runtime.py -q`
|
||
Expected: PASS。
|
||
|
||
---
|
||
|
||
### Task 3: 初始化数据补齐与回归验证
|
||
|
||
**Files:**
|
||
- Modify: `backend/src/core/config/static/database/system_agents.yaml`
|
||
- Modify: `backend/src/core/config/initial/init_data.py`(如需补充类型兜底)
|
||
- Test: `backend/tests/unit/core/agent/test_run_resume_service.py`
|
||
|
||
**Step 1: 写失败测试(RED)**
|
||
|
||
补充断言:YAML 读取后 `config` 可为空或包含 `max_tokens: null`,初始化逻辑不会报错,且生成结构符合 `SystemAgentLLMConfig`。
|
||
|
||
**Step 2: 运行测试确认失败**
|
||
|
||
Run: `uv run pytest backend/tests/unit/core/agent/test_run_resume_service.py -q`
|
||
Expected: 新增断言失败。
|
||
|
||
**Step 3: 最小实现(GREEN)**
|
||
|
||
1. 在 `system_agents.yaml` 为各 agent 配置显式补充 `max_tokens: null`。
|
||
2. `init_data.py` 保持 `config: SystemAgentLLMConfig | None = None`,写库时统一序列化为 dict。
|
||
|
||
**Step 4: 运行测试确认通过**
|
||
|
||
Run: `uv run pytest backend/tests/unit/core/agent/test_run_resume_service.py -q`
|
||
Expected: PASS。
|
||
|
||
---
|
||
|
||
## 最终验证
|
||
|
||
1. `uv run pytest backend/tests/unit/core/agent/test_run_resume_service.py backend/tests/unit/core/agent/test_crewai_runtime.py -q`
|
||
2. `uv run pytest backend/tests/integration/core/agent/test_queue_run_resume.py -q`
|
||
3. `uv run ruff check backend/src backend/tests`
|
||
4. `uv run basedpyright`
|
||
|
||
预期:全部通过;若集成测试依赖本地 DB 状态导致跳过/失败,需记录原因并给出手工验证步骤。
|
||
|
||
## 完成标准
|
||
|
||
- `RunService` 从 DB 读取并校验 `config`。
|
||
- runtime 到 LiteLLM 链路支持 `temperature/max_tokens` 可选透传。
|
||
- `None` 不透传。
|
||
- 单测与相关集成测试通过,并给出命令级证据。
|