Describe the bug
问题描述
POST /api/strategies/generate 每次调用都会失败,报错:
strategyV2.generationInvalid
-> strategyV2.initializeFailed: DiscoveryContext.set_metadata() takes 1 positional argument but 3 were given
系统提示词让大模型使用 context.set_metadata(...),但没有给出精确的函数签名;而运行时实现只接受关键字参数(**values)。大模型(我用 DeepSeek deepseek-v4-flash 稳定复现)总是生成位置参数写法 set_metadata("key", "value"),在编译策略时直接抛 TypeError。内置的"自动修复"环节也无法修复,因为报错信息本身没有传达"必须用关键字参数"这个契约。
Steps to reproduce
复现步骤
- 用预构建镜像部署(
ghcr.io/openbyteinc/quantdinger-backend:latest,2026-08-14 构建)
- 配置任意 LLM 提供商(已验证 DeepSeek,模型
deepseek-v4-flash)
- 登录后调用接口,随便给个提示词:
curl -s -X POST http://127.0.0.1:5000/api/strategies/generate \
-H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
-d '{"prompt":"写一个 BTC/USDT 1小时周期的简单双均线交叉策略。"}'
- 返回:
{"code":0,"msg":"strategyV2.generationInvalid","data":{"error":"strategyV2.initializeFailed:DiscoveryContext.set_metadata() takes 1 positional argument but 3 were given"}}
后端日志确认:首次编译失败(3 were given)→ 自动修复 → 修复后的代码再次失败(2 were given):
repairing invalid generated strategy: strategyV2.initializeFailed:DiscoveryContext.set_metadata() takes 1 positional argument but 3 were given
strategy generation failed: strategyV2.initializeFailed:DiscoveryContext.set_metadata() takes 1 positional argument but 2 were given
Expected behavior
预期行为
策略生成应该成功。要么:
- 运行时接受位置参数写法(
set_metadata("direction", "long")),或者
- 提示词给出精确的关键字签名,让模型第一次就能生成正确代码
Deployment method
Docker Compose
Relevant logs
## 根因分析
两个文件之间存在**契约不一致**:
**1. 提示词文档 —— `backend_api_python/app/services/ai_generation_contracts.py:35`** 只写了:
- Use `context.set_metadata(...)` in `initialize` for stable descriptive metadata such as direction mode and strategy family.
没有给出签名,也没有说明位置参数会被拒绝。而同一份提示词里其他 API 都标注了 "signatures are exact"(精确签名,如 `order(symbol, amount)`、`get_history(count, ...)`),所以模型很自然地推断成位置参数调用。
**2. 运行时实现 —— `backend_api_python/app/services/strategy_v2/contract.py:153`**:
def set_metadata(self, **values: Any) -> None:
self.metadata.update(values)
只接受关键字参数。调用 `set_metadata("direction", "long")` 会抛 `TypeError: set_metadata() takes 1 positional argument but 2 were given`。
自动修复环节(`_compile_or_repair_generated_strategy`,在 `backend_api_python/app/routes/strategy.py`)把原始报错文本回传给模型,但因为提示词里始终缺少正确的签名,模型再次生成同样的错误写法。
## 建议修复(二选一,或两个都做)
1. **让运行时兼容位置参数**(改动小、风险低,不依赖模型行为):
def set_metadata(self, *args: Any, **values: Any) -> None:
if len(args) >= 2:
values.update({args[i]: args[i + 1] for i in range(0, len(args) - 1, 2)})
elif args:
values.setdefault("value", args[0])
self.metadata.update(values)
2. **在提示词里写明精确签名**(帮助所有模型第一次就生成正确代码,减少修复往返):
- Use `context.set_metadata(**values)` in `initialize` for stable descriptive metadata such as direction mode and strategy family. The signature is keyword-only — always pass keyword arguments, e.g. `context.set_metadata(direction="long", family="moving_average")`. Positional arguments are rejected and fail compilation; never write `context.set_metadata("key", "value")`.
## 环境
- 部署方式:方案 A,GHCR 预构建镜像 + Docker Compose(10 个容器全部 healthy)
- 后端镜像:`ghcr.io/openbyteinc/quantdinger-backend:latest`(2026-08-14 构建,与当前 `main` 分支内容一致)
- LLM 提供商:DeepSeek(`deepseek-v4-flash`),API base `https://api.deepseek.com/v1`
- 已确认当前 `main` 分支仍包含 `set_metadata(self, **values)` 和模糊的提示词 —— 上游尚未修复
Describe the bug
问题描述
POST /api/strategies/generate每次调用都会失败,报错:系统提示词让大模型使用
context.set_metadata(...),但没有给出精确的函数签名;而运行时实现只接受关键字参数(**values)。大模型(我用 DeepSeekdeepseek-v4-flash稳定复现)总是生成位置参数写法set_metadata("key", "value"),在编译策略时直接抛TypeError。内置的"自动修复"环节也无法修复,因为报错信息本身没有传达"必须用关键字参数"这个契约。Steps to reproduce
复现步骤
ghcr.io/openbyteinc/quantdinger-backend:latest,2026-08-14 构建)deepseek-v4-flash){"code":0,"msg":"strategyV2.generationInvalid","data":{"error":"strategyV2.initializeFailed:DiscoveryContext.set_metadata() takes 1 positional argument but 3 were given"}}后端日志确认:首次编译失败(
3 were given)→ 自动修复 → 修复后的代码再次失败(2 were given):Expected behavior
预期行为
策略生成应该成功。要么:
set_metadata("direction", "long")),或者Deployment method
Docker Compose
Relevant logs