From eb5056b5f21be6a379eb7fd9957f549a7851bc49 Mon Sep 17 00:00:00 2001 From: renjianbo <18691577328@163.com> Date: Sun, 3 May 2026 09:46:12 +0800 Subject: [PATCH] feat(S2): max_tokens dynamic from template, remove hardcoded 500 - PromptTemplate model: add max_tokens (default 500) and example_input fields - generate_with_llm: read max_tokens from template, accept override param - api_prompt_generate: accept optional max_tokens with 100-4096 clamp - Vue: add advanced options toggle with max_tokens input - Vue: auto-populate max_tokens from selected template Co-Authored-By: Claude Opus 4.6 --- src/flask_prompt_master/models/models.py | 2 ++ src/flask_prompt_master/routes/routes.py | 31 +++++++++++++++++---- vue-app/src/api/modules/prompt.ts | 2 +- vue-app/src/api/types/template.ts | 1 + vue-app/src/views/GenerateView.vue | 35 ++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/flask_prompt_master/models/models.py b/src/flask_prompt_master/models/models.py index 3427eea..ded7233 100644 --- a/src/flask_prompt_master/models/models.py +++ b/src/flask_prompt_master/models/models.py @@ -81,6 +81,8 @@ class PromptTemplate(db.Model): sub_category = db.Column(db.String(50)) system_prompt = db.Column(db.Text, nullable=False) is_default = db.Column(db.Boolean, default=False) + max_tokens = db.Column(db.Integer, default=500) + example_input = db.Column(db.Text) created_at = db.Column(db.DateTime, default=datetime.utcnow) class MealPlan(db.Model): diff --git a/src/flask_prompt_master/routes/routes.py b/src/flask_prompt_master/routes/routes.py index 50b6fe7..985509d 100644 --- a/src/flask_prompt_master/routes/routes.py +++ b/src/flask_prompt_master/routes/routes.py @@ -49,20 +49,28 @@ def get_system_prompt(template_id=None): 请直接返回优化后的提示词,不要添加任何解释或其他内容。""" -def generate_with_llm(input_text, template_id=None, max_retries=3): +def generate_with_llm(input_text, template_id=None, max_retries=3, max_tokens=None): """调用大模型API生成提示词,带重试机制""" import time - + system_prompt = get_system_prompt(template_id) start_time = time.time() # 记录开始时间 - + + # 确定 max_tokens: 参数传入 > 模板配置 > 默认 500 + _max_tokens = max_tokens or 500 + if not max_tokens and template_id: + template = PromptTemplate.query.get(template_id) + if template and template.max_tokens: + _max_tokens = template.max_tokens + # 记录参数到日志 current_app.logger.info("=== API 调用参数 ===") current_app.logger.info(f"模板ID: {template_id}") current_app.logger.info(f"输入文本: {input_text}") current_app.logger.info(f"系统提示: {system_prompt}") + current_app.logger.info(f"max_tokens: {_max_tokens}") current_app.logger.info("==================") - + for attempt in range(max_retries): try: response = client.chat.completions.create( @@ -72,7 +80,7 @@ def generate_with_llm(input_text, template_id=None, max_retries=3): {"role": "user", "content": input_text} ], temperature=0.7, - max_tokens=500, + max_tokens=_max_tokens, timeout=60 # 设置60秒超时 ) @@ -342,6 +350,7 @@ def get_templates_by_category(category): 'profession': template.profession, 'sub_category': template.sub_category, 'system_prompt': template.system_prompt, + 'max_tokens': template.max_tokens or 500, 'sample_input': build_sample_input_text(template), } template_list.append(template_dict) @@ -401,8 +410,18 @@ def api_prompt_generate(): if len(input_text) > 1000: return jsonify({'success': False, 'message': '需求描述请勿超过 1000 字'}), 400 + # 可选 max_tokens 覆盖 + _mt = data.get('max_tokens') + _max_tokens = None + if _mt is not None and _mt != '': + try: + _max_tokens = int(_mt) + _max_tokens = max(100, min(4096, _max_tokens)) + except (TypeError, ValueError): + pass + try: - generated_text = generate_with_llm(input_text, template_id) + generated_text = generate_with_llm(input_text, template_id, max_tokens=_max_tokens) if not generated_text or ( isinstance(generated_text, str) and generated_text.startswith('提示词生成失败') ): diff --git a/vue-app/src/api/modules/prompt.ts b/vue-app/src/api/modules/prompt.ts index cf135eb..51867f6 100644 --- a/vue-app/src/api/modules/prompt.ts +++ b/vue-app/src/api/modules/prompt.ts @@ -14,6 +14,6 @@ export function fetchTemplatesByCategory(category: string) { return client.get(path).then((r) => r.data) } -export function generatePrompt(body: { input_text: string; template_id: number | null }) { +export function generatePrompt(body: { input_text: string; template_id: number | null; max_tokens?: number }) { return client.post('/api/prompt/generate', body).then((r) => r.data) } diff --git a/vue-app/src/api/types/template.ts b/vue-app/src/api/types/template.ts index 3ebfa5e..59a0306 100644 --- a/vue-app/src/api/types/template.ts +++ b/vue-app/src/api/types/template.ts @@ -7,6 +7,7 @@ export interface PromptTemplateItem { profession: string | null sub_category: string | null system_prompt: string + max_tokens: number sample_input: string } diff --git a/vue-app/src/views/GenerateView.vue b/vue-app/src/views/GenerateView.vue index 8c4abe2..66e0d41 100644 --- a/vue-app/src/views/GenerateView.vue +++ b/vue-app/src/views/GenerateView.vue @@ -26,6 +26,8 @@ const selectedTemplateId = ref(undefined) const inputText = ref('') const autoFillSample = ref(true) +const showAdvanced = ref(false) +const maxTokensOverride = ref(undefined) const result = ref<{ id: number; input_text: string; generated_text: string } | null>(null) @@ -100,9 +102,11 @@ watch(filteredTemplates, (list) => { }) watch(selectedTemplateId, (id) => { - if (!autoFillSample.value || id == null) return - const t = templates.value.find((x) => x.id === id) - if (t?.sample_input) inputText.value = t.sample_input + if (id != null) { + const t = templates.value.find((x) => x.id === id) + if (autoFillSample.value && t?.sample_input) inputText.value = t.sample_input + maxTokensOverride.value = t?.max_tokens || undefined + } }) async function loadMeta() { @@ -201,6 +205,7 @@ async function onSubmit() { const res = await generatePrompt({ input_text: text, template_id: selectedTemplateId.value, + max_tokens: maxTokensOverride.value, }) if (!res.success) { ElMessage.error(res.message || '生成失败') @@ -356,9 +361,27 @@ onMounted(async () => { placeholder="请描述目标、背景、约束与期望输出…" />
- - 生成专业提示词 - + + + 生成专业提示词 + + + {{ showAdvanced ? '收起' : '高级选项' }} + + +
+
+ + + 留空由模板决定,范围 100–4096 +