Spaces:
Running
Running
Suporte a mais modelos e outros ajustes
Browse files
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
---
|
69 |
`
|
70 |
|
71 |
-
console.log(prompt.length, prompt);
|
72 |
-
|
73 |
-
|
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(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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})
|