vedaco commited on
Commit
7d944f7
·
verified ·
1 Parent(s): 3ad9cb7

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +69 -246
server.js CHANGED
@@ -8,265 +8,88 @@ app.use(cors());
8
  app.use(express.json({ limit: '50mb' }));
9
 
10
  const PORT = process.env.PORT || 7860;
11
-
12
- // Ollama Configuration - use 127.0.0.1 instead of localhost
13
- const OLLAMA_HOST = process.env.OLLAMA_URL || 'http://127.0.0.1:11434';
14
  const MODEL = process.env.MODEL || 'qwen3.5:0.8b';
15
 
16
- // Parse OLLAMA_URL to get hostname and port
17
- const OLLAMA_URL_OBJ = new URL(OLLAMA_HOST);
18
- const OLLAMA_HOSTNAME = OLLAMA_URL_OBJ.hostname;
19
- const OLLAMA_PORT = OLLAMA_URL_OBJ.port || 11434;
20
-
21
- // Tera V2 System Prompt
22
- const SYSTEM_PROMPT = `You are Tera V2, an advanced AI document intelligence assistant.
23
-
24
- Your capabilities:
25
- - Analyze complex documents, contracts, and research papers
26
- - Extract key insights and summarize content
27
- - Answer questions based on provided documents
28
- - Generate podcast scripts and audio content
29
-
30
- Response Style:
31
- - Professional yet approachable
32
- - Clear and concise
33
- - Cite specific parts of documents when answering
34
- - Format responses for readability`;
35
 
36
- console.log('╔════════════════════════════════════════╗');
37
- console.log('║ Tera V2 Starting... ║');
38
- console.log('╚════════════════════════════════════════╝');
39
- console.log(`Model: ${MODEL}`);
40
- console.log(`Ollama: ${OLLAMA_HOST}:${OLLAMA_PORT}\n`);
41
-
42
- // Root route - API info
43
  app.get('/', (req, res) => {
44
- res.json({
45
- name: 'Tera V2 API',
46
- version: '2.0.0',
47
- model: MODEL,
48
- status: 'running',
49
- ollama: `${OLLAMA_HOST}:${OLLAMA_PORT}`,
50
- endpoints: {
51
- health: '/health',
52
- chat: '/api/chat',
53
- audio: '/api/generate-audio-script'
54
- }
55
- });
56
  });
57
 
58
  // Health check
59
- app.get('/health', async (req, res) => {
60
- try {
61
- const options = {
62
- hostname: OLLAMA_HOSTNAME,
63
- port: OLLAMA_PORT,
64
- path: '/api/tags',
65
- method: 'GET',
66
- timeout: 5000
67
- };
68
-
69
- const request = http.request(options, (response) => {
70
- let data = '';
71
- response.on('data', chunk => data += chunk);
72
- response.on('end', () => {
73
- try {
74
- const models = JSON.parse(data).models || [];
75
- const hasModel = models.some(m => m.name.includes(MODEL));
76
- res.json({
77
- status: 'ok',
78
- service: 'Tera V2',
79
- model: MODEL,
80
- modelLoaded: hasModel,
81
- ollamaConnected: true
82
- });
83
- } catch (e) {
84
- res.status(503).json({
85
- status: 'error',
86
- message: 'Ollama not responding correctly',
87
- ollamaConnected: false
88
- });
89
- }
90
- });
91
- });
92
-
93
- request.on('error', (err) => {
94
- console.error('Health check error:', err.message);
95
- res.status(503).json({
96
- status: 'error',
97
- message: 'Ollama not running',
98
- solution: 'Wait for container to finish starting',
99
- ollamaConnected: false
100
- });
101
- });
102
-
103
- request.setTimeout(5000, () => {
104
- request.destroy();
105
- res.status(503).json({
106
- status: 'error',
107
- message: 'Ollama timeout',
108
- ollamaConnected: false
109
- });
110
- });
111
-
112
- request.end();
113
-
114
- } catch (error) {
115
- res.status(503).json({
116
- status: 'error',
117
- message: error.message,
118
- ollamaConnected: false
119
- });
120
- }
121
  });
122
 
