1+ import systemPrompt from "../systemPrompt.js" ;
2+ import sarvamSystemPrompt from "../sarvamSystemPrompt.js" ;
3+
4+ import { GoogleGenAI } from "@google/genai" ;
5+ import Cerebras from "@cerebras/cerebras_cloud_sdk" ;
6+ import { SarvamAIClient } from "sarvamai" ;
7+
8+ import sarvamClient from "./sarvamClient.js" ;
9+
10+ const geminiAI = new GoogleGenAI ( {
11+ apiKey : process . env . GEMINI_API_KEY ,
12+ } ) ;
13+
14+ const cerebras = new Cerebras ( {
15+ apiKey : process . env . CEREBRAS_API_KEY ,
16+ } ) ;
17+
18+ export async function * streamGemini ( prompt ) {
19+ const responseStream = await geminiAI . models . generateContentStream ( {
20+ model : "gemini-2.5-flash" ,
21+ contents : prompt ,
22+ config : {
23+ systemInstruction : systemPrompt ,
24+ temperature : 0.7 ,
25+ } ,
26+ } ) ;
27+
28+ for await ( const chunk of responseStream ) {
29+ const text = chunk . text || "" ;
30+ if ( text ) yield text ;
31+ }
32+ }
33+
34+ export async function * streamCerebras ( prompt ) {
35+ const stream = await cerebras . chat . completions . create ( {
36+ model : "gpt-oss-120b" ,
37+ stream : true ,
38+ messages : [
39+ { role : "system" , content : systemPrompt } ,
40+ { role : "user" , content : prompt } ,
41+ ] ,
42+ } ) ;
43+
44+ for await ( const chunk of stream ) {
45+ const text = chunk . choices ?. [ 0 ] ?. delta ?. content || "" ;
46+ if ( text ) yield text ;
47+ }
48+ }
49+
50+ export async function * streamGemma ( prompt ) {
51+ const response = await fetch ( `${ process . env . OLLAMA_BASE_URL } /api/chat` , {
52+ method : "POST" ,
53+ headers : {
54+ "Content-Type" : "application/json" ,
55+ } ,
56+ body : JSON . stringify ( {
57+ model : process . env . OLLAMA_MODEL ,
58+ messages : [
59+ { role : "system" , content : systemPrompt } ,
60+ { role : "user" , content : prompt } ,
61+ ] ,
62+ stream : true ,
63+ } ) ,
64+ } ) ;
65+
66+ if ( ! response . ok || ! response . body ) {
67+ throw new Error ( "Failed to stream response from Ollama" ) ;
68+ }
69+
70+ const reader = response . body . getReader ( ) ;
71+ const decoder = new TextDecoder ( ) ;
72+ let buffer = "" ;
73+
74+ while ( true ) {
75+ const { value, done } = await reader . read ( ) ;
76+
77+ if ( done ) break ;
78+
79+ buffer += decoder . decode ( value , { stream : true } ) ;
80+
81+ const lines = buffer . split ( "\n" ) ;
82+ buffer = lines . pop ( ) || "" ;
83+
84+ for ( const line of lines ) {
85+ if ( ! line . trim ( ) ) continue ;
86+
87+ const json = JSON . parse ( line ) ;
88+ const text = json . message ?. content || "" ;
89+
90+ if ( text ) yield text ;
91+ if ( json . done ) return ;
92+ }
93+ }
94+ }
95+
96+ export async function * streamSarvam ( prompt ) {
97+ const client = new SarvamAIClient ( {
98+ apiSubscriptionKey : process . env . SARVAM_API_KEY ,
99+ } ) ;
100+
101+ try {
102+ const stream = await client . chat . completions ( {
103+ model : "sarvam-30b" ,
104+ stream : true ,
105+ messages : [
106+ { role : "system" , content : sarvamSystemPrompt } ,
107+ {
108+ role : "user" ,
109+ content : `${ prompt } \n\n(Reply in Hinglish, same energy as always)` ,
110+ } ,
111+ ] ,
112+ temperature : 0.5 ,
113+ top_p : 1 ,
114+ max_tokens : 2000 ,
115+ reasoning_effort : null ,
116+ } ) ;
117+
118+ for await ( const chunk of stream ) {
119+ const text = chunk . choices ?. [ 0 ] ?. delta ?. content || "" ;
120+ if ( text ) yield text ;
121+ }
122+ } catch {
123+ // Safe fallback if the installed Sarvam JS SDK version does not support streaming.
124+ const fullResponse = await sarvamClient ( prompt ) ;
125+ yield fullResponse ;
126+ }
127+ }
128+
129+ export const streamingModels = {
130+ gemini : streamGemini ,
131+ cerebras : streamCerebras ,
132+ gemma : streamGemma ,
133+ sarvam : streamSarvam ,
134+ } ;
0 commit comments