|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export interface HuggingFaceFileResult { |
|
|
file_id: string; |
|
|
file_url: string; |
|
|
repo_path: string; |
|
|
} |
|
|
|
|
|
const HF_API_BASE = 'https://huggingface.co/api'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export async function uploadToHuggingFace( |
|
|
file: Blob, |
|
|
fileName: string, |
|
|
fileId: string |
|
|
): Promise<HuggingFaceFileResult> { |
|
|
const token = process.env.HF_TOKEN; |
|
|
const repoId = process.env.HF_REPO_ID; |
|
|
const repoType = process.env.HF_REPO_TYPE || 'dataset'; |
|
|
|
|
|
if (!token || !repoId) { |
|
|
throw new Error('Hugging Face credentials not configured. Set HF_TOKEN and HF_REPO_ID'); |
|
|
} |
|
|
|
|
|
|
|
|
const arrayBuffer = await file.arrayBuffer(); |
|
|
const buffer = Buffer.from(arrayBuffer); |
|
|
const base64Content = buffer.toString('base64'); |
|
|
|
|
|
|
|
|
const ext = fileName.split('.').pop() || 'bin'; |
|
|
const pathInRepo = `files/${fileId}.${ext}`; |
|
|
|
|
|
|
|
|
|
|
|
const repoTypePlural = repoType === 'dataset' ? 'datasets' : 'models'; |
|
|
const commitUrl = `${HF_API_BASE}/${repoTypePlural}/${repoId}/commit/main`; |
|
|
|
|
|
|
|
|
const commitData = { |
|
|
operations: [ |
|
|
{ |
|
|
operation: 'add', |
|
|
path: pathInRepo, |
|
|
content: base64Content, |
|
|
} |
|
|
], |
|
|
commit_message: `Upload ${fileName}`, |
|
|
}; |
|
|
|
|
|
const response = await fetch(commitUrl, { |
|
|
method: 'POST', |
|
|
headers: { |
|
|
'Authorization': `Bearer ${token}`, |
|
|
'Content-Type': 'application/json', |
|
|
}, |
|
|
body: JSON.stringify(commitData), |
|
|
}); |
|
|
|
|
|
if (!response.ok) { |
|
|
const errorText = await response.text(); |
|
|
throw new Error(`Hugging Face API error: ${response.status} - ${errorText}`); |
|
|
} |
|
|
|
|
|
|
|
|
const fileUrl = `https://huggingface.co/${repoType === 'dataset' ? 'datasets' : repoType}/${repoId}/resolve/main/${pathInRepo}`; |
|
|
|
|
|
|
|
|
const cdnUrl = `https://cdn.huggingface.co/${repoId}/main/${pathInRepo}`; |
|
|
|
|
|
return { |
|
|
file_id: fileId, |
|
|
file_url: cdnUrl, |
|
|
repo_path: pathInRepo, |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export async function getHuggingFaceUrl( |
|
|
fileId: string, |
|
|
extension: string = 'jpg' |
|
|
): Promise<string> { |
|
|
const repoId = process.env.HF_REPO_ID; |
|
|
const repoType = process.env.HF_REPO_TYPE || 'dataset'; |
|
|
const pathInRepo = `files/${fileId}.${extension}`; |
|
|
|
|
|
|
|
|
return `https://cdn.huggingface.co/${repoId}/main/${pathInRepo}`; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function isHuggingFaceConfigured(): boolean { |
|
|
return !!(process.env.HF_TOKEN && process.env.HF_REPO_ID); |
|
|
} |
|
|
|