Files

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());
},
};