274 lines
9.2 KiB
TypeScript
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();
|