rrg92 commited on
Commit
f2e63dd
·
1 Parent(s): ef1251b

Suporte a mais modelos e outros ajustes

Browse files
Files changed (1) hide show
  1. server.js +290 -58
server.js CHANGED
@@ -6,11 +6,236 @@ process.on('uncaughtException', err => console.log('JayCoach:Exception:', err))
6
 
7
  const hfToken = process.env.HF_TOKEN
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  if(!hfToken){
10
  throw new Error('NO TOKEN!');
11
  }
12
 
13
- async function Prompt(error, tentativas){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  if(tentativas){
16
  tentativas = 'últimas tentativas:'+tentativas
@@ -21,40 +246,40 @@ async function Prompt(error, tentativas){
21
  if(error <= 450)
22
  tom = `Gere mensagens com bastantes elogios, duvidando se foi realmente um humano que fez isso
23
  EXEMPLOS:
24
- - Rapaz, acho que isso foi humanamente impossível...
25
- - Você não está usando um script não né?
26
- - Não é possível, tá muito baixo pra ter sido um ser humano...
27
  `
28
  else if(error <= 500)
29
- tom = `Gere mensagens que parabenizem e elogiem o desempenho
30
  EXEMPLOS:
31
- - Muito, muito, mas muito bom!
32
- - ora, ora ora, temos um Vingador da IA aqui
33
- - Você é o pica das galáxias da IA hein!
34
  `
35
 
36
  else if(error <= 2000)
37
  tom = `Gere mensagens inspiradoras, no sentido em que está indo bem!
38
  EXEMPLOS:
39
- - Vamos lá, dá pra melhorar, você consegue
40
- - Não desista, continue tentando
41
  `
42
  else
43
  tom = `Gere mensagens sarcástias e engraçadas brincando com a situação. Faça piadas e zoeiras.
44
  EXEMPLOS:
45
- - Ei, psiu, volta aqui
46
- - Ou, não é pra aí não, volta aqui
47
- - Você ainda tá tentando ou tá só de brincadeira mesmo?
48
- - Ainda bem que eu não sou você hein...
49
- - Nossa, mas esse erro tá sensacionalmente errado!
50
- - Muito bom continue assim #sqn
51
  `
52
 
 
 
53
  let prompt = `
54
  Um usuário está estudando Redes Neurais e IA e está aprendendo o conceito de Erro (erro quadrático médio).
55
- Ele está fazendo um exercío onde deve conseguir gerar um erro o mais próximo de 0 possível.
56
- Gere uma mensagem para ser exibida ao usuário com base no valor do erro atual dele.
57
- Use emojis nas respostas, quando apropriado!
58
 
59
  ${tom}
60
 
@@ -62,51 +287,29 @@ async function Prompt(error, tentativas){
62
  Informações das tentativas:
63
 
64
  Erro atual: ${error}
65
- ${tentativas}
66
-
67
- RESTRIÇÕES: máx 20 palavras, encerrar com |fim|
 
 
 
 
 
 
 
 
68
  ---
69
  `
70
 
71
- console.log(prompt.length, prompt);
72
-
73
- let data = {
74
- inputs: [
75
- "<|user|>"
76
- ,prompt
77
- +"<|end|>"
78
- ,"<|assistant|>"
79
- ].join("\n")
80
-
81
- ,parameters:{
82
- max_new_tokens: 70
83
- ,return_full_text: false
84
- ,temperature: 0.7
85
- }
86
-
87
- ,options:{
88
- use_cache: false
89
- ,wait_for_model: false
90
- }
91
-
92
- }
93
-
94
- const response = await fetch(
95
- "https://api-inference.huggingface.co/models/meta-llama/Meta-Llama-3-8B-Instruct",
96
- {
97
- headers: { Authorization: "Bearer "+hfToken, "content-type":"application/json" },
98
- method: "POST",
99
- body: JSON.stringify(data),
100
- }
101
- );
102
-
103
- const result = await response.json();
104
- return result;
105
  }
106
 
107
  app.get('/error', async (req, res) => {
108
 
109
  let tentativas = req.query.tentativas;
 
110
 
111
  if(tentativas && tentativas.length >= 100){
112
  res.json({error:"Tentando atacar né?"})
@@ -117,15 +320,32 @@ app.get('/error', async (req, res) => {
117
  tentativas = tentativas.split(",").map(Number).join(",");
118
 
119
 
120
- resp = await Prompt(req.query.error, tentativas);
 
 
 
 
 
 
 
121
 
 
 
 
 
122
 
123
  let gentext = resp[0].generated_text
124
 
125
  let textParts = gentext.split('|fim|');
126
- let txtFinal = textParts[0];
 
 
 
 
 
127
 
128
  console.log("FullResp:"+gentext);
 
129
  res.json({text:txtFinal})
130
  })
131
 
@@ -133,6 +353,18 @@ app.get('/test', async (req, res) => {
133
  res.send("Working!")
134
  })
135
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  app.use(function(err, req, res, next) {
137
  console.error(err.stack);
138
  res.json({error:'Server error, admin must check logs',status:res.status})
 
6
 
7
  const hfToken = process.env.HF_TOKEN
8
 
9
+
10
+ const MODELS = {
11
+
12
+ 'phi3': {
13
+ name: 'microsoft/Phi-3-mini-128k-instruct'
14
+ ,prompt: function(prompt){
15
+ return [
16
+ "<|user|>"
17
+ ,prompt
18
+ +"<|end|>"
19
+ ,"<|assistant|>"
20
+ ].join("\n")
21
+ }
22
+ }
23
+
24
+ ,'phi3mini4': {
25
+ name: 'microsoft/Phi-3-mini-4k-instruct'
26
+ ,prompt: function(prompt){
27
+ return [
28
+ "<|user|>"
29
+ ,prompt
30
+ +"<|end|>"
31
+ ,"<|assistant|>"
32
+ ].join("\n")
33
+ }
34
+ }
35
+
36
+
37
+
38
+ ,'lama': {
39
+ name: 'meta-llama/Meta-Llama-3-8B-Instruct'
40
+ ,prompt: function(prompt){
41
+ return [
42
+ "<|start_header_id|>user<|end_header_id|>"
43
+ ,prompt+"<|eot_id|><|start_header_id|>assistant<|end_header_id|>"
44
+ +""
45
+ ].join("\n")
46
+ }
47
+ }
48
+
49
+ ,'mistral':{
50
+ name: 'mistralai/Mistral-7B-Instruct-v0.3'
51
+ ,prompt: function(prompt){
52
+ return prompt;
53
+ return [
54
+ "[INST]"+prompt+"[/INST]"
55
+ ].join("\n")
56
+ }
57
+
58
+ }
59
+
60
+ }
61
+
62
+
63
  if(!hfToken){
64
  throw new Error('NO TOKEN!');
65
  }
66
 
67
+ let LastWorkedModel = '';
68
+ const ModelNames = Object.keys(MODELS);
69
+ const ModelList = []
70
+ let BestModel = {}
71
+
72
+ for(let modelId in MODELS){
73
+ let model = MODELS[modelId]
74
+
75
+ model.id = modelId
76
+ model.stats = {
77
+ total:0
78
+ ,erros:0
79
+ ,parcela:1
80
+ ,get errop() { return this.total === 0 ? 0 : this.erros/this.total }
81
+ ,get pok() { return 1 - this.errop }
82
+ }
83
+
84
+ ModelList.push(model);
85
+ }
86
+
87
+ // Encontrar o modelo que oferece que tem melhor chances do acerto!
88
+ /*
89
+ Se você não entendeu o codigo abaixo, parabens. Eu tb não rsrs.
90
+ brincadeir...
91
+ Aqui é apenas uma pequena maneira de calcular o melhor modelo rpa ser usado...
92
+ Cada model tem uma prop que chamei de pok (Percentual de OK = % de sucesso quando o model foi usado!)
93
+ Então, vamos somar todos os percentuais de ok que temos, e atribuir uma parcela desse total pra cada model.
94
+ O model que tiver mais % de ok dos demais, tem mais chances de ser escolhido do que um que tem menos...
95
+
96
+ Exemplos:
97
+
98
+ Phi3 Gemini Lama
99
+ |----|--------|-----------------------------|
100
+ 10% 20% 70%
101
+
102
+ Phi3 Gemini Lama
103
+ |--------|----------------|----------------|
104
+ 20% 39.9% 40.1%
105
+
106
+ Agora, escolhe ai um número entre 0 e 100%, aleatoriamente.
107
+ Se for até 10%, pega Google...
108
+ Se for até entre 10 e 20%, vai o Lama...e acma de 20% vai a Microsoft...
109
+
110
+ Sacou a manha? Com isso, quanto mais um model nao da erro, mais ele tem a chance de ser escolhido!
111
+ Se 2 models tem o mesmo peso, vamos usar um pequeno hack na conta pra nunca dar empate e um deles sempre ter 1 pouco a mais!
112
+
113
+
114
+ O reusumo é: Imagine aquele meme da Nazaré fazendo as contas!
115
+ */
116
+ function UpdateProbs(opts){
117
+ BestModel.LastRandom = Math.random();
118
+
119
+ let AllModels = [];
120
+
121
+ // total de "oks"
122
+ let Total = ModelList.reduce( (acc,m) => acc + m.stats.pok , 0 )
123
+
124
+ // calcula parcela de ok desse model!
125
+ ModelList.forEach( m => m.stats.parcela = m.stats.pok/Total )
126
+
127
+ // Organiza pela ordem...
128
+ let SortedModels = ModelList.sort( (a,b) => {
129
+ let diff = a.stats.parcela - b.stats.parcela;
130
+
131
+ if(diff == 0)
132
+ diff = a.stats.parcela*Math.random() - b.stats.parcela*Math.random()
133
+
134
+ return diff;
135
+ })
136
+
137
+ BestModel.LastSorted = SortedModels;
138
+
139
+ let parcAcc = 0;
140
+ for(let [idx,model] of SortedModels.entries()){
141
+ let stats = model.stats;
142
+ parcAcc += stats.parcela;
143
+
144
+ if(BestModel.LastRandom <= parcAcc){
145
+ BestModel.model = model.id;
146
+ return;
147
+ }
148
+ }
149
+
150
+
151
+ return;
152
+ }
153
+
154
+ async function GetModelAnswer(model, prompt){
155
+
156
+ let StartIndex;
157
+
158
+ if(!model){
159
+ UpdateProbs();
160
+ model = BestModel.model;
161
+ }
162
+
163
+
164
+ let i = ModelList.length;
165
+ while(i--){ // pra evitar um loop infinito, vai girar no maximo o numero de models...
166
+ let ModelConfig = MODELS[model];
167
+ let MyStats = ModelConfig.stats;
168
+ console.log(MyStats);
169
+ let InferenceApi = 'https://api-inference.huggingface.co/models/' + ModelConfig.name;
170
+
171
+ let data ={
172
+ inputs: ModelConfig.prompt(prompt)
173
+ ,parameters:{
174
+ max_new_tokens: 70
175
+ ,return_full_text: false
176
+ ,temperature: 0.5
177
+ }
178
+ ,options:{
179
+ use_cache: false
180
+ ,wait_for_model: false
181
+ }
182
+ }
183
+
184
+ console.log("Falando com a IA 🤖", model, ModelConfig.name)
185
+ MyStats.total++
186
+ const response = await fetch(
187
+ InferenceApi,
188
+ {
189
+ headers: { Authorization: "Bearer "+hfToken, "content-type":"application/json" },
190
+ method: "POST",
191
+ body: JSON.stringify(data),
192
+ }
193
+ );
194
+
195
+
196
+ if(response.status != 200){
197
+ MyStats.erros++;
198
+ console.log('FAILED: Escolhendo outro...', response.status)
199
+ if(StartIndex == null)
200
+ StartIndex = ModelList.map(m => m.id).indexOf(model);
201
+
202
+ let NextIndex = StartIndex+1;
203
+
204
+ if(NextIndex >= ModelList.length)
205
+ NextIndex = 0;
206
+
207
+ if(NextIndex == StartIndex){
208
+ console.log("Fiz de tudo, mas não deu bom :(");
209
+ throw new Error('SOME_SHIT_HAPPENS');
210
+ }
211
+
212
+ model = ModelList[NextIndex].id;
213
+ console.log("Tentando com o ",model);
214
+ continue;
215
+ }
216
+
217
+ console.log("Ok, lendo o json...", response.status);
218
+ const result = await response.json();
219
+ LastWorkedModel = model;
220
+ return {
221
+ result
222
+ ,model
223
+ }
224
+ }
225
+
226
+ // se chegou aqui é pq todo mundo falhou!
227
+ throw new Error('Nenhum model respondeu! O trem tá feio ou o dev cagou em algo...')
228
+ }
229
+
230
+ async function Prompt(opts){
231
+
232
+ let error = opts.error
233
+ let tentativas = opts.tentativas
234
+ let max = opts.max
235
+ let model = opts.model
236
+
237
+ if(!max)
238
+ max = 20
239
 
240
  if(tentativas){
241
  tentativas = 'últimas tentativas:'+tentativas
 
246
  if(error <= 450)
247
  tom = `Gere mensagens com bastantes elogios, duvidando se foi realmente um humano que fez isso
248
  EXEMPLOS:
249
+ - Rapaz, acho que isso foi humanamente impossível...|fim|
250
+ - Você não está usando um script não né?|fim|
251
+ - Não é possível, tá muito baixo pra ter sido um ser humano...|fim|
252
  `
253
  else if(error <= 500)
254
+ tom = `Gere mensagens que parabenizem e elogiem o desempenho.
255
  EXEMPLOS:
256
+ - Muito, muito, mas muito bom!|fim|
257
+ - ora, ora ora, temos um Vingador da IA aqui|fim|
258
+ - Você é o pica das galáxias da IA hein!|fim|
259
  `
260
 
261
  else if(error <= 2000)
262
  tom = `Gere mensagens inspiradoras, no sentido em que está indo bem!
263
  EXEMPLOS:
264
+ - Vamos lá, dá pra melhorar, você consegue|fim|
265
+ - Não desista, continue tentando|fim|
266
  `
267
  else
268
  tom = `Gere mensagens sarcástias e engraçadas brincando com a situação. Faça piadas e zoeiras.
269
  EXEMPLOS:
270
+ - Ei, psiu, volta aqui|fim|
271
+ - Ou, não é pra aí não, volta aqui|fim|
272
+ - Você ainda tá tentando ou tá só de brincadeira mesmo?|fim|
273
+ - Ainda bem que eu não sou você hein...|fim|
274
+ - Nossa, mas esse erro tá sensacionalmente errado!|fim|
275
+ - Muito bom continue assim #sqn|fim|
276
  `
277
 
278
+ let statusErro = "Menor que "
279
+
280
  let prompt = `
281
  Um usuário está estudando Redes Neurais e IA e está aprendendo o conceito de Erro (erro quadrático médio).
282
+ Ele está fazendo um exercício onde deve conseguir gerar um erro < 499 (menor que 499).
 
 
283
 
284
  ${tom}
285
 
 
287
  Informações das tentativas:
288
 
289
  Erro atual: ${error}
290
+ ${tentativas}
291
+ Status: ${statusErro}
292
+
293
+ Gere uma mensagem para ser exibida ao usuário com base no valor do erro e status atual dele.
294
+ Use emojis nas respostas, quando apropriado!
295
+ REGRAS:
296
+ - máx ${max} palavras
297
+ - Responda como se estivesse falando diretamente com o usuário (use a segunda pessoa "você").
298
+ - encerrar com |fim|
299
+
300
+
301
  ---
302
  `
303
 
304
+ console.log("PromptLength: ", prompt.length, prompt);
305
+ let answer = await GetModelAnswer(model, prompt);
306
+ return answer.result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  }
308
 
309
  app.get('/error', async (req, res) => {
310
 
311
  let tentativas = req.query.tentativas;
312
+ let max = 20;
313
 
314
  if(tentativas && tentativas.length >= 100){
315
  res.json({error:"Tentando atacar né?"})
 
320
  tentativas = tentativas.split(",").map(Number).join(",");
321
 
322
 
323
+ resp = await Prompt({
324
+ error:req.query.error
325
+ ,tentativas
326
+ ,model:req.query.model
327
+ ,max
328
+ });
329
+
330
+ console.log("Respondido", resp);
331
 
332
+ if(!resp || !Array.isArray(resp)){
333
+ res.json({text:":("});
334
+ return;
335
+ }
336
 
337
  let gentext = resp[0].generated_text
338
 
339
  let textParts = gentext.split('|fim|');
340
+ let txtFinal = textParts[0].trim();
341
+
342
+ let estimatedChars = max*8;
343
+ if(txtFinal.length >= estimatedChars){
344
+ txtFinal = txtFinal.slice(0,estimatedChars);
345
+ }
346
 
347
  console.log("FullResp:"+gentext);
348
+ console.log("Final:"+txtFinal);
349
  res.json({text:txtFinal})
350
  })
351
 
 
353
  res.send("Working!")
354
  })
355
 
356
+ app.get('/models', async (req, res) => {
357
+ //UpdateProbs()
358
+
359
+ res.json({
360
+ BestModel
361
+ })
362
+ })
363
+
364
+ app.get('/', async (req, res) => {
365
+ res.send('JayCoach ON! Veja mais no blog IA Talking: <a href="https://iatalk.ing/tag/jay-trainer">https://iatalk.ing</a>')
366
+ })
367
+
368
  app.use(function(err, req, res, next) {
369
  console.error(err.stack);
370
  res.json({error:'Server error, admin must check logs',status:res.status})