123
- // Chat endpoint with streaming
124
  app.post('/api/chat', async (req, res) => {
125
- try {
126
- const { messages, sources } = req.body;
127
-
128
- // Build context from sources
129
- let context = '';
130
- if (sources && sources.length > 0) {
131
- context = '\n\nDOCUMENTS:\n' + sources.map((s, i) =>
132
- `[${i + 1}] ${s.name}:\n${s.content?.substring(0, 3000) || '[Image]'}`
133
- ).join('\n\n');
134
- }
135
-
136
- const lastMessage = messages[messages.length - 1];
137
- const prompt = `${SYSTEM_PROMPT}${context}\n\nUser: ${lastMessage.content}\n\nTera V2:`;
138
-
139
- res.setHeader('Content-Type', 'text/event-stream');
140
- res.setHeader('Cache-Control', 'no-cache');
141
-
142
- const requestData = JSON.stringify({
143
- model: MODEL,
144
- prompt: prompt,
145
- stream: true,
146
- options: { temperature: 0.7, num_predict: 4096 }
147
- });
148
-
149
- const options = {
150
- hostname: OLLAMA_HOSTNAME,
151
- port: OLLAMA_PORT,
152
- path: '/api/generate',
153
- method: 'POST',
154
- headers: {
155
- 'Content-Type': 'application/json',
156
- 'Content-Length': Buffer.byteLength(requestData)
157
- },
158
- timeout: 120000
159
- };
160
-
161
- const proxyReq = http.request(options, (proxyRes) => {
162
- proxyRes.on('data', (chunk) => {
163
- const lines = chunk.toString().split('\n');
164
- for (const line of lines) {
165
- if (line.trim()) {
166
- try {
167
- const data = JSON.parse(line);
168
- if (data.response) {
169
- res.write(`data: {"content": ${JSON.stringify(data.response)}}\n\n`);
170
- }
171
- if (data.done) {
172
- res.write('data: {"done": true}\n\n');
173
- }
174
- } catch (e) {}
175
- }
176
  }
177
- });
178
-
179
- proxyRes.on('end', () => {
180
- res.write('data: {"done": true}\n\n');
181
- res.end();
182
- });
183
- });
184
-
185
- proxyReq.on('error', (error) => {
186
- console.error('Ollama error:', error.message);
187
- res.write(`data: {"error": "Ollama connection failed: ${error.message}"}\n\n`);
188
- res.end();
189
- });
190
-
191
- proxyReq.write(requestData);
192
- proxyReq.end();
193
-
194
- } catch (error) {
195
- console.error('Chat error:', error.message);
196
- res.status(500).json({ error: error.message });
197
- }
198
- });
199
-
200
- // Audio script generation
201
- app.post('/api/generate-audio-script', async (req, res) => {
202
- try {
203
- const { sources, format, instructions } = req.body;
204
-
205
- let content = '';
206
- if (sources && sources.length > 0) {
207
- content = sources.map(s => s.content?.substring(0, 4000) || '').join('\n\n');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
209
-
210
- const formatPrompts = {
211
- deepdive: 'Create an in-depth podcast discussion between two hosts analyzing the content.',
212
- briefing: 'Create a brief news-style summary of the key points.',
213
- story: 'Create a narrative-driven exploration of the content.'
214
- };
215
-
216
- const customInstr = instructions ? ` ${instructions}` : '';
217
- const prompt = `${SYSTEM_PROMPT}\n\nYou are creating a podcast script. ${formatPrompts[format] || formatPrompts.deepdive}${customInstr}\n\nDocuments:\n${content}\n\nScript:`;
218
-
219
- const requestData = JSON.stringify({
220
- model: MODEL,
221
- prompt: prompt,
222
- stream: false,
223
- options: { temperature: 0.8, num_predict: 4096 }
224
- });
225
-
226
- const options = {
227
- hostname: OLLAMA_HOSTNAME,
228
- port: OLLAMA_PORT,
229
- path: '/api/generate',
230
- method: 'POST',
231
- headers: {
232
- 'Content-Type': 'application/json',
233
- 'Content-Length': Buffer.byteLength(requestData)
234
- }
235
- };
236
-
237
- const proxyReq = http.request(options, (proxyRes) => {
238
- let data = '';
239
- proxyRes.on('data', chunk => data += chunk);
240
- proxyRes.on('end', () => {
241
- try {
242
- const response = JSON.parse(data);
243
- res.json({ script: response.response, success: true });
244
- } catch (e) {
245
- res.status(500).json({ error: 'Invalid response from Ollama' });
246
- }
247
- });
248
- });
249
-
250
- proxyReq.on('error', (error) => {
251
- res.status(500).json({ error: error.message });
252
- });
253
-
254
- proxyReq.write(requestData);
255
- proxyReq.end();
256
-
257
- } catch (error) {
258
- res.status(500).json({ error: error.message });
259
- }
260
  });
261
 
262
  app.listen(PORT, () => {
263
- console.log('╔════════════════════════════════════════╗');
264
- console.log('║ Tera V2 is Ready! ║');
265
- console.log('╚════════════════════════════════════════╝');
266
- console.log(`Server: http://localhost:${PORT}`);
267
- console.log(`Ollama: ${OLLAMA_HOST}:${OLLAMA_PORT}`);
268
- console.log(`Model: ${MODEL}`);
269
- console.log('');
270
- console.log('Waiting for Ollama to be ready...');
271
- console.log('╔════════════════════════════════════════╗\n');
272
  });
 
8
  app.use(express.json({ limit: '50mb' }));
9
 
10
  const PORT = process.env.PORT || 7860;
11
+ const OLLAMA_HOST = '127.0.0.1';
12
+ const OLLAMA_PORT = 11434;
 
13
  const MODEL = process.env.MODEL || 'qwen3.5:0.8b';
14
 
15
+ console.log('Tera V2 Starting...');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ // Root route
 
 
 
 
 
 
18
  app.get('/', (req, res) => {
19
+ res.json({ name: 'Tera V2 API', version: '2.0.0', model: MODEL, status: 'running' });
 
 
 
 
 
 
 
 
 
 
 
20
  });
21
 
22
  // Health check
23
+ app.get('/health', (req, res) => {
24
+ res.json({ status: 'ok', service: 'Tera V2', model: MODEL });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  });
26
 
27
+ // SIMPLE CHAT (Non-streaming - works better)
28
  app.post('/api/chat', async (req, res) => {
29
+ try {
30
+ const { messages, sources } = req.body;
31
+
32
+ // Build prompt
33
+ let context = '';
34
+ if (sources && sources.length > 0) {
35
+ context = '\n\nDOCUMENTS:\n' + sources.map(s => s.name + ':\n' + (s.content?.substring(0, 2000) || '')).join('\n\n');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
+
38
+ const prompt = `You are Tera V2, an AI assistant.${context}\n\nUser: ${messages[messages.length-1].content}\n\nTera V2:`;
39
+
40
+ console.log('Processing:', messages[messages.length-1].content.substring(0, 50));
41
+
42
+ // Call Ollama
43
+ const requestData = JSON.stringify({
44
+ model: MODEL,
45
+ prompt: prompt,
46
+ stream: false,
47
+ options: { temperature: 0.7, num_predict: 2048 }
48
+ });
49
+
50
+ const options = {
51
+ hostname: OLLAMA_HOST,
52
+ port: OLLAMA_PORT,
53
+ path: '/api/generate',
54
+ method: 'POST',
55
+ headers: {
56
+ 'Content-Type': 'application/json',
57
+ 'Content-Length': Buffer.byteLength(requestData)
58
+ },
59
+ timeout: 120000
60
+ };
61
+
62
+ const proxyReq = http.request(options, (proxyRes) => {
63
+ let data = '';
64
+ proxyRes.on('data', chunk => data += chunk);
65
+ proxyRes.on('end', () => {
66
+ try {
67
+ const response = JSON.parse(data);
68
+ // Return in same format as before for compatibility
69
+ res.json({
70
+ content: response.response,
71
+ done: true
72
+ });
73
+ } catch (e) {
74
+ res.status(500).json({ error: 'Failed to parse response' });
75
+ }
76
+ });
77
+ });
78
+
79
+ proxyReq.on('error', (e) => {
80
+ console.error('Ollama error:', e.message);
81
+ res.status(500).json({ error: e.message });
82
+ });
83
+
84
+ proxyReq.write(requestData);
85
+ proxyReq.end();
86
+
87
+ } catch (error) {
88
+ console.error('Error:', error.message);
89
+ res.status(500).json({ error: error.message });
90
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  });
92
 
93
  app.listen(PORT, () => {
94
+ console.log('Tera V2 Ready on port', PORT);
 
 
 
 
 
 
 
 
95
  });