Files
Genarrative/server-rs/crates/api-server/src/prompt/puzzle/draft.rs
2026-05-05 14:40:41 +08:00

84 lines
3.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// 拼图作品草稿生成动作的提示词主源。
///
/// 拼图结果页草稿本体仍由 SpacetimeDB reducer 按表单/锚点确定性编译;
/// 这里收口 api-server 在生成草稿前后需要写入 reducer 的表单 seed 文本,
/// 以及草稿首图生成时的 prompt 来源选择,避免业务路由直接拼提示词文本。
#[derive(Clone, Copy, Debug, Default)]
pub(crate) struct PuzzleFormSeedPromptParts<'a> {
pub(crate) title: Option<&'a str>,
pub(crate) work_description: Option<&'a str>,
pub(crate) picture_description: Option<&'a str>,
}
/// 将填表式拼图输入编译成 SpacetimeDB 可恢复的表单 seed prompt。
pub(crate) fn build_puzzle_form_seed_prompt(parts: PuzzleFormSeedPromptParts<'_>) -> String {
[
("作品名称", normalize_prompt_part(parts.title)),
("作品描述", normalize_prompt_part(parts.work_description)),
("画面描述", normalize_prompt_part(parts.picture_description)),
]
.into_iter()
.filter_map(|(label, value)| value.map(|value| format!("{label}{value}")))
.collect::<Vec<_>>()
.join("\n")
}
/// 生成作品草稿时,首图 prompt 优先使用玩家当前表单里的画面描述。
pub(crate) fn resolve_puzzle_draft_cover_prompt(
explicit_prompt: Option<&str>,
level_picture_description: &str,
draft_summary: &str,
) -> String {
normalize_prompt_part(explicit_prompt)
.or_else(|| normalize_prompt_part(Some(level_picture_description)))
.or_else(|| normalize_prompt_part(Some(draft_summary)))
.unwrap_or_default()
.to_string()
}
/// 结果页单关重新生成时,优先使用面板当前编辑态 prompt再回退关卡画面描述。
pub(crate) fn resolve_puzzle_level_image_prompt(
explicit_prompt: Option<&str>,
level_picture_description: &str,
) -> String {
normalize_prompt_part(explicit_prompt)
.or_else(|| normalize_prompt_part(Some(level_picture_description)))
.unwrap_or_default()
.to_string()
}
fn normalize_prompt_part(value: Option<&str>) -> Option<&str> {
value.map(str::trim).filter(|value| !value.is_empty())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn form_seed_prompt_keeps_only_user_visible_fields() {
let prompt = build_puzzle_form_seed_prompt(PuzzleFormSeedPromptParts {
title: None,
work_description: None,
picture_description: Some("猫咪在灯牌下回头"),
});
assert_eq!(prompt, "画面描述:猫咪在灯牌下回头");
}
#[test]
fn draft_cover_prompt_prefers_current_picture_description() {
let prompt =
resolve_puzzle_draft_cover_prompt(Some(" 当前表单画面 "), "旧关卡画面", "作品简介");
assert_eq!(prompt, "当前表单画面");
}
#[test]
fn level_image_prompt_falls_back_to_level_description() {
let prompt = resolve_puzzle_level_image_prompt(Some(" "), "关卡画面描述");
assert_eq!(prompt, "关卡画面描述");
}
}