| 9 | const [loading, setLoading] = useState(false); |
| 10 | |
| 11 | const handleSubmit = async (e: React.FormEvent) => { |
| 12 | e.preventDefault(); |
| 13 | if (!prompt.trim() || loading) return; |
| 14 | |
| 15 | setLoading(true); |
| 16 | setCompletion(''); |
| 17 | |
| 18 | try { |
| 19 | const response = await fetch('/api/langbase/pipes/run-stream', { |
| 20 | method: 'POST', |
| 21 | headers: {'Content-Type': 'application/json'}, |
| 22 | // Send prompt as an LLM message. |
| 23 | body: JSON.stringify({ |
| 24 | messages: [{role: 'user', content: prompt}], |
| 25 | stream: true, |
| 26 | }), |
| 27 | }); |
| 28 | |
| 29 | if (response.body) { |
| 30 | // Convert the stream to a stream runner. |
| 31 | const runner = getRunner(response.body); |
| 32 | |
| 33 | // Method 1: Using event listeners |
| 34 | runner.on('connect', () => { |
| 35 | console.log('Stream started.\n'); |
| 36 | }); |
| 37 | |
| 38 | runner.on('content', content => { |
| 39 | setCompletion(prev => prev + content); |
| 40 | }); |
| 41 | |
| 42 | runner.on('end', () => { |
| 43 | console.log('\nStream ended.'); |
| 44 | }); |
| 45 | |
| 46 | runner.on('error', error => { |
| 47 | console.error('Error:', error); |
| 48 | }); |
| 49 | |
| 50 | console.dir(await runner.finalChatCompletion(), {depth: null}); |
| 51 | |
| 52 | // Method #2 to get all of the chunk. |
| 53 | // for await (const chunk of runner) { |
| 54 | // const content = chunk?.choices[0]?.delta?.content; |
| 55 | // content && setCompletion(prev => prev + content); |
| 56 | // } |
| 57 | } |
| 58 | } catch (error) { |
| 59 | setLoading(false); |
| 60 | console.error('Error:', error); |
| 61 | } finally { |
| 62 | setLoading(false); |
| 63 | } |
| 64 | }; |
| 65 | |
| 66 | return ( |
| 67 | <div className="bg-neutral-200 rounded-md p-2 flex flex-col gap-2 w-full"> |