301 lines
7.9 KiB
TypeScript
301 lines
7.9 KiB
TypeScript
/**
|
||
* Dify Dataset 客户端 API 模块
|
||
*
|
||
* 提供浏览器端调用 Dify 知识库 API 的函数
|
||
* 通过 Remix API Routes 代理请求
|
||
*
|
||
* @module api/dify-dataset/client
|
||
*/
|
||
|
||
import axios from 'axios';
|
||
import type {
|
||
DatasetsResponse,
|
||
DocumentsResponse,
|
||
SegmentsResponse,
|
||
Document,
|
||
OperationResult,
|
||
} from './types';
|
||
|
||
// ============================================================================
|
||
// 基础配置
|
||
// ============================================================================
|
||
|
||
/**
|
||
* API 基础 URL
|
||
* 指向 Remix API Routes(/api/dataset/*)
|
||
*/
|
||
const API_URL = '/api/dataset';
|
||
|
||
// ============================================================================
|
||
// 知识库 API
|
||
// ============================================================================
|
||
|
||
/**
|
||
* 获取知识库列表
|
||
*
|
||
* @param page - 页码,默认 1
|
||
* @param limit - 每页数量,默认 20
|
||
* @returns 知识库列表响应
|
||
*/
|
||
export async function fetchDatasets(
|
||
page: number = 1,
|
||
limit: number = 20
|
||
): Promise<DatasetsResponse> {
|
||
const params = new URLSearchParams({
|
||
page: page.toString(),
|
||
limit: limit.toString(),
|
||
});
|
||
|
||
const response = await axios.get<DatasetsResponse>(
|
||
`${API_URL}/datasets?${params}`,
|
||
{ withCredentials: true }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* 获取单个知识库详情
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @returns 知识库详情
|
||
*/
|
||
export async function fetchDataset(datasetId: string): Promise<any> {
|
||
const response = await axios.get(
|
||
`${API_URL}/datasets/${datasetId}`,
|
||
{ withCredentials: true }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
// ============================================================================
|
||
// 文档 API
|
||
// ============================================================================
|
||
|
||
/**
|
||
* 获取知识库文档列表
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param page - 页码,默认 1
|
||
* @param limit - 每页数量,默认 20
|
||
* @param keyword - 搜索关键词
|
||
* @returns 文档列表响应
|
||
*/
|
||
export async function fetchDocuments(
|
||
datasetId: string,
|
||
page: number = 1,
|
||
limit: number = 20,
|
||
keyword?: string
|
||
): Promise<DocumentsResponse> {
|
||
const params = new URLSearchParams({
|
||
page: page.toString(),
|
||
limit: limit.toString(),
|
||
});
|
||
|
||
if (keyword) {
|
||
params.append('keyword', keyword);
|
||
}
|
||
|
||
console.log('[Dataset Client] 获取文档列表:', { datasetId, page, limit, keyword });
|
||
|
||
const response = await axios.get<DocumentsResponse>(
|
||
`${API_URL}/datasets/${datasetId}/documents?${params}`,
|
||
{ withCredentials: true }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* 获取单个文档详情
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param documentId - 文档 ID
|
||
* @returns 文档详情
|
||
*/
|
||
export async function fetchDocument(
|
||
datasetId: string,
|
||
documentId: string
|
||
): Promise<Document> {
|
||
const response = await axios.get<Document>(
|
||
`${API_URL}/datasets/${datasetId}/documents/${documentId}`,
|
||
{ withCredentials: true }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* 删除文档
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param documentId - 文档 ID
|
||
* @returns 操作结果
|
||
*/
|
||
export async function deleteDocument(
|
||
datasetId: string,
|
||
documentId: string
|
||
): Promise<OperationResult> {
|
||
console.log('[Dataset Client] 删除文档:', { datasetId, documentId });
|
||
|
||
const response = await axios.delete<OperationResult>(
|
||
`${API_URL}/datasets/${datasetId}/documents/${documentId}`,
|
||
{ withCredentials: true }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* 启用/禁用文档
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param documentId - 文档 ID
|
||
* @param enabled - 是否启用
|
||
* @returns 操作结果
|
||
*/
|
||
export async function toggleDocumentStatus(
|
||
datasetId: string,
|
||
documentId: string,
|
||
enabled: boolean
|
||
): Promise<OperationResult> {
|
||
console.log('[Dataset Client] 切换文档状态:', { datasetId, documentId, enabled });
|
||
|
||
const response = await axios.patch<OperationResult>(
|
||
`${API_URL}/datasets/${datasetId}/documents/${documentId}/status`,
|
||
{ enabled },
|
||
{
|
||
headers: { 'Content-Type': 'application/json' },
|
||
withCredentials: true,
|
||
}
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
// ============================================================================
|
||
// 文档分段 API
|
||
// ============================================================================
|
||
|
||
/**
|
||
* 获取文档分段列表
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param documentId - 文档 ID
|
||
* @param page - 页码,默认 1
|
||
* @param limit - 每页数量,默认 20
|
||
* @param keyword - 搜索关键词
|
||
* @returns 分段列表响应
|
||
*/
|
||
export async function fetchSegments(
|
||
datasetId: string,
|
||
documentId: string,
|
||
page: number = 1,
|
||
limit: number = 20,
|
||
keyword?: string
|
||
): Promise<SegmentsResponse> {
|
||
const params = new URLSearchParams({
|
||
page: page.toString(),
|
||
limit: limit.toString(),
|
||
});
|
||
|
||
if (keyword) {
|
||
params.append('keyword', keyword);
|
||
}
|
||
|
||
console.log('[Dataset Client] 获取分段列表:', { datasetId, documentId, page, limit });
|
||
|
||
const response = await axios.get<SegmentsResponse>(
|
||
`${API_URL}/datasets/${datasetId}/documents/${documentId}/segments?${params}`,
|
||
{ withCredentials: true }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* 删除分段
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param documentId - 文档 ID
|
||
* @param segmentId - 分段 ID
|
||
* @returns 操作结果
|
||
*/
|
||
export async function deleteSegment(
|
||
datasetId: string,
|
||
documentId: string,
|
||
segmentId: string
|
||
): Promise<OperationResult> {
|
||
console.log('[Dataset Client] 删除分段:', { datasetId, documentId, segmentId });
|
||
|
||
const response = await axios.delete<OperationResult>(
|
||
`${API_URL}/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}`,
|
||
{ withCredentials: true }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* 启用/禁用分段
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param documentId - 文档 ID
|
||
* @param segmentId - 分段 ID
|
||
* @param enabled - 是否启用
|
||
* @returns 操作结果
|
||
*/
|
||
export async function toggleSegmentStatus(
|
||
datasetId: string,
|
||
documentId: string,
|
||
segmentId: string,
|
||
enabled: boolean
|
||
): Promise<OperationResult> {
|
||
const response = await axios.patch<OperationResult>(
|
||
`${API_URL}/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}/status`,
|
||
{ enabled },
|
||
{
|
||
headers: { 'Content-Type': 'application/json' },
|
||
withCredentials: true,
|
||
}
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
// ============================================================================
|
||
// 文件上传 API
|
||
// ============================================================================
|
||
|
||
/**
|
||
* 上传文件到知识库
|
||
*
|
||
* @param datasetId - 知识库 ID
|
||
* @param file - 文件对象
|
||
* @param onProgress - 上传进度回调
|
||
* @returns 创建的文档信息
|
||
*/
|
||
export async function uploadDocument(
|
||
datasetId: string,
|
||
file: File,
|
||
onProgress?: (percent: number) => void
|
||
): Promise<any> {
|
||
const formData = new FormData();
|
||
formData.append('file', file);
|
||
formData.append('data', JSON.stringify({
|
||
indexing_technique: 'high_quality',
|
||
process_rule: {
|
||
mode: 'automatic',
|
||
},
|
||
}));
|
||
|
||
console.log('[Dataset Client] 上传文档:', { datasetId, fileName: file.name });
|
||
|
||
const response = await axios.post(
|
||
`${API_URL}/datasets/${datasetId}/documents/create-by-file`,
|
||
formData,
|
||
{
|
||
withCredentials: true,
|
||
onUploadProgress: (progressEvent) => {
|
||
if (progressEvent.total && onProgress) {
|
||
const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||
onProgress(percent);
|
||
}
|
||
},
|
||
}
|
||
);
|
||
return response.data;
|
||
}
|