forked from open-webui/open-webui
		
	refac
This commit is contained in:
		
							parent
							
								
									8f570bc2ee
								
							
						
					
					
						commit
						3853261b40
					
				
					 3 changed files with 134 additions and 114 deletions
				
			
		|  | @ -249,7 +249,8 @@ export const deleteModel = async (token: string, tagName: string) => { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const pullModel = async (token: string, tagName: string) => { | export const pullModel = async (token: string, tagName: string) => { | ||||||
| try { | 	let error = null; | ||||||
|  | 
 | ||||||
| 	const res = await fetch(`${OLLAMA_API_BASE_URL}/pull`, { | 	const res = await fetch(`${OLLAMA_API_BASE_URL}/pull`, { | ||||||
| 		method: 'POST', | 		method: 'POST', | ||||||
| 		headers: { | 		headers: { | ||||||
|  | @ -259,9 +260,31 @@ try { | ||||||
| 		body: JSON.stringify({ | 		body: JSON.stringify({ | ||||||
| 			name: tagName | 			name: tagName | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}).catch((err) => { | ||||||
| 	return res; | 		console.log(err); | ||||||
| } catch (error) { | 		error = err; | ||||||
|  | 
 | ||||||
|  | 		if ('detail' in err) { | ||||||
|  | 			error = err.detail; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return null; | ||||||
|  | 	}); | ||||||
|  | 	if (error) { | ||||||
| 		throw error; | 		throw error; | ||||||
| 	} | 	} | ||||||
|  | 	return res; | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | // export const pullModel = async (token: string, tagName: string) => {
 | ||||||
|  | // 	return await fetch(`${OLLAMA_API_BASE_URL}/pull`, {
 | ||||||
|  | // 		method: 'POST',
 | ||||||
|  | // 		headers: {
 | ||||||
|  | // 			'Content-Type': 'text/event-stream',
 | ||||||
|  | // 			Authorization: `Bearer ${token}`
 | ||||||
|  | // 		},
 | ||||||
|  | // 		body: JSON.stringify({
 | ||||||
|  | // 			name: tagName
 | ||||||
|  | // 		})
 | ||||||
|  | // 	});
 | ||||||
|  | // };
 | ||||||
|  |  | ||||||
|  | @ -51,7 +51,11 @@ | ||||||
| 	let notificationEnabled = false; | 	let notificationEnabled = false; | ||||||
| 	let system = ''; | 	let system = ''; | ||||||
| 	const MAX_PARALLEL_DOWNLOADS = 3; | 	const MAX_PARALLEL_DOWNLOADS = 3; | ||||||
| 	const modelDownloadQueue = queue((task:{modelName: string}, cb) => pullModelHandlerProcessor({modelName: task.modelName, callback: cb}), MAX_PARALLEL_DOWNLOADS); | 	const modelDownloadQueue = queue( | ||||||
|  | 		(task: { modelName: string }, cb) => | ||||||
|  | 			pullModelHandlerProcessor({ modelName: task.modelName, callback: cb }), | ||||||
|  | 		MAX_PARALLEL_DOWNLOADS | ||||||
|  | 	); | ||||||
| 	let modelDownloadStatus: Record<string, any> = {}; | 	let modelDownloadStatus: Record<string, any> = {}; | ||||||
| 
 | 
 | ||||||
| 	// Advanced | 	// Advanced | ||||||
|  | @ -250,11 +254,13 @@ | ||||||
| 		saveSettings({ saveChatHistory: saveChatHistory }); | 		saveSettings({ saveChatHistory: saveChatHistory }); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	const pullModelHandlerProcessor = async (opts:{modelName:string, callback: Function}) => { | 	const pullModelHandlerProcessor = async (opts: { modelName: string; callback: Function }) => { | ||||||
| 
 | 		const res = await pullModel(localStorage.token, opts.modelName).catch((error) => { | ||||||
| 		try { | 			opts.callback({ success: false, error, modelName: opts.modelName }); | ||||||
| 			const res = await pullModel(localStorage.token, opts.modelName); | 			return null; | ||||||
|  | 		}); | ||||||
| 
 | 
 | ||||||
|  | 		if (res) { | ||||||
| 			const reader = res.body | 			const reader = res.body | ||||||
| 				.pipeThrough(new TextDecoderStream()) | 				.pipeThrough(new TextDecoderStream()) | ||||||
| 				.pipeThrough(splitStream('\n')) | 				.pipeThrough(splitStream('\n')) | ||||||
|  | @ -284,88 +290,56 @@ | ||||||
| 									} else { | 									} else { | ||||||
| 										downloadProgress = 100; | 										downloadProgress = 100; | ||||||
| 									} | 									} | ||||||
| 								modelDownloadStatus[opts.modelName] = {pullProgress: downloadProgress, digest: data.digest}; | 									modelDownloadStatus[opts.modelName] = { | ||||||
|  | 										pullProgress: downloadProgress, | ||||||
|  | 										digest: data.digest | ||||||
|  | 									}; | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} catch (error) { | 				} catch (error) { | ||||||
| 					console.log('Failed to read from data stream', error); | 					console.log(error); | ||||||
| 					throw error; | 					opts.callback({ success: false, error, modelName: opts.modelName }); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			opts.callback({ success: true, modelName: opts.modelName }); | 			opts.callback({ success: true, modelName: opts.modelName }); | ||||||
| 		} catch (error) { |  | ||||||
| 			console.error(error); |  | ||||||
| 			opts.callback({success:false, error, modelName: opts.modelName}); |  | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		 |  | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	const pullModelHandler = async () => { | 	const pullModelHandler = async () => { | ||||||
| 		if (modelDownloadStatus[modelTag]) { | 		if (modelDownloadStatus[modelTag]) { | ||||||
| 			toast.error("Model already in queue for downloading."); | 			toast.error('Model already in queue for downloading.'); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		if (Object.keys(modelDownloadStatus).length === 3) { | 		if (Object.keys(modelDownloadStatus).length === 3) { | ||||||
| 			toast.error('Maximum of 3 models can be downloading simultaneously. Please try again later'); | 			toast.error('Maximum of 3 models can be downloading simultaneously. Please try again later'); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		modelTransferring = true; | 		modelTransferring = true; | ||||||
| 
 | 
 | ||||||
| 		modelDownloadQueue.push({modelName: modelTag},async (data:{modelName: string; success: boolean; error?: Error}) => { | 		modelDownloadQueue.push( | ||||||
|  | 			{ modelName: modelTag }, | ||||||
|  | 			async (data: { modelName: string; success: boolean; error?: Error }) => { | ||||||
| 				const { modelName } = data; | 				const { modelName } = data; | ||||||
| 				// Remove the downloaded model | 				// Remove the downloaded model | ||||||
| 				delete modelDownloadStatus[modelName]; | 				delete modelDownloadStatus[modelName]; | ||||||
| 
 | 
 | ||||||
|  | 				console.log(data); | ||||||
|  | 
 | ||||||
| 				if (!data.success) { | 				if (!data.success) { | ||||||
| 				toast.error(`There was some issue in downloading the model ${modelName}`); | 					toast.error(data.error); | ||||||
| 					return; | 					return; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				toast.success(`Model ${modelName} was successfully downloaded`); | 				toast.success(`Model ${modelName} was successfully downloaded`); | ||||||
| 				models.set(await getModels()); | 				models.set(await getModels()); | ||||||
| 		}); | 			} | ||||||
|  | 		); | ||||||
| 
 | 
 | ||||||
| 		modelTag = ''; | 		modelTag = ''; | ||||||
| 		modelTransferring = false; | 		modelTransferring = false; | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	const calculateSHA256 = async (file) => { |  | ||||||
| 		console.log(file); |  | ||||||
| 		// Create a FileReader to read the file asynchronously |  | ||||||
| 		const reader = new FileReader(); |  | ||||||
| 
 |  | ||||||
| 		// Define a promise to handle the file reading |  | ||||||
| 		const readFile = new Promise((resolve, reject) => { |  | ||||||
| 			reader.onload = () => resolve(reader.result); |  | ||||||
| 			reader.onerror = reject; |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		// Read the file as an ArrayBuffer |  | ||||||
| 		reader.readAsArrayBuffer(file); |  | ||||||
| 
 |  | ||||||
| 		try { |  | ||||||
| 			// Wait for the FileReader to finish reading the file |  | ||||||
| 			const buffer = await readFile; |  | ||||||
| 
 |  | ||||||
| 			// Convert the ArrayBuffer to a Uint8Array |  | ||||||
| 			const uint8Array = new Uint8Array(buffer); |  | ||||||
| 
 |  | ||||||
| 			// Calculate the SHA-256 hash using Web Crypto API |  | ||||||
| 			const hashBuffer = await crypto.subtle.digest('SHA-256', uint8Array); |  | ||||||
| 
 |  | ||||||
| 			// Convert the hash to a hexadecimal string |  | ||||||
| 			const hashArray = Array.from(new Uint8Array(hashBuffer)); |  | ||||||
| 			const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join(''); |  | ||||||
| 
 |  | ||||||
| 			return `sha256:${hashHex}`; |  | ||||||
| 		} catch (error) { |  | ||||||
| 			console.error('Error calculating SHA-256 hash:', error); |  | ||||||
| 			throw error; |  | ||||||
| 		} |  | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	const uploadModelHandler = async () => { | 	const uploadModelHandler = async () => { | ||||||
|  | @ -1190,22 +1164,12 @@ | ||||||
| 								</div> | 								</div> | ||||||
| 							</div> | 							</div> | ||||||
| 							{#if Object.keys(modelDownloadStatus).length > 0} | 							{#if Object.keys(modelDownloadStatus).length > 0} | ||||||
| 							<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400"> |  | ||||||
| 								<thead |  | ||||||
| 									class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400" |  | ||||||
| 								> |  | ||||||
| 									<tr> |  | ||||||
| 										<th scope="col" class="px-6 py-3"> Model Name </th> |  | ||||||
| 										<th scope="col" class="px-6 py-3"> Download progress </th> |  | ||||||
| 									</tr> |  | ||||||
| 								</thead> |  | ||||||
| 								<tbody> |  | ||||||
| 								{#each Object.entries(modelDownloadStatus) as [modelName, payload]} | 								{#each Object.entries(modelDownloadStatus) as [modelName, payload]} | ||||||
| 									<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700"> | 									<div class="flex flex-col"> | ||||||
| 										<td class="px-6 py-4">{modelName}</td> | 										<div class="font-medium mb-0.5">{modelName}</div> | ||||||
| 										<td class="px-6 py-4"> | 										<div class=""> | ||||||
| 											<div | 											<div | ||||||
| 											class="dark:bg-gray-600 bg-green-600 text-xs font-medium text-blue-100 text-center p-0.5 leading-none rounded-full" | 												class="dark:bg-gray-600 bg-gray-500 text-xs font-medium text-gray-100 text-center p-0.5 leading-none rounded-full" | ||||||
| 												style="width: {Math.max(15, payload.pullProgress ?? 0)}%" | 												style="width: {Math.max(15, payload.pullProgress ?? 0)}%" | ||||||
| 											> | 											> | ||||||
| 												{payload.pullProgress ?? 0}% | 												{payload.pullProgress ?? 0}% | ||||||
|  | @ -1213,11 +1177,9 @@ | ||||||
| 											<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;"> | 											<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;"> | ||||||
| 												{payload.digest} | 												{payload.digest} | ||||||
| 											</div> | 											</div> | ||||||
| 									</td> | 										</div> | ||||||
| 									</tr> | 									</div> | ||||||
| 								{/each} | 								{/each} | ||||||
| 									</tbody> |  | ||||||
| 									</table> |  | ||||||
| 							{/if} | 							{/if} | ||||||
| 							<hr class=" dark:border-gray-700" /> | 							<hr class=" dark:border-gray-700" /> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -127,3 +127,38 @@ export const findWordIndices = (text) => { | ||||||
| 
 | 
 | ||||||
| 	return matches; | 	return matches; | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | export const calculateSHA256 = async (file) => { | ||||||
|  | 	console.log(file); | ||||||
|  | 	// Create a FileReader to read the file asynchronously
 | ||||||
|  | 	const reader = new FileReader(); | ||||||
|  | 
 | ||||||
|  | 	// Define a promise to handle the file reading
 | ||||||
|  | 	const readFile = new Promise((resolve, reject) => { | ||||||
|  | 		reader.onload = () => resolve(reader.result); | ||||||
|  | 		reader.onerror = reject; | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	// Read the file as an ArrayBuffer
 | ||||||
|  | 	reader.readAsArrayBuffer(file); | ||||||
|  | 
 | ||||||
|  | 	try { | ||||||
|  | 		// Wait for the FileReader to finish reading the file
 | ||||||
|  | 		const buffer = await readFile; | ||||||
|  | 
 | ||||||
|  | 		// Convert the ArrayBuffer to a Uint8Array
 | ||||||
|  | 		const uint8Array = new Uint8Array(buffer); | ||||||
|  | 
 | ||||||
|  | 		// Calculate the SHA-256 hash using Web Crypto API
 | ||||||
|  | 		const hashBuffer = await crypto.subtle.digest('SHA-256', uint8Array); | ||||||
|  | 
 | ||||||
|  | 		// Convert the hash to a hexadecimal string
 | ||||||
|  | 		const hashArray = Array.from(new Uint8Array(hashBuffer)); | ||||||
|  | 		const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join(''); | ||||||
|  | 
 | ||||||
|  | 		return `sha256:${hashHex}`; | ||||||
|  | 	} catch (error) { | ||||||
|  | 		console.error('Error calculating SHA-256 hash:', error); | ||||||
|  | 		throw error; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy J. Baek
						Timothy J. Baek