276 lines
8.0 KiB
TypeScript
276 lines
8.0 KiB
TypeScript
import axios from 'axios'
|
|
import { message } from 'antd'
|
|
|
|
const api = axios.create({
|
|
baseURL: '/api',
|
|
timeout: 30000,
|
|
})
|
|
|
|
api.interceptors.response.use(
|
|
(response) => response,
|
|
(error) => {
|
|
const msg = error.response?.data?.detail || error.message || '请求失败'
|
|
message.error(msg)
|
|
return Promise.reject(error)
|
|
},
|
|
)
|
|
|
|
export default api
|
|
|
|
export interface Target {
|
|
id: string
|
|
name: string
|
|
description: string
|
|
platform: string
|
|
channel_type: string
|
|
channel_config: Record<string, unknown>
|
|
status: string
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export interface Scenario {
|
|
id: string
|
|
name: string
|
|
description: string
|
|
tags: string[]
|
|
cases: any[]
|
|
model_bindings: Record<string, string>
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export type ModelCapability = 'chat' | 'embedding' | 'moderation'
|
|
export type ModelProtocol = 'openai_compatible' | 'anthropic' | 'google_gemini' | 'dashscope'
|
|
export type ModelModality = 'text' | 'image' | 'audio' | 'video'
|
|
|
|
export interface ModelConfig {
|
|
id: string
|
|
name: string
|
|
provider: ModelProtocol
|
|
capability: ModelCapability
|
|
endpoint_url: string
|
|
model_name: string | null
|
|
vendor_name: string
|
|
input_modalities: ModelModality[]
|
|
output_modalities: ModelModality[]
|
|
context_window: number | null
|
|
max_output_tokens: number | null
|
|
supports_streaming: boolean
|
|
supports_tool_calling: boolean
|
|
supports_structured_output: boolean
|
|
supports_reasoning: boolean
|
|
region: string
|
|
documentation_url: string | null
|
|
has_api_key: boolean
|
|
enabled: boolean
|
|
is_default: boolean
|
|
description: string
|
|
created_at: string | null
|
|
updated_at: string | null
|
|
}
|
|
|
|
export interface ModelConfigPayload {
|
|
name: string
|
|
provider: ModelProtocol
|
|
capability: ModelCapability
|
|
endpoint_url: string
|
|
model_name?: string | null
|
|
vendor_name: string
|
|
input_modalities: ModelModality[]
|
|
output_modalities: ModelModality[]
|
|
context_window?: number | null
|
|
max_output_tokens?: number | null
|
|
supports_streaming: boolean
|
|
supports_tool_calling: boolean
|
|
supports_structured_output: boolean
|
|
supports_reasoning: boolean
|
|
region: string
|
|
documentation_url?: string | null
|
|
api_key?: string | null
|
|
clear_api_key?: boolean
|
|
enabled: boolean
|
|
is_default: boolean
|
|
description: string
|
|
}
|
|
|
|
export interface ModelConfigReference {
|
|
scenario_id: string
|
|
scenario_name: string
|
|
purpose: string
|
|
}
|
|
|
|
export interface Run {
|
|
id: string
|
|
target_id: string
|
|
scenario_id: string
|
|
status: string
|
|
started_at: string
|
|
completed_at: string | null
|
|
summary: Record<string, unknown> | null
|
|
}
|
|
|
|
export interface DashboardStats {
|
|
targets_count: number
|
|
scenarios_count: number
|
|
runs_count: number
|
|
overall_pass_rate: number | null
|
|
recent_runs: Run[]
|
|
}
|
|
|
|
export interface TrendPoint {
|
|
date: string
|
|
pass_rate: number
|
|
run_count: number
|
|
}
|
|
|
|
export const targetsApi = {
|
|
list: () => api.get<Target[]>('/targets'),
|
|
get: (id: string) => api.get<Target>(`/targets/${id}`),
|
|
create: (data: Partial<Target>) => api.post<Target>('/targets', data),
|
|
update: (id: string, data: Partial<Target>) => api.put<Target>(`/targets/${id}`, data),
|
|
delete: (id: string) => api.delete(`/targets/${id}`),
|
|
test: (id: string) => api.post<{ ok: boolean; message: string }>(`/targets/${id}/test`),
|
|
runs: (id: string) => api.get<Run[]>(`/targets/${id}/runs`),
|
|
}
|
|
|
|
export const scenariosApi = {
|
|
list: () => api.get<Scenario[]>('/scenarios'),
|
|
get: (id: string) => api.get<Scenario>(`/scenarios/${id}`),
|
|
create: (data: Partial<Scenario>) => api.post<Scenario>('/scenarios', data),
|
|
update: (id: string, data: Partial<Scenario>) => api.put<Scenario>(`/scenarios/${id}`, data),
|
|
delete: (id: string) => api.delete(`/scenarios/${id}`),
|
|
validate: (data: any) => api.post<{ valid: boolean; errors: string[] }>('/scenarios/validate', data),
|
|
listTemplates: () => api.get<any[]>('/scenarios/templates'),
|
|
getTemplate: (id: string) => api.get<any>(`/scenarios/templates/${id}`),
|
|
}
|
|
|
|
export const modelConfigsApi = {
|
|
list: (params?: { capability?: ModelCapability; enabled?: boolean }) =>
|
|
api.get<ModelConfig[]>('/model-configs', { params }),
|
|
get: (id: string) => api.get<ModelConfig>(`/model-configs/${id}`),
|
|
create: (data: ModelConfigPayload) => api.post<ModelConfig>('/model-configs', data),
|
|
update: (id: string, data: ModelConfigPayload) => api.put<ModelConfig>(`/model-configs/${id}`, data),
|
|
delete: (id: string) => api.delete(`/model-configs/${id}`),
|
|
test: (id: string) => api.post<{ ok: boolean; message: string; tested_at: string }>(`/model-configs/${id}/test`),
|
|
references: (id: string) => api.get<ModelConfigReference[]>(`/model-configs/${id}/references`),
|
|
}
|
|
|
|
export const runsApi = {
|
|
list: () => api.get<Run[]>('/runs'),
|
|
start: (target_id: string, scenario_id: string) =>
|
|
api.post<Run>('/runs', { target_id, scenario_id }),
|
|
get: (id: string) => api.get<Run>(`/runs/${id}`),
|
|
logs: (id: string) => api.get<RunLogsResponse>(`/runs/${id}/logs`),
|
|
cancel: (id: string) => api.post(`/runs/${id}/cancel`),
|
|
}
|
|
|
|
export interface RunLogsTurn {
|
|
id: string
|
|
case_id: string
|
|
round_index: number
|
|
latency_ms: number | null
|
|
sent_text: string
|
|
reply_text: string
|
|
sent_at: string | null
|
|
received_at: string | null
|
|
}
|
|
|
|
export interface RunLogsResult {
|
|
case_id: string
|
|
rule_type: string
|
|
passed: boolean
|
|
score: number | null
|
|
reason: string | null
|
|
}
|
|
|
|
export interface CaseSnapshotExpectations {
|
|
intent?: string | null
|
|
keywords_include: string[]
|
|
keywords_exclude: string[]
|
|
response_time_max_ms?: number | null
|
|
coherence_min_score?: number | null
|
|
}
|
|
|
|
export interface CaseSnapshot {
|
|
id: string
|
|
type: string
|
|
messages: string[]
|
|
prompt?: string | null
|
|
turns?: number | null
|
|
expectations: CaseSnapshotExpectations
|
|
eval_rules: { type: string; params: Record<string, unknown> }[]
|
|
}
|
|
|
|
export interface RunLogsResponse {
|
|
turns: RunLogsTurn[]
|
|
results: RunLogsResult[]
|
|
scenario_snapshot: Record<string, CaseSnapshot>
|
|
}
|
|
|
|
export const reportsApi = {
|
|
get: (runId: string) => api.get(`/reports/${runId}`),
|
|
html: (runId: string) => api.get(`/reports/${runId}/html`),
|
|
json: (runId: string) => api.get(`/reports/${runId}/json`),
|
|
markdownUrl: (runId: string) => `/api/reports/${runId}/markdown`,
|
|
compare: (run1: string, run2: string) =>
|
|
api.get(`/reports/compare`, { params: { run1, run2 } }),
|
|
}
|
|
|
|
export const statsApi = {
|
|
dashboard: () => api.get<DashboardStats>('/stats/dashboard'),
|
|
trend: (days?: number) => api.get<TrendPoint[]>('/stats/trend', { params: { days } }),
|
|
}
|
|
|
|
// ── File Management ──────────────────────────────────────────────
|
|
|
|
export interface FileCategory {
|
|
id: string
|
|
name: string
|
|
parent_id: string | null
|
|
children: FileCategory[]
|
|
}
|
|
|
|
export interface FileRecord {
|
|
id: string
|
|
original_name: string
|
|
file_size: number
|
|
mime_type: string
|
|
file_ext: string
|
|
category_id: string | null
|
|
storage_directory: string
|
|
created_at: string | null
|
|
}
|
|
|
|
export interface FileUploadConfig {
|
|
allowed_extensions: string[]
|
|
max_upload_size_mb: number
|
|
}
|
|
|
|
export const filesApi = {
|
|
// Categories
|
|
getConfig: () => api.get<FileUploadConfig>('/files/config'),
|
|
listCategories: () => api.get<FileCategory[]>('/files/categories'),
|
|
createCategory: (data: { name: string; parent_id?: string | null }) =>
|
|
api.post<FileCategory>('/files/categories', data),
|
|
updateCategory: (id: string, data: { name: string }) =>
|
|
api.put(`/files/categories/${id}`, data),
|
|
deleteCategory: (id: string) => api.delete(`/files/categories/${id}`),
|
|
|
|
// Files
|
|
list: (categoryId?: string | null) =>
|
|
api.get<FileRecord[]>('/files', { params: categoryId ? { category_id: categoryId } : {} }),
|
|
upload: (file: File, categoryId?: string | null) => {
|
|
const form = new FormData()
|
|
form.append('file', file)
|
|
if (categoryId) {
|
|
form.append('category_id', categoryId)
|
|
}
|
|
return api.post<FileRecord>('/files/upload', form, {
|
|
timeout: 120000,
|
|
})
|
|
},
|
|
download: (id: string) => api.get<Blob>(`/files/${id}/download`, { responseType: 'blob' }),
|
|
delete: (id: string) => api.delete(`/files/${id}`),
|
|
}
|