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