feat(ASA-P5,P6): 实现嵌入管理与LLM配置API服务层 [AC-ASA-08~AC-ASA-15]

This commit is contained in:
MerCry 2026-02-25 01:34:20 +08:00
parent fc53fdc6ac
commit 935dcd1611
5 changed files with 221 additions and 7 deletions

View File

@ -0,0 +1,50 @@
import request from '@/utils/request'
import type {
LLMProviderInfo,
LLMConfig,
LLMConfigUpdate,
LLMTestResult,
LLMTestRequest,
LLMProvidersResponse,
LLMConfigUpdateResponse
} from '@/types/llm'
export function getLLMProviders(): Promise<LLMProvidersResponse> {
return request({
url: '/llm/providers',
method: 'get'
})
}
export function getLLMConfig(): Promise<LLMConfig> {
return request({
url: '/llm/config',
method: 'get'
})
}
export function saveLLMConfig(data: LLMConfigUpdate): Promise<LLMConfigUpdateResponse> {
return request({
url: '/llm/config',
method: 'put',
data
})
}
export function testLLM(data: LLMTestRequest): Promise<LLMTestResult> {
return request({
url: '/llm/test',
method: 'post',
data
})
}
export type {
LLMProviderInfo,
LLMConfig,
LLMConfigUpdate,
LLMTestResult,
LLMTestRequest,
LLMProvidersResponse,
LLMConfigUpdateResponse
}

View File

@ -1,9 +1,131 @@
import request from '@/utils/request' import request from '@/utils/request'
export function runRagExperiment(data: { query: string, kbIds?: string[], params?: any }) { export interface AIResponse {
content: string
prompt_tokens?: number
completion_tokens?: number
total_tokens?: number
latency_ms?: number
model?: string
}
export interface RetrievalResult {
content: string
score: number
source: string
metadata?: Record<string, any>
}
export interface RagExperimentRequest {
query: string
kb_ids?: string[]
top_k?: number
score_threshold?: number
llm_provider?: string
generate_response?: boolean
}
export interface RagExperimentResult {
query: string
retrieval_results?: RetrievalResult[]
final_prompt?: string
ai_response?: AIResponse
total_latency_ms?: number
}
export function runRagExperiment(data: RagExperimentRequest): Promise<RagExperimentResult> {
return request({ return request({
url: '/admin/rag/experiments/run', url: '/admin/rag/experiments/run',
method: 'post', method: 'post',
data data
}) })
} }
export function runRagExperimentStream(
data: RagExperimentRequest,
onMessage: (event: MessageEvent) => void,
onError?: (error: Event) => void,
onComplete?: () => void
): EventSource {
const baseUrl = import.meta.env.VITE_APP_BASE_API || '/api'
const url = `${baseUrl}/admin/rag/experiments/stream`
const eventSource = new EventSource(url, {
withCredentials: true
})
eventSource.onmessage = onMessage
eventSource.onerror = (error) => {
eventSource.close()
onError?.(error)
}
return eventSource
}
export function createSSEConnection(
url: string,
body: RagExperimentRequest,
onMessage: (data: string) => void,
onError?: (error: Error) => void,
onComplete?: () => void
): () => void {
const baseUrl = import.meta.env.VITE_APP_BASE_API || '/api'
const fullUrl = `${baseUrl}${url}`
const controller = new AbortController()
fetch(fullUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'text/event-stream',
},
body: JSON.stringify(body),
signal: controller.signal
})
.then(async (response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const reader = response.body?.getReader()
if (!reader) {
throw new Error('No response body')
}
const decoder = new TextDecoder()
let buffer = ''
while (true) {
const { done, value } = await reader.read()
if (done) {
onComplete?.()
break
}
buffer += decoder.decode(value, { stream: true })
const lines = buffer.split('\n')
buffer = lines.pop() || ''
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6)
if (data === '[DONE]') {
onComplete?.()
return
}
onMessage(data)
}
}
}
})
.catch((error) => {
if (error.name !== 'AbortError') {
onError?.(error)
}
})
return () => controller.abort()
}

View File

@ -0,0 +1,42 @@
export interface LLMProviderInfo {
name: string
display_name: string
description?: string
config_schema: Record<string, any>
}
export interface LLMConfig {
provider: string
config: Record<string, any>
updated_at?: string
}
export interface LLMConfigUpdate {
provider: string
config?: Record<string, any>
}
export interface LLMTestResult {
success: boolean
response?: string
latency_ms?: number
prompt_tokens?: number
completion_tokens?: number
total_tokens?: number
message?: string
error?: string
}
export interface LLMTestRequest {
test_prompt?: string
config?: LLMConfigUpdate
}
export interface LLMProvidersResponse {
providers: LLMProviderInfo[]
}
export interface LLMConfigUpdateResponse {
success: boolean
message: string
}

View File

