Qassure-frontend/src/services/ai-service.ts

274 lines
9.2 KiB
TypeScript

import apiClient from "@/services/api-client";
import type {
AICompletion,
AICompletionListResponse,
AICostSummary,
AIHealthResponse,
AIProviderInfo,
AIPrompt,
KnowledgeCollection,
KnowledgeSearchItem,
TenantAIConfig,
} from "@/types/ai";
const unwrap = <T>(response: any): T => {
if (response?.data?.data !== undefined) return response.data.data as T;
if (response?.data !== undefined) return response.data as T;
return response as T;
};
class AIService {
async getProviders(): Promise<AIProviderInfo[]> {
const response = await apiClient.get("/ai/providers");
return unwrap<AIProviderInfo[]>(response);
}
async getProviderHealth(provider: string): Promise<AIHealthResponse> {
const response = await apiClient.get(`/ai/providers/${encodeURIComponent(provider)}/health`);
return unwrap<AIHealthResponse>(response);
}
async getGatewayHealth(): Promise<AIHealthResponse> {
const response = await apiClient.get("/ai/health");
return unwrap<AIHealthResponse>(response);
}
async getModels(): Promise<Array<{ id: string; provider: string; isDefault?: boolean }>> {
const response = await apiClient.get("/ai/models");
return unwrap<Array<{ id: string; provider: string; isDefault?: boolean }>>(response);
}
async createCompletion(payload: {
messages: Array<{ role: "system" | "user" | "assistant"; content: string }>;
provider?: string;
model?: string;
temperature?: number;
max_tokens?: number;
}): Promise<AICompletion> {
const response = await apiClient.post("/ai/completions", payload);
return unwrap<AICompletion>(response);
}
async getCompletion(id: string): Promise<AICompletion> {
const response = await apiClient.get(`/ai/completions/${encodeURIComponent(id)}`);
return unwrap<AICompletion>(response);
}
async listCompletions(params: {
page?: number;
limit?: number;
provider?: string;
model?: string;
status?: string;
user_id?: string;
module_id?: string;
start_date?: string;
end_date?: string;
}): Promise<AICompletionListResponse> {
const response = await apiClient.get("/ai/completions", { params });
if (response?.data?.data && response?.data?.pagination) {
return { data: response.data.data, pagination: response.data.pagination };
}
return unwrap<AICompletionListResponse>(response);
}
async playground(payload: {
messages: Array<{ role: "system" | "user" | "assistant"; content: string }>;
provider?: string;
model?: string;
temperature?: number;
max_tokens?: number;
}): Promise<AICompletion> {
const response = await apiClient.post("/ai/playground", payload);
return unwrap<AICompletion>(response);
}
async getCostSummary(params: {
group_by?: "day" | "week" | "month";
start_date?: string;
end_date?: string;
} = {}): Promise<AICostSummary> {
const response = await apiClient.get("/ai/costs", { params });
return unwrap<AICostSummary>(response);
}
async upsertConfig(payload: {
provider: string;
config_type: "azure" | "direct";
api_key: string;
display_name?: string;
endpoint?: string;
deployment?: string;
api_version?: string;
custom_models?: string[];
default_model?: string;
is_active?: boolean;
}): Promise<TenantAIConfig> {
const response = await apiClient.post("/ai/config", payload);
return unwrap<TenantAIConfig>(response);
}
async listConfigs(): Promise<TenantAIConfig[]> {
const response = await apiClient.get("/ai/config");
return unwrap<TenantAIConfig[]>(response);
}
async testConfig(provider: string): Promise<AIHealthResponse> {
const response = await apiClient.post(`/ai/config/${encodeURIComponent(provider)}/test`, {});
return unwrap<AIHealthResponse>(response);
}
async deleteConfig(provider: string): Promise<void> {
await apiClient.delete(`/ai/config/${encodeURIComponent(provider)}`);
}
async createPrompt(payload: {
name: string;
description?: string;
use_case: string;
system_message?: string;
user_template: string;
provider?: string;
model?: string;
temperature?: number;
max_tokens?: number;
variables?: Array<{ name: string; type?: "string" | "number" | "boolean" | "array"; required?: boolean }>;
tags?: string[];
is_default?: boolean;
}): Promise<AIPrompt> {
const response = await apiClient.post("/ai/prompts", payload);
return unwrap<AIPrompt>(response);
}
async getPrompt(id: string): Promise<AIPrompt> {
const response = await apiClient.get(`/ai/prompts/${id}`);
return unwrap<AIPrompt>(response);
}
async updatePrompt(id: string, payload: {
name: string;
description?: string;
use_case: string;
system_message?: string;
user_template: string;
provider?: string;
model?: string;
temperature?: number;
max_tokens?: number;
variables?: Array<{ name: string; type?: "string" | "number" | "boolean" | "array"; required?: boolean }>;
tags?: string[];
is_default?: boolean;
change_notes?: string;
}): Promise<AIPrompt> {
const response = await apiClient.put(`/ai/prompts/${id}`, payload);
return unwrap<AIPrompt>(response);
}
async clonePrompt(id: string): Promise<AIPrompt> {
const response = await apiClient.post(`/ai/prompts/${id}/clone`);
return unwrap<AIPrompt>(response);
}
async listPrompts(params: { page?: number; limit?: number; status?: string; search?: string } = {}): Promise<{
data: AIPrompt[];
pagination?: { page: number; limit: number; total: number; totalPages: number };
}> {
const response = await apiClient.get("/ai/prompts", { params });
if (response?.data?.data && response?.data?.pagination) {
return { data: response.data.data, pagination: response.data.pagination };
}
return unwrap(response);
}
async updatePromptStatus(id: string, status: "draft" | "active" | "archived" | "deprecated"): Promise<AIPrompt> {
const response = await apiClient.patch(`/ai/prompts/${id}/status`, { status });
return unwrap<AIPrompt>(response);
}
async deletePrompt(id: string): Promise<void> {
await apiClient.delete(`/ai/prompts/${id}`);
}
async getVersions(id: string): Promise<AIPrompt[]> {
const response = await apiClient.get(`/ai/prompts/${id}/versions`);
return unwrap<AIPrompt[]>(response);
}
async getVersion(id: string, version: number): Promise<AIPrompt> {
const response = await apiClient.get(`/ai/prompts/${id}/versions/${version}`);
return unwrap<AIPrompt>(response);
}
async rollback(id: string, version: number): Promise<AIPrompt> {
const response = await apiClient.post(`/ai/prompts/${id}/rollback`, { version });
return unwrap<AIPrompt>(response);
}
async executePrompt(
id: string,
payload: { variables?: Record<string, unknown>; provider?: string; model?: string; temperature?: number; max_tokens?: number },
): Promise<AICompletion> {
const response = await apiClient.post(`/ai/prompts/${id}/execute`, payload);
return unwrap<AICompletion>(response);
}
async testPrompt(
id: string,
payload: { variables?: Record<string, unknown>; provider?: string; model?: string; temperature?: number; max_tokens?: number },
): Promise<AICompletion> {
const response = await apiClient.post(`/ai/prompts/${id}/test`, payload);
return unwrap<AICompletion>(response);
}
async listCollections(params: { page?: number; limit?: number; status?: string } = {}): Promise<{
data: KnowledgeCollection[];
pagination?: { page: number; limit: number; total: number; totalPages: number };
}> {
const response = await apiClient.get("/ai/knowledge/collections", { params });
if (response?.data?.data && response?.data?.pagination) {
return { data: response.data.data, pagination: response.data.pagination };
}
return unwrap(response);
}
async createCollection(payload: { name: string; description?: string; metadata?: Record<string, unknown> }): Promise<KnowledgeCollection> {
const response = await apiClient.post("/ai/knowledge/collections", payload);
return unwrap<KnowledgeCollection>(response);
}
async uploadKnowledgeDocument(payload: { collectionId: string; file: File; provider?: string }): Promise<unknown> {
const formData = new FormData();
formData.append("collectionId", payload.collectionId);
formData.append("file", payload.file);
if (payload.provider) {
formData.append("provider", payload.provider);
}
const response = await apiClient.post("/ai/knowledge/documents", formData);
return unwrap(response);
}
async searchKnowledge(payload: {
query: string;
collectionId?: string;
provider?: string;
topK?: number;
minScore?: number;
}): Promise<KnowledgeSearchItem[]> {
const response = await apiClient.post("/ai/knowledge/search", payload);
return unwrap<KnowledgeSearchItem[]>(response);
}
async searchKnowledgeWithContext(payload: {
query: string;
collectionId?: string;
provider?: string;
topK?: number;
minScore?: number;
}): Promise<{ context?: string; matches?: KnowledgeSearchItem[] }> {
const response = await apiClient.post("/ai/knowledge/search/context", payload);
return unwrap<{ context?: string; matches?: KnowledgeSearchItem[] }>(response);
}
}
export const aiService = new AIService();