AI问数
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
export * from './bot';
|
||||
export * from './report';
|
||||
export * from './report-bot';
|
||||
export * from './report-cube';
|
||||
export * from './report-data';
|
||||
export * from './service';
|
||||
export * from './service-knowledge';
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
import { useAppConfig } from '@vben/hooks';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { pyRequestClient } from '#/api/request';
|
||||
|
||||
export interface CubeReportScope {
|
||||
canGlobal: boolean;
|
||||
companies: Array<{ id: string; name: string }>;
|
||||
}
|
||||
|
||||
export interface CubeReportAppParameters {
|
||||
fileUpload: Record<string, unknown>;
|
||||
openingStatement: string;
|
||||
suggestedQuestions: string[];
|
||||
suggestedQuestionsAfterAnswer: { enabled: boolean };
|
||||
systemParameters: Record<string, unknown>;
|
||||
userInputForm: Array<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export interface CubeReportSession {
|
||||
allowGlobal: boolean;
|
||||
createdAt: null | string;
|
||||
hasData?: boolean;
|
||||
id: string;
|
||||
tenantId: null | string;
|
||||
tenantName: string;
|
||||
title: string;
|
||||
updatedAt: null | string;
|
||||
}
|
||||
|
||||
export interface CubeReportFile {
|
||||
belongsTo?: 'assistant' | 'user';
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface CubeReportMessage {
|
||||
content: string;
|
||||
createdAt: null | string;
|
||||
difyMessageId: null | string;
|
||||
files: CubeReportFile[];
|
||||
id: string;
|
||||
role: 'assistant' | 'user';
|
||||
status: 'completed' | 'failed' | 'streaming';
|
||||
}
|
||||
|
||||
export interface CubeReportColumn {
|
||||
key: string;
|
||||
title: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface CubeReportPage {
|
||||
columns: CubeReportColumn[];
|
||||
limitSource?: 'system' | 'user';
|
||||
page: number;
|
||||
pageSize: number;
|
||||
rows: Array<Record<string, unknown>>;
|
||||
sql?: string;
|
||||
title?: string;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface CubeReportExportResult {
|
||||
bucketName: string;
|
||||
filename: string;
|
||||
objectName: string;
|
||||
rowCount: number;
|
||||
sheetCount: number;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export type CubeReportStreamEvent =
|
||||
| { content: string; type: 'message_delta' | 'message_replace' }
|
||||
| {
|
||||
conversationId?: string;
|
||||
hasData: boolean;
|
||||
type: 'complete';
|
||||
}
|
||||
| { message: string; type: 'error' }
|
||||
| { taskId: string; type: 'task' }
|
||||
| { text: string; type: 'status' };
|
||||
|
||||
export interface SendCubeReportMessage {
|
||||
allowGlobal: boolean;
|
||||
content: string;
|
||||
conversationId?: null | string;
|
||||
files: CubeReportFile[];
|
||||
tenantId?: string;
|
||||
tenantName?: string;
|
||||
}
|
||||
|
||||
function getFetchConfig() {
|
||||
const { pyApiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||
const accessStore = useAccessStore();
|
||||
return {
|
||||
baseURL: pyApiURL.replace(/\/$/, ''),
|
||||
authorization: accessStore.accessToken
|
||||
? `Bearer ${accessStore.accessToken}`
|
||||
: '',
|
||||
};
|
||||
}
|
||||
|
||||
async function responseError(response: Response) {
|
||||
const text = await response.text();
|
||||
try {
|
||||
const payload = JSON.parse(text) as { detail?: string; message?: string };
|
||||
return payload.detail || payload.message || text;
|
||||
} catch {
|
||||
return text || `请求失败(${response.status})`;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getCubeReportScope() {
|
||||
return pyRequestClient.get<CubeReportScope>('/llm/cube-report/scope');
|
||||
}
|
||||
|
||||
export async function getCubeReportAppParameters() {
|
||||
return pyRequestClient.get<CubeReportAppParameters>(
|
||||
'/llm/cube-report/app-parameters',
|
||||
);
|
||||
}
|
||||
|
||||
export async function getCubeReportSessions() {
|
||||
return pyRequestClient.get<CubeReportSession[]>('/llm/cube-report/sessions');
|
||||
}
|
||||
|
||||
export async function getCubeReportSession(id: string) {
|
||||
return pyRequestClient.get<{
|
||||
messages: CubeReportMessage[];
|
||||
session: CubeReportSession;
|
||||
}>(`/llm/cube-report/sessions/${id}`);
|
||||
}
|
||||
|
||||
export async function getCubeReportData(
|
||||
id: string,
|
||||
params: { page: number; pageSize: number },
|
||||
) {
|
||||
return pyRequestClient.get<CubeReportPage>(
|
||||
`/llm/cube-report/sessions/${id}/data`,
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
export async function exportCubeReportSession(id: string) {
|
||||
return pyRequestClient.post<CubeReportExportResult>(
|
||||
`/llm/cube-report/sessions/${id}/export`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function renameCubeReportSession(id: string, name: string) {
|
||||
return pyRequestClient.post<CubeReportSession>(
|
||||
`/llm/cube-report/sessions/${id}/name`,
|
||||
{ name },
|
||||
);
|
||||
}
|
||||
|
||||
export async function deleteCubeReportSession(id: string) {
|
||||
return pyRequestClient.delete<{ result: string }>(
|
||||
`/llm/cube-report/sessions/${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function stopCubeReportTask(taskId: string) {
|
||||
return pyRequestClient.post<{ result: string }>(
|
||||
`/llm/cube-report/tasks/${taskId}/stop`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function uploadCubeReportFile(file: File) {
|
||||
const { authorization, baseURL } = getFetchConfig();
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const response = await fetch(`${baseURL}/llm/cube-report/files/upload`, {
|
||||
method: 'POST',
|
||||
headers: { Authorization: authorization },
|
||||
body: form,
|
||||
});
|
||||
if (!response.ok) throw new Error(await responseError(response));
|
||||
const payload = (await response.json()) as {
|
||||
data: CubeReportFile;
|
||||
};
|
||||
return payload.data;
|
||||
}
|
||||
|
||||
export async function downloadCubeReportFile(
|
||||
conversationId: string,
|
||||
file: CubeReportFile,
|
||||
) {
|
||||
const { authorization, baseURL } = getFetchConfig();
|
||||
const params = new URLSearchParams({
|
||||
conversationId,
|
||||
asAttachment: 'true',
|
||||
});
|
||||
const response = await fetch(
|
||||
`${baseURL}/llm/cube-report/files/${file.id}/preview?${params}`,
|
||||
{ headers: { Authorization: authorization } },
|
||||
);
|
||||
if (!response.ok) throw new Error(await responseError(response));
|
||||
const blob = await response.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
const anchor = document.createElement('a');
|
||||
anchor.href = url;
|
||||
anchor.download = file.name;
|
||||
anchor.click();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
export async function streamCubeReportMessage(
|
||||
payload: SendCubeReportMessage,
|
||||
onEvent: (event: CubeReportStreamEvent) => void,
|
||||
) {
|
||||
const { authorization, baseURL } = getFetchConfig();
|
||||
const response = await fetch(`${baseURL}/llm/cube-report/messages/stream`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'text/event-stream',
|
||||
Authorization: authorization,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(await responseError(response));
|
||||
if (!response.body) throw new Error('当前浏览器不支持流式响应');
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
let buffer = '';
|
||||
const consumePacket = (packet: string) => {
|
||||
const data = packet
|
||||
.split(/\r?\n/)
|
||||
.filter((line) => line.startsWith('data: '))
|
||||
.map((line) => line.slice(6))
|
||||
.join('\n');
|
||||
if (data) onEvent(JSON.parse(data) as CubeReportStreamEvent);
|
||||
};
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
buffer += decoder.decode(value, { stream: !done });
|
||||
const packets = buffer.split(/\r?\n\r?\n/);
|
||||
buffer = packets.pop() ?? '';
|
||||
packets.forEach((packet) => consumePacket(packet));
|
||||
if (done) break;
|
||||
}
|
||||
if (buffer.trim()) consumePacket(buffer);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user