@ -50,7 +50,7 @@ version: "0.3.0"
- [x] (P5-01~P5-06) 后端管理接口实现 - [x] (P5-01~P5-06) 后端管理接口实现
#### Phase 6: 嵌入模型管理(待处理) #### Phase 6: 嵌入模型管理(待处理)
- [ ] (P5-01) API 服务层与类型定义 [AC-ASA-08, AC-ASA-09] - [x] (P5-01) API 服务层与类型定义 [AC-ASA-08, AC-ASA-09]
- [ ] (P5-02) 提供者选择组件 [AC-ASA-09] - [ ] (P5-02) 提供者选择组件 [AC-ASA-09]
- [ ] (P5-03) 动态配置表单 [AC-ASA-09, AC-ASA-10] - [ ] (P5-03) 动态配置表单 [AC-ASA-09, AC-ASA-10]
- [ ] (P5-04) 测试连接组件 [AC-ASA-11, AC-ASA-12] - [ ] (P5-04) 测试连接组件 [AC-ASA-11, AC-ASA-12]
@ -60,7 +60,7 @@ version: "0.3.0"
- [ ] (P5-08) 组件整合与测试 [AC-ASA-08~AC-ASA-13] - [ ] (P5-08) 组件整合与测试 [AC-ASA-08~AC-ASA-13]
#### Phase 7: LLM 配置与 RAG 调试输出(当前) #### Phase 7: LLM 配置与 RAG 调试输出(当前)
- [ ] (P6-01) LLM API 服务层与类型定义:创建 src/api/llm.ts 和 src/types/llm.ts [AC-ASA-14, AC-ASA-15] - [x] (P6-01) LLM API 服务层与类型定义:创建 src/api/llm.ts 和 src/types/llm.ts [AC-ASA-14, AC-ASA-15]
- [ ] (P6-02) LLM 提供者选择组件:创建 LLMProviderSelect.vue [AC-ASA-15] - [ ] (P6-02) LLM 提供者选择组件:创建 LLMProviderSelect.vue [AC-ASA-15]
- [ ] (P6-03) LLM 动态配置表单:创建 LLMConfigForm.vue [AC-ASA-15, AC-ASA-16] - [ ] (P6-03) LLM 动态配置表单:创建 LLMConfigForm.vue [AC-ASA-15, AC-ASA-16]
- [ ] (P6-04) LLM 测试连接组件:创建 LLMTestPanel.vue [AC-ASA-17, AC-ASA-18] - [ ] (P6-04) LLM 测试连接组件:创建 LLMTestPanel.vue [AC-ASA-17, AC-ASA-18]

View File

@ -123,7 +123,7 @@ principles:
> 页面导向:嵌入模型配置页面,支持提供者切换、参数配置、连接测试。 > 页面导向:嵌入模型配置页面,支持提供者切换、参数配置、连接测试。
- [ ] (P5-01) API 服务层与类型定义:创建 src/api/embedding.ts 和 src/types/embedding.ts - [x] (P5-01) API 服务层与类型定义:创建 src/api/embedding.ts 和 src/types/embedding.ts
- AC: [AC-ASA-08, AC-ASA-09] - AC: [AC-ASA-08, AC-ASA-09]
- [ ] (P5-02) 提供者选择组件:实现 `EmbeddingProviderSelect` 下拉组件,对接 `/admin/embedding/providers` - [ ] (P5-02) 提供者选择组件:实现 `EmbeddingProviderSelect` 下拉组件,对接 `/admin/embedding/providers`
@ -153,7 +153,7 @@ principles:
| 任务 | 描述 | 状态 | | 任务 | 描述 | 状态 |
|------|------|------| |------|------|------|
| P5-01 | API 服务层与类型定义 | ⏳ 待处理 | | P5-01 | API 服务层与类型定义 | ✅ 已完成 |
| P5-02 | 提供者选择组件 | ⏳ 待处理 | | P5-02 | 提供者选择组件 | ⏳ 待处理 |
| P5-03 | 动态配置表单 | ⏳ 待处理 | | P5-03 | 动态配置表单 | ⏳ 待处理 |
| P5-04 | 测试连接组件 | ⏳ 待处理 | | P5-04 | 测试连接组件 | ⏳ 待处理 |
@ -170,7 +170,7 @@ principles:
### 6.1 LLM 模型配置 ### 6.1 LLM 模型配置
- [ ] (P6-01) LLM API 服务层与类型定义:创建 src/api/llm.ts 和 src/types/llm.ts - [x] (P6-01) LLM API 服务层与类型定义:创建 src/api/llm.ts 和 src/types/llm.ts
- AC: [AC-ASA-14, AC-ASA-15] - AC: [AC-ASA-14, AC-ASA-15]
- [ ] (P6-02) LLM 提供者选择组件:实现 `LLMProviderSelect` 下拉组件 - [ ] (P6-02) LLM 提供者选择组件:实现 `LLMProviderSelect` 下拉组件
@ -208,7 +208,7 @@ principles:
| 任务 | 描述 | 状态 | | 任务 | 描述 | 状态 |
|------|------|------| |------|------|------|
| P6-01 | LLM API 服务层与类型定义 | ⏳ 待处理 | | P6-01 | LLM API 服务层与类型定义 | ✅ 已完成 |
| P6-02 | LLM 提供者选择组件 | ⏳ 待处理 | | P6-02 | LLM 提供者选择组件 | ⏳ 待处理 |
| P6-03 | LLM 动态配置表单 | ⏳ 待处理 | | P6-03 | LLM 动态配置表单 | ⏳ 待处理 |
| P6-04 | LLM 测试连接组件 | ⏳ 待处理 | | P6-04 | LLM 测试连接组件 | ⏳ 待处理 |