ai-robot-core/ai-service-admin/src/views/rag-lab/index.vue

165 lines
4.7 KiB
Vue
Raw Normal View History

<template>
<div class="rag-lab-container">
<el-row :gutter="20">
<!-- 左侧调试输入 [AC-ASA-05] -->
<el-col :span="10">
<el-card header="调试输入">
<el-form label-position="top">
<el-form-item label="查询 Query">
<el-input
v-model="queryParams.query"
type="textarea"
:rows="4"
placeholder="输入测试问题..."
/>
</el-form-item>
<el-form-item label="知识库范围">
<el-select
v-model="queryParams.kbIds"
multiple
placeholder="请选择知识库"
style="width: 100%"
>
<el-option label="默认知识库" value="default" />
</el-select>
</el-form-item>
<el-form-item label="参数配置">
<div class="param-item">
<span class="label">Top-K</span>
<el-input-number v-model="queryParams.params.topK" :min="1" :max="10" />
</div>
<div class="param-item">
<span class="label">Score Threshold</span>
<el-slider
v-model="queryParams.params.threshold"
:min="0"
:max="1"
:step="0.1"
show-input
/>
</div>
</el-form-item>
<el-button type="primary" block @click="handleRun" :loading="loading">
运行实验
</el-button>
</el-form>
</el-card>
</el-col>
<!-- 右侧实验结果 [AC-ASA-05] -->
<el-col :span="14">
<el-tabs v-model="activeTab" type="border-card">
<el-tab-pane label="召回片段" name="retrieval">
<div v-if="results.retrievalResults.length === 0" class="placeholder-text">
暂无实验数据
</div>
<div v-else class="result-list">
<el-card
v-for="(item, index) in results.retrievalResults"
:key="index"
class="result-card"
shadow="never"
>
<div class="result-header">
<el-tag size="small">Score: {{ item.score.toFixed(4) }}</el-tag>
<span class="source">来源: {{ item.source }}</span>
</div>
<div class="result-content">{{ item.content }}</div>
</el-card>
</div>
</el-tab-pane>
<el-tab-pane label="最终 Prompt" name="prompt">
<div v-if="!results.finalPrompt" class="placeholder-text">
等待实验运行...
</div>
<div v-else class="prompt-view">
<pre><code>{{ results.finalPrompt }}</code></pre>
</div>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { runRagExperiment } from '@/api/rag'
const loading = ref(false)
const activeTab = ref('retrieval')
const queryParams = reactive({
query: '',
kbIds: [],
params: {
topK: 3,
threshold: 0.5
}
})
const results = reactive({
retrievalResults: [],
finalPrompt: ''
})
/** 运行实验 [AC-ASA-05] */
const handleRun = async () => {
if (!queryParams.query.trim()) {
ElMessage.warning('请输入查询 Query')
return
}
loading.value = true
try {
const res: any = await runRagExperiment(queryParams)
results.retrievalResults = res.retrievalResults || []
results.finalPrompt = res.finalPrompt || ''
activeTab.value = 'retrieval'
ElMessage.success('实验运行成功')
} catch (err) {
console.error(err)
} finally {
loading.value = false
}
}
</script>
<style scoped>
.rag-lab-container { padding: 20px; }
.param-item {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.param-item .label {
width: 120px;
font-size: 14px;
}
.placeholder-text { color: #909399; text-align: center; padding: 50px 0; }
.result-list { height: 600px; overflow-y: auto; }
.result-card { margin-bottom: 15px; }
.result-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.source { font-size: 12px; color: #909399; }
.result-content { font-size: 14px; line-height: 1.6; color: #303133; }
.prompt-view {
background-color: #f5f7fa;
padding: 15px;
border-radius: 4px;
max-height: 600px;
overflow-y: auto;
}
.prompt-view pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
font-family: monospace;
}
</style>