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:
@@ -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():
|
||||
"""微信小程序生成提示词接口"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user