| 1 | # -*- coding: utf-8 -*- |
| 2 | """ |
| 3 | 统一提示词加载器 |
| 4 | 从 prompts/ 目录加载提示词模板文件 |
| 5 | """ |
| 6 | |
| 7 | import os |
| 8 | from typing import Optional |
| 9 | |
| 10 | # 获取 prompts 目录的绝对路径 (loader.py is in backend/prompts/, prompts are in backend/prompts/) |
| 11 | PROMPTS_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 12 | |
| 13 | |
| 14 | def load_prompt(category: str, name: str, lang: str = 'zh') -> str: |
| 15 | """ |
| 16 | 加载提示词文件 |
| 17 | |
| 18 | Args: |
| 19 | category: 提示词分类 (script, character, setting, storyboard, reference, video, logline) |
| 20 | name: 提示词文件名 (不含扩展名) |
| 21 | lang: 语言版本 ('zh' 或 'en') |
| 22 | |
| 23 | Returns: |
| 24 | 提示词内容字符串 |
| 25 | |
| 26 | Example: |
| 27 | prompt = load_prompt('script', 'logline_generate', 'zh') |
| 28 | """ |
| 29 | # 尝试加载语言版本 |
| 30 | file_path = os.path.join(PROMPTS_DIR, category, f"{name}_{lang}.txt") |
| 31 | if os.path.exists(file_path): |
| 32 | with open(file_path, 'r', encoding='utf-8') as f: |
| 33 | return f.read().strip() |
| 34 | |
| 35 | # 回退到带 _zh 的版本 |
| 36 | file_path = os.path.join(PROMPTS_DIR, category, f"{name}_zh.txt") |
| 37 | if os.path.exists(file_path): |
| 38 | with open(file_path, 'r', encoding='utf-8') as f: |
| 39 | return f.read().strip() |
| 40 | |
| 41 | # 回退到不带后缀的通用版本 |
| 42 | file_path = os.path.join(PROMPTS_DIR, category, f"{name}.txt") |
| 43 | if os.path.exists(file_path): |
| 44 | with open(file_path, 'r', encoding='utf-8') as f: |
| 45 | return f.read().strip() |
| 46 | |
| 47 | raise FileNotFoundError(f"Prompt not found: {category}/{name}_{lang}.txt or {category}/{name}.txt") |
| 48 | |
| 49 | |
| 50 | def load_prompt_with_fallback(category: str, name: str, lang: str = 'zh', fallback_lang: str = 'zh') -> str: |
| 51 | """ |
| 52 | 加载提示词,如果指定语言不存在则回退 |
| 53 | |
| 54 | Args: |
| 55 | category: 提示词分类 |
| 56 | name: 提示词文件名 |
| 57 | lang: 首选语言 |
| 58 | fallback_lang: 回退语言 |
| 59 | """ |
| 60 | # 先尝试首选语言 |
| 61 | file_path = os.path.join(PROMPTS_DIR, category, f"{name}_{lang}.txt") |
| 62 | if os.path.exists(file_path): |
| 63 | with open(file_path, 'r', encoding='utf-8') as f: |
| 64 | return f.read().strip() |
| 65 | |
| 66 | # 回退到指定语言 |
| 67 | if fallback_lang != lang: |
| 68 | file_path = os.path.join(PROMPTS_DIR, category, f"{name}_{fallback_lang}.txt") |
| 69 | if os.path.exists(file_path): |
| 70 | with open(file_path, 'r', encoding='utf-8') as f: |
| 71 | return f.read().strip() |
| 72 | |
| 73 | # 最后尝试不带后缀的版本 |
| 74 | file_path = os.path.join(PROMPTS_DIR, category, f"{name}.txt") |
| 75 | if os.path.exists(file_path): |
| 76 | with open(file_path, 'r', encoding='utf-8') as f: |
| 77 | return f.read().strip() |
| 78 | |
| 79 | raise FileNotFoundError(f"Prompt not found: {category}/{name}_{lang}.txt") |
| 80 | |
| 81 | |
| 82 | def format_prompt(template: str, **kwargs) -> str: |
| 83 | """ |
| 84 | 格式化提示词模板 |
| 85 | |
| 86 | Args: |
| 87 | template: 提示词模板字符串 |
| 88 | **kwargs: 格式化参数 |
| 89 | |
| 90 | Returns: |
| 91 | 格式化后的提示词 |
| 92 | |
| 93 | Example: |
| 94 | prompt = format_prompt("Hello {name}, you are {age} years old", name="John", age=30) |
| 95 | """ |
| 96 | return template.format(**kwargs) |
| 97 |