feat(S5): prompt effect verification - test generated prompt against LLM

- Backend: POST /api/prompt/test uses generated prompt as system_prompt
- Frontend: test input card, run test button, output display
- testPrompt API module with typed response

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
renjianbo
2026-05-03 09:56:02 +08:00
parent e2c0b6b87a
commit daf7c1867a
3 changed files with 97 additions and 1 deletions

View File

@@ -529,6 +529,35 @@ def delete_template(template_id):
}), 500
# 添加微信小程序API路由
@main_bp.route('/api/prompt/test', methods=['POST'])
def api_prompt_test():
"""用生成的提示词 + 测试输入实际调用 LLM查看效果"""
data = request.get_json(silent=True) or {}
prompt_text = (data.get('prompt_text') or '').strip()
test_input = (data.get('test_input') or '').strip()
if not prompt_text:
return jsonify({'success': False, 'message': '缺少提示词内容'}), 400
if not test_input:
return jsonify({'success': False, 'message': '请输入测试内容'}), 400
try:
response = client.chat.completions.create(
model='deepseek-chat',
messages=[
{'role': 'system', 'content': prompt_text},
{'role': 'user', 'content': test_input},
],
temperature=0.7,
max_tokens=1000,
timeout=60,
)
test_output = response.choices[0].message.content.strip()
return jsonify({'success': True, 'test_output': test_output})
except Exception as e:
current_app.logger.error(f'prompt_test error: {e}')
return jsonify({'success': False, 'message': f'测试调用失败: {str(e)}'}), 500
@main_bp.route('/api/wx/generate', methods=['POST'])
def wx_generate_prompt():
"""微信小程序生成提示词接口"""

View File

@@ -27,6 +27,16 @@ export interface ContinuePromptResponse {
prompt?: { id: number; input_text: string; generated_text: string }
}
export interface TestPromptResponse {
success: boolean
message?: string
test_output?: string
}
export function testPrompt(body: { prompt_text: string; test_input: string }) {
return client.post<TestPromptResponse>('/api/prompt/test', body).then((r) => r.data)
}
export function continuePrompt(body: {
conversation_id?: number | null
previous_result: string

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { fetchGenerateMeta, fetchTemplatesByCategory, generatePrompt, continuePrompt } from '@/api/modules/prompt'
import { fetchGenerateMeta, fetchTemplatesByCategory, generatePrompt, continuePrompt, testPrompt } from '@/api/modules/prompt'
import { quickAddFavorite } from '@/api/modules/favorite'
import type { PromptTemplateItem } from '@/api/types/template'
import { ArrowDownBold } from '@element-plus/icons-vue'
@@ -37,6 +37,37 @@ const rounds = ref(0)
const refineInstruction = ref('')
const refining = ref(false)
const testing = ref(false)
const testInput = ref('')
const testOutput = ref<string | null>(null)
async function onTestPrompt() {
if (!result.value) return
const input = testInput.value.trim()
if (!input) {
ElMessage.warning('请输入测试内容')
return
}
testing.value = true
testOutput.value = null
try {
const res = await testPrompt({
prompt_text: result.value.generated_text,
test_input: input,
})
if (!res.success) {
ElMessage.error(res.message || '测试失败')
return
}
testOutput.value = res.test_output ?? null
ElMessage.success('测试完成')
} catch {
ElMessage.error('测试请求失败')
} finally {
testing.value = false
}
}
const router = useRouter()
const selectedTemplate = computed(
@@ -493,6 +524,32 @@ onMounted(async () => {
</el-space>
</div>
</el-card>
<el-card v-if="result" shadow="never" class="section test-card">
<template #header>
<span>测试效果</span>
<span class="hint" style="margin-left: 8px; font-weight: normal; font-size: 0.85rem">
将生成的提示词实际执行一次查看 LLM 输出消耗一次 API 调用
</span>
</template>
<el-input
v-model="testInput"
type="textarea"
:rows="3"
maxlength="500"
show-word-limit
placeholder="输入测试内容,如:请写一个 Python 排序函数"
/>
<div class="actions">
<el-button type="warning" plain :loading="testing" @click="onTestPrompt">
运行测试
</el-button>
</div>
<el-card v-if="testOutput" shadow="never" class="test-output">
<template #header>测试输出</template>
<pre class="result-pre">{{ testOutput }}</pre>
</el-card>
</el-card>
</div>
</template>