配置BGM助手中等推理强度
Project CI / Repository checks (pull_request) Failing after 7s
Project CI / Backend tests (pull_request) Failing after 8s
Project CI / Frontend tests (pull_request) Successful in 3m42s
Project CI / Native shell tests (pull_request) Successful in 14m59s

将BGM补全与简化请求统一设置reasoning_effort为medium
补充请求对象和HTTP载荷断言并同步权威设计
This commit is contained in:
2026-08-06 07:22:37 +00:00
parent a786fa7562
commit c3e8be719d
2 changed files with 11 additions and 3 deletions
@@ -124,7 +124,7 @@
### AI 补全
- 点击 AI 补全时先按统一规则规范化输入框首尾空白并同步写回;至少 2 个有效字符且总字符数不超过 200 时,前端才把这份可见最终 Prompt 传给登录态内部 BFF。
- Prompt 助手当前使用专用请求模型 `gpt-5.6-luna`;画布 Agent 本身仍使用现有编辑器 Agent LLM 配置中的 `gpt-5.4-mini`。两者复用现有 `LlmClient`,不建立新的平台 LLM 能力。
- Prompt 助手当前使用专用请求模型 `gpt-5.6-luna`,请求级 `reasoning_effort` 固定为 `medium`;画布 Agent 本身仍使用现有编辑器 Agent LLM 配置中的 `gpt-5.4-mini`。两者复用现有 `LlmClient`,不建立新的平台 LLM 能力。
- 服务端模板必须要求:保留用户明确的主题、场景、风格、情绪、乐器、能量、韵律、时长、循环和避免项;按场景选择性补足场景、氛围、能量、韵律、乐器、旋律、声音设计、循环和避免项,不为凑全方向堆砌形容词。
- 用户描述已足够完整时,只补充一至两个与主题匹配的具体声音细节。发现冲突时,优先级为“明确避免项和限制 > 明确玩法用途与场景 > 风格、情绪、能量与韵律 > AI 补充细节”。
- 内部 envelope 的 `prompt` 字段只允许包含一条可直接写回输入框的中文 BGM Prompt;候选文本本身不得包含解释、标题、Markdown、JSON、代码块、具体艺人或歌曲模仿要求。
@@ -327,7 +327,7 @@ POST /api/editor/audios/background-music/prompts/simplifications
-`api-server` 增加登录态内部 BGM Prompt 助手 BFF
- `POST /api/editor/audios/background-music/prompts/completions`
- `POST /api/editor/audios/background-music/prompts/simplifications`
- Prompt 助手 BFF 在入站和 LLM 候选出站边界执行 BGM canonicalization;服务端字符数、0 / 1 / 2 个有效字符规则、正式生成 200 字限制和简化 201–2000 字资格都基于 canonical Prompt。助手使用现有编辑器专用 LLM client、`gpt-5.6-luna` 请求模型和显式 OpenAI Chat 协议;画布 Agent 其它调用仍使用 `gpt-5.4-mini`。补全固定执行一个业务语义轮,简化按 `180 -> 170` 最多两个业务语义轮,并按“一键简化”章节冻结 `originalPrompt`、派生每轮 `currentPrompt``LlmClient` 在单轮内部执行的 transport retry 不计入业务语义轮数,简化第一轮 transport、超时或上游失败不进入 170 字轮。服务端负责模板组装、在正文解析或候选提取前检查 `finish_reason`、canonical 字符校验、对完整 `response.text` 中单个 JSON object 的 `serde_json` 全量解析、补全与简化共用的内部 envelope 校验、执行格式 / 完整性 / 残句三个布尔判断和现有 API 错误 envelope;不自行猜测三个语义判断,也不向客户端返回未通过候选。助手不发送 function tools,不接受 tool call,不从代码块或解释中截取 JSON,不自动修复,也不做运行时双协议 fallback。
- Prompt 助手 BFF 在入站和 LLM 候选出站边界执行 BGM canonicalization;服务端字符数、0 / 1 / 2 个有效字符规则、正式生成 200 字限制和简化 201–2000 字资格都基于 canonical Prompt。助手使用现有编辑器专用 LLM client、`gpt-5.6-luna` 请求模型、固定 `reasoning_effort=medium` 和显式 OpenAI Chat 协议;画布 Agent 其它调用仍使用 `gpt-5.4-mini`。补全固定执行一个业务语义轮,简化按 `180 -> 170` 最多两个业务语义轮,并按“一键简化”章节冻结 `originalPrompt`、派生每轮 `currentPrompt``LlmClient` 在单轮内部执行的 transport retry 不计入业务语义轮数,简化第一轮 transport、超时或上游失败不进入 170 字轮。服务端负责模板组装、在正文解析或候选提取前检查 `finish_reason`、canonical 字符校验、对完整 `response.text` 中单个 JSON object 的 `serde_json` 全量解析、补全与简化共用的内部 envelope 校验、执行格式 / 完整性 / 残句三个布尔判断和现有 API 错误 envelope;不自行猜测三个语义判断,也不向客户端返回未通过候选。助手不发送 function tools,不接受 tool call,不从代码块或解释中截取 JSON,不自动修复,也不做运行时双协议 fallback。
- `finish_reason` 检查复用并公开 `platform-llm` 现有 API-kind-aware 未完成原因 predicate;不得在 `LlmClient` 全局拒绝普通纯文本响应,也不得改变其它调用方既有的长文本降级行为。
- 两个助手路由使用各自的 `32 KiB` body limit,并在 `tracking.rs` 中注册上述 User-scope 成功事件;不增加助手专属限流器、本地额度计数或功能级 `429`
- Prompt 助手继续复用 `LlmClient` 现有失败原文日志行为。本需求不增加请求级日志开关、脱敏、metadata-only 模式或相关上线门禁。
@@ -4,7 +4,9 @@ use axum::{
http::StatusCode,
response::Response,
};
use platform_llm::{LlmClient, LlmMessage, LlmRunRequest, LlmRunResponse};
use platform_llm::{
LlmClient, LlmMessage, LlmResponseReasoningEffort, LlmRunRequest, LlmRunResponse,
};
use serde::Deserialize;
use serde_json::{Value, json};
use shared_contracts::assets::{
@@ -213,6 +215,7 @@ fn build_background_music_prompt_llm_request(
])
.with_model(BACKGROUND_MUSIC_PROMPT_ASSIST_MODEL)
.with_openai_chat()
.with_response_reasoning_effort(LlmResponseReasoningEffort::Medium)
.with_max_output_tokens(BACKGROUND_MUSIC_PROMPT_ASSIST_MAX_OUTPUT_TOKENS)
}
@@ -469,6 +472,10 @@ mod tests {
assert_eq!(request.model.as_deref(), Some("gpt-5.6-luna"));
assert_eq!(request.api_kind, LlmApiKind::OpenAiChat);
assert_eq!(
request.response_reasoning_effort,
Some(LlmResponseReasoningEffort::Medium)
);
assert_eq!(
request.max_output_tokens,
Some(BACKGROUND_MUSIC_PROMPT_ASSIST_MAX_OUTPUT_TOKENS)
@@ -880,6 +887,7 @@ mod tests {
requests[0].body["model"],
BACKGROUND_MUSIC_PROMPT_ASSIST_MODEL
);
assert_eq!(requests[0].body["reasoning_effort"], "medium");
assert!(requests[0].body.get("tools").is_none());
assert!(requests[0].body.get("tool_choice").is_none());
let input = user_message_json(&requests[0].body);