feat: download llamacpp backend fail back to cdn (#6361)
* feat: download llamacpp backend fail back to cdn incase github api encounters errors
This commit is contained in:
parent
b2c4e89402
commit
1b74772d07
@ -77,7 +77,7 @@ export async function listSupportedBackends(): Promise<
|
|||||||
supportedBackends.push('macos-arm64')
|
supportedBackends.push('macos-arm64')
|
||||||
}
|
}
|
||||||
|
|
||||||
const releases = await _fetchGithubReleases('menloresearch', 'llama.cpp')
|
const { releases } = await _fetchGithubReleases('menloresearch', 'llama.cpp')
|
||||||
releases.sort((a, b) => b.tag_name.localeCompare(a.tag_name))
|
releases.sort((a, b) => b.tag_name.localeCompare(a.tag_name))
|
||||||
releases.splice(10) // keep only the latest 10 releases
|
releases.splice(10) // keep only the latest 10 releases
|
||||||
|
|
||||||
@ -145,7 +145,8 @@ export async function isBackendInstalled(
|
|||||||
|
|
||||||
export async function downloadBackend(
|
export async function downloadBackend(
|
||||||
backend: string,
|
backend: string,
|
||||||
version: string
|
version: string,
|
||||||
|
source: 'github' | 'cdn' = 'github'
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const janDataFolderPath = await getJanDataFolderPath()
|
const janDataFolderPath = await getJanDataFolderPath()
|
||||||
const llamacppPath = await joinPath([janDataFolderPath, 'llamacpp'])
|
const llamacppPath = await joinPath([janDataFolderPath, 'llamacpp'])
|
||||||
@ -161,9 +162,15 @@ export async function downloadBackend(
|
|||||||
|
|
||||||
const platformName = IS_WINDOWS ? 'win' : 'linux'
|
const platformName = IS_WINDOWS ? 'win' : 'linux'
|
||||||
|
|
||||||
|
// Build URLs per source
|
||||||
|
const backendUrl =
|
||||||
|
source === 'github'
|
||||||
|
? `https://github.com/menloresearch/llama.cpp/releases/download/${version}/llama-${version}-bin-${backend}.tar.gz`
|
||||||
|
: `https://catalog.jan.ai/llama.cpp/releases/${version}/llama-${version}-bin-${backend}.tar.gz`
|
||||||
|
|
||||||
const downloadItems = [
|
const downloadItems = [
|
||||||
{
|
{
|
||||||
url: `https://github.com/menloresearch/llama.cpp/releases/download/${version}/llama-${version}-bin-${backend}.tar.gz`,
|
url: backendUrl,
|
||||||
save_path: await joinPath([backendDir, 'backend.tar.gz']),
|
save_path: await joinPath([backendDir, 'backend.tar.gz']),
|
||||||
proxy: proxyConfig,
|
proxy: proxyConfig,
|
||||||
},
|
},
|
||||||
@ -172,13 +179,19 @@ export async function downloadBackend(
|
|||||||
// also download CUDA runtime + cuBLAS + cuBLASLt if needed
|
// also download CUDA runtime + cuBLAS + cuBLASLt if needed
|
||||||
if (backend.includes('cu11.7') && !(await _isCudaInstalled('11.7'))) {
|
if (backend.includes('cu11.7') && !(await _isCudaInstalled('11.7'))) {
|
||||||
downloadItems.push({
|
downloadItems.push({
|
||||||
url: `https://github.com/menloresearch/llama.cpp/releases/download/${version}/cudart-llama-bin-${platformName}-cu11.7-x64.tar.gz`,
|
url:
|
||||||
|
source === 'github'
|
||||||
|
? `https://github.com/menloresearch/llama.cpp/releases/download/${version}/cudart-llama-bin-${platformName}-cu11.7-x64.tar.gz`
|
||||||
|
: `https://catalog.jan.ai/llama.cpp/releases/${version}/cudart-llama-bin-${platformName}-cu11.7-x64.tar.gz`,
|
||||||
save_path: await joinPath([libDir, 'cuda11.tar.gz']),
|
save_path: await joinPath([libDir, 'cuda11.tar.gz']),
|
||||||
proxy: proxyConfig,
|
proxy: proxyConfig,
|
||||||
})
|
})
|
||||||
} else if (backend.includes('cu12.0') && !(await _isCudaInstalled('12.0'))) {
|
} else if (backend.includes('cu12.0') && !(await _isCudaInstalled('12.0'))) {
|
||||||
downloadItems.push({
|
downloadItems.push({
|
||||||
url: `https://github.com/menloresearch/llama.cpp/releases/download/${version}/cudart-llama-bin-${platformName}-cu12.0-x64.tar.gz`,
|
url:
|
||||||
|
source === 'github'
|
||||||
|
? `https://github.com/menloresearch/llama.cpp/releases/download/${version}/cudart-llama-bin-${platformName}-cu12.0-x64.tar.gz`
|
||||||
|
: `https://catalog.jan.ai/llama.cpp/releases/${version}/cudart-llama-bin-${platformName}-cu12.0-x64.tar.gz`,
|
||||||
save_path: await joinPath([libDir, 'cuda12.tar.gz']),
|
save_path: await joinPath([libDir, 'cuda12.tar.gz']),
|
||||||
proxy: proxyConfig,
|
proxy: proxyConfig,
|
||||||
})
|
})
|
||||||
@ -188,7 +201,7 @@ export async function downloadBackend(
|
|||||||
const downloadType = 'Engine'
|
const downloadType = 'Engine'
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Downloading backend ${backend} version ${version}: ${JSON.stringify(
|
`Downloading backend ${backend} version ${version} from ${source}: ${JSON.stringify(
|
||||||
downloadItems
|
downloadItems
|
||||||
)}`
|
)}`
|
||||||
)
|
)
|
||||||
@ -223,6 +236,11 @@ export async function downloadBackend(
|
|||||||
|
|
||||||
events.emit('onFileDownloadSuccess', { modelId: taskId, downloadType })
|
events.emit('onFileDownloadSuccess', { modelId: taskId, downloadType })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Fallback: if GitHub fails, retry once with CDN
|
||||||
|
if (source === 'github') {
|
||||||
|
console.warn(`GitHub download failed, falling back to CDN:`, error)
|
||||||
|
return await downloadBackend(backend, version, 'cdn')
|
||||||
|
}
|
||||||
console.error(`Failed to download backend ${backend}: `, error)
|
console.error(`Failed to download backend ${backend}: `, error)
|
||||||
events.emit('onFileDownloadError', { modelId: taskId, downloadType })
|
events.emit('onFileDownloadError', { modelId: taskId, downloadType })
|
||||||
throw error
|
throw error
|
||||||
@ -270,20 +288,31 @@ async function _getSupportedFeatures() {
|
|||||||
return features
|
return features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch releases with GitHub-first strategy and fallback to CDN on any error.
|
||||||
|
* CDN endpoint is expected to mirror GitHub releases JSON shape.
|
||||||
|
*/
|
||||||
async function _fetchGithubReleases(
|
async function _fetchGithubReleases(
|
||||||
owner: string,
|
owner: string,
|
||||||
repo: string
|
repo: string
|
||||||
): Promise<any[]> {
|
): Promise<{ releases: any[]; source: 'github' | 'cdn' }> {
|
||||||
// by default, it's per_page=30 and page=1 -> the latest 30 releases
|
const githubUrl = `https://api.github.com/repos/${owner}/${repo}/releases`
|
||||||
const url = `https://api.github.com/repos/${owner}/${repo}/releases`
|
try {
|
||||||
const response = await fetch(url)
|
const response = await fetch(githubUrl)
|
||||||
|
if (!response.ok) throw new Error(`GitHub error: ${response.status} ${response.statusText}`)
|
||||||
|
const releases = await response.json()
|
||||||
|
return { releases, source: 'github' }
|
||||||
|
} catch (_err) {
|
||||||
|
const cdnUrl = 'https://catalog.jan.ai/llama.cpp/releases/releases.json'
|
||||||
|
const response = await fetch(cdnUrl)
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(
|
throw new Error(`Failed to fetch releases from both sources. CDN error: ${response.status} ${response.statusText}`)
|
||||||
`Failed to fetch releases from ${url}: ${response.statusText}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return response.json()
|
const releases = await response.json()
|
||||||
|
return { releases, source: 'cdn' }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function _isCudaInstalled(version: string): Promise<boolean> {
|
async function _isCudaInstalled(version: string): Promise<boolean> {
|
||||||
const sysInfo = await getSystemInfo()
|
const sysInfo = await getSystemInfo()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user