165 lines
5.4 KiB
TypeScript
165 lines
5.4 KiB
TypeScript
/**
|
|
* 自有 RAG Chat API 模块
|
|
*
|
|
* 保持前端 dify-chat 调用面不变,内部转发到新的 /api/v3/rag/* 接口。
|
|
*
|
|
* @module api/dify-chat/chat
|
|
*/
|
|
|
|
import { difyFetch } from './client.server';
|
|
|
|
function unwrapResult<T>(payload: any): T {
|
|
if (payload && typeof payload === 'object' && 'data' in payload) {
|
|
return payload.data as T;
|
|
}
|
|
return payload as T;
|
|
}
|
|
|
|
function toIntAppId(appId?: string): string | undefined {
|
|
if (!appId) return undefined;
|
|
const parsed = Number(appId);
|
|
return Number.isFinite(parsed) ? String(parsed) : undefined;
|
|
}
|
|
|
|
function normalizeConversationName(name: string): string {
|
|
const compact = (name || '').replace(/\s+/g, ' ').trim();
|
|
if (!compact) return '新对话';
|
|
return compact.length > 20 ? `${compact.slice(0, 20)}...` : compact;
|
|
}
|
|
|
|
export const difyClient = {
|
|
async getApplicationParameters(jwt?: string, appId?: string): Promise<any> {
|
|
const response = await difyFetch('chat/parameters', {
|
|
method: 'GET',
|
|
appId: toIntAppId(appId),
|
|
}, jwt);
|
|
const payload = unwrapResult<any>(await response.json());
|
|
return {
|
|
opening_statement: payload?.openingStatement || '',
|
|
suggested_questions: payload?.suggestedQuestions || [],
|
|
user_input_form: payload?.userInputForm || [],
|
|
file_upload: payload?.fileUpload || { enabled: false },
|
|
};
|
|
},
|
|
|
|
async getConversations(jwt?: string, appId?: string): Promise<any> {
|
|
const params = new URLSearchParams({
|
|
page: '1',
|
|
pageSize: '100',
|
|
});
|
|
const normalizedAppId = toIntAppId(appId);
|
|
if (normalizedAppId) {
|
|
params.set('appId', normalizedAppId);
|
|
}
|
|
|
|
const response = await difyFetch(`chat/conversations?${params.toString()}`, {
|
|
method: 'GET',
|
|
}, jwt);
|
|
const payload = unwrapResult<any>(await response.json());
|
|
return {
|
|
data: (payload?.data || []).map((item: any) => ({
|
|
id: item.id,
|
|
name: item.name,
|
|
introduction: item.introduction || '',
|
|
created_at: item.createdAt || 0,
|
|
updated_at: item.updatedAt || 0,
|
|
})),
|
|
has_more: Boolean(payload?.hasMore),
|
|
limit: payload?.limit || 100,
|
|
};
|
|
},
|
|
|
|
async getConversationMessages(conversationId: string, jwt?: string): Promise<any> {
|
|
const params = new URLSearchParams({
|
|
page: '1',
|
|
pageSize: '100',
|
|
});
|
|
const response = await difyFetch(`chat/conversations/${conversationId}/messages?${params.toString()}`, {
|
|
method: 'GET',
|
|
}, jwt);
|
|
const payload = unwrapResult<any>(await response.json());
|
|
return {
|
|
data: (payload?.data || []).map((item: any) => ({
|
|
id: item.id,
|
|
query: item.query,
|
|
answer: item.answer,
|
|
feedback: item.feedback || undefined,
|
|
retriever_resources: item.retrieverResources || [],
|
|
created_at: item.createdAt || 0,
|
|
})),
|
|
has_more: Boolean(payload?.hasMore),
|
|
limit: payload?.limit || 100,
|
|
};
|
|
},
|
|
|
|
async createChatMessage(
|
|
inputs: Record<string, any>,
|
|
query: string,
|
|
responseMode: string = 'streaming',
|
|
conversationId?: string,
|
|
files?: any[],
|
|
jwt?: string,
|
|
appId?: string
|
|
): Promise<Response | any> {
|
|
const body = {
|
|
inputs,
|
|
query,
|
|
response_mode: responseMode,
|
|
conversation_id: conversationId,
|
|
files: files || [],
|
|
appId: toIntAppId(appId) ? Number(appId) : null,
|
|
conversationId: conversationId || null,
|
|
};
|
|
const response = await difyFetch('chat/messages', {
|
|
method: 'POST',
|
|
body: JSON.stringify(body),
|
|
}, jwt);
|
|
|
|
if (responseMode === 'streaming') {
|
|
return response;
|
|
}
|
|
|
|
return response.json();
|
|
},
|
|
|
|
async renameConversation(
|
|
conversationId: string,
|
|
name: string,
|
|
autoGenerate: boolean = false,
|
|
jwt?: string
|
|
): Promise<any> {
|
|
let nextName = name?.trim() || '';
|
|
|
|
if (autoGenerate || !nextName) {
|
|
const messages = await this.getConversationMessages(conversationId, jwt);
|
|
const firstQuestion = messages?.data?.find((item: any) => item?.query)?.query || '';
|
|
nextName = normalizeConversationName(firstQuestion);
|
|
}
|
|
|
|
const response = await difyFetch(`chat/conversations/${conversationId}`, {
|
|
method: 'PATCH',
|
|
body: JSON.stringify({ name: nextName }),
|
|
}, jwt);
|
|
return unwrapResult<any>(await response.json());
|
|
},
|
|
|
|
async deleteConversation(conversationId: string, jwt?: string): Promise<any> {
|
|
const response = await difyFetch(`chat/conversations/${conversationId}`, {
|
|
method: 'DELETE',
|
|
}, jwt);
|
|
return unwrapResult<any>(await response.json());
|
|
},
|
|
|
|
async updateMessageFeedback(
|
|
messageId: string,
|
|
rating: 'like' | 'dislike' | null,
|
|
jwt?: string
|
|
): Promise<any> {
|
|
const response = await difyFetch(`chat/messages/${messageId}/feedback`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({ rating }),
|
|
}, jwt);
|
|
return unwrapResult<any>(await response.json());
|
|
},
|
|
};
|