Spaces:
Build error
Build error
File size: 3,963 Bytes
ca552c5 2238e7a ca552c5 2f317f9 ca552c5 2f317f9 ca552c5 2f317f9 ca552c5 2238e7a ca552c5 2238e7a ca552c5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | import { useState, useRef } from 'react'
import { API_BASE, authHeaders } from '../config'
export function useStreaming() {
const [loading, setLoading] = useState(false)
const [response, setResponse] = useState(null)
const [error, setError] = useState(null)
const [streamingText, setStreamingText] = useState('')
const abortRef = useRef(null)
const readNDJSONStream = async (res) => {
const reader = res.body.getReader()
const decoder = new TextDecoder()
let accumulated = ''
let buffer = ''
let streamError = null
while (true) {
const { done, value } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
const lines = buffer.split('\n')
buffer = lines.pop()
for (const line of lines) {
if (!line.trim()) continue
try {
const chunk = JSON.parse(line)
if (chunk.error) {
streamError = String(chunk.error)
continue
}
if (chunk.response) {
accumulated += chunk.response
setStreamingText(accumulated)
}
} catch { /* skip malformed */ }
}
}
if (streamError) {
throw new Error(streamError)
}
const finalText = accumulated.trim()
if (!finalText) {
throw new Error('Model returned an empty response. Try again or pick a different model.')
}
return finalText
}
const streamFrom = async (endpoint, { json, formData } = {}) => {
abortRef.current = new AbortController()
const fetchOpts = {
method: 'POST',
signal: abortRef.current.signal,
}
if (json) {
fetchOpts.headers = authHeaders({ 'Content-Type': 'application/json' })
fetchOpts.body = JSON.stringify(json)
} else if (formData) {
fetchOpts.headers = authHeaders()
fetchOpts.body = formData
}
const res = await fetch(`${API_BASE}${endpoint}`, fetchOpts)
if (!res.ok) {
const body = await res.text()
let detail = `Backend error (${res.status})`
try { detail = JSON.parse(body).detail } catch { /* use default */ }
throw new Error(detail)
}
return readNDJSONStream(res)
}
const submit = async (activeTab, { youtubeUrl, transcript, selectedFile, selectedModel }) => {
setLoading(true)
setError(null)
setResponse(null)
setStreamingText('')
try {
let summary
if (activeTab === 'youtube') {
if (!youtubeUrl.trim()) throw new Error('Please enter a YouTube URL')
summary = await streamFrom('/summarize/youtube', { json: { url: youtubeUrl, model: selectedModel } })
} else if (activeTab === 'transcript') {
if (!transcript.trim()) throw new Error('Please enter some text')
summary = await streamFrom('/summarize/transcript', { json: { text: transcript, model: selectedModel } })
} else if (activeTab === 'file') {
if (!selectedFile) throw new Error('Please select a file')
const fd = new FormData()
fd.append('file', selectedFile)
summary = await streamFrom(`/summarize/file?model=${encodeURIComponent(selectedModel)}`, { formData: fd })
}
setResponse({ summary, success: true, source_type: activeTab, model: selectedModel })
} catch (err) {
setError(err.message || 'An error occurred')
} finally {
setLoading(false)
}
}
return { loading, response, error, streamingText, submit }
}
|