Cursive: Um framework para LLMs intuitivo
Salve salve!
Implementar inteligência artificial nos seus projetos hoje em dia é incrivelmente fácil, mas escalar de um protótipo na sua máquina para um produto fácil de manter e confiável é surpreendentemente complicado. E depois de criar alguns produtos e conversar com algumas empresas, percebi que os problemas enfretados são bem universais.
Cursive
Criamos uma framework que ajuda a implementar LLMs de forma muito fácil e intuitiva, com algumas coisas em mente:
✦ Extensível - Os frameworks de LLM atuais tornam depurar ou extender o comportamento de funcionalidades muito difícil e frustrante. Cursive expões hooks que habilita que você faça o que você quiser a qualquer momento do ciclo de vida de uma inferência.
✦ Compatível - A maioria das bibliotecas ou pacotes para JavaScript funcionam em um runtime ou outro. Cursive é isomórfico, e funciona em Node, Browser, Cloudflare Workers, Deno, Bun ou qualquer outro runtime.
✦ DX importa - A experiência do desenvolvedor é o fator mais importante. Muito carinho foi empregado em tornar operações complexas como contar uso e gastos ou chamar funções, em algo simples e imediatamente disponível.
✦ Universal - Use a mesma interface comum para diferentes modelos. Quando no Browser, o Cursive suporta nativamente o WindowAI.
Uso
import { useCursive } from 'cursive-gpt'
const cursive = useCursive({
openAI: {
apiKey: 'sk-xxxx'
}
})
const { answer } = await cursive.ask({
prompt: 'What is the meaning of life?',
})
Chamadas básicas
const resA = await cursive.ask({
prompt: 'Give me a good name for a gecko.',
model: 'gpt-4',
maxTokens: 16,
})
console.log(resA.answer) // Zephyr
const resB = await resA.conversation.ask({
prompt: 'How would you say it in Portuguese?'
})
console.log(resB.answer) // Zéfiro
Streaming
Normalmente, você tem que calcular a quantidade de tokens gerados ao usar streaming. Cursive te dá essa informação automaticamente!
const result = await cursive.ask({
prompt: 'Count to 10',
stream: true,
onToken(partial) {
console.log(partial.content)
}
})
console.log(result.usage.totalTokens) // 40
Chamar funções
Desde que a OpenAI passou a suportar function calling (o motor que empodera os plugins na plataforma do ChatGPT), engenheiros tem reclamado da falta de ergonomia em resolver o function call e devolver o resultado para a mesma conversa. Cursive resolve isso de forma elegante, deixando definição e código a ser executado lado a lado.
import { createFunction, useCursive, z } from 'cursive-gpt'
const cursive = useCursive({
openAI: {
apiKey: 'sk-xxxx'
}
})
const sum = createFunction({
name: 'sum',
description: 'sums two numbers',
parameters: {
a: z.number().describe('Number A'),
b: z.number().describe('Number B'),
},
async execute({ a, b }) {
return a + b
},
})
const { answer } = await cursive.ask({
prompt: 'What is the sum of 232 and 243?',
functions: [sum],
})
console.log(answer) // The sum of 232 and 243 is 475.
Se você quiser apenas gerar os argumentos para a função sem continuar a conversa, basta incluir o atributo pause: true
na sua função. Isso é muito útil para extração/geração de conteúdo estruturado.
const createCharacter = createFunction({
name: 'createCharacter',
description: 'Creates a character',
parameters: {
name: z.string().describe('The name of the character'),
age: z.number().describe('The age of the character'),
},
pause: true,
async execute({ name, age }) {
return { name, age }
},
})
const { functionResult } = await cursive.ask({
prompt: 'Create a character named John who is 23 years old.',
functions: [createCharacter],
})
console.log(functionResult) // { name: 'John', age: 23 }
Function call funciona com GPT-3.5 e GPT-4, e pela primeira vez em qualquer lugar, abstraímos essa funcionalidade para o Claude 2 e Claude Instant. Se você quiser usar function call com um modelo que suporta até 100K tokens de contexto, agora você pode :]
Hooks
cursive.on('completion:after', (result) => {
console.log(result.cost.total)
console.log(result.usage.total_tokens)
})
cursive.on('completion:error', (error) => {
console.log(error)
})
cursive.ask({
prompt: 'Can androids dream of electric sheep?',
})
// 0.0002185
// 113
Embeddings
const embedding = await cursive.embed('This should be a document.')
Robustez
Cursive toma conta de falhas em inferências pra você. Se a inferência falhar, ele tenta de novo com intervalos. Se ele exceder contexto, ele tenta com um modelo que permite uma janela de contexto maior. Tudo isso é configurável!
const cursive = useCursive({
maxRetries: 5, // 0 disables it completely
expand: {
enable: true,
defaultsTo: 'gpt-3.5-turbo-16k',
modelMapping: {
'gpt-3.5-turbo': 'gpt-3.5-turbo-16k',
'gpt-4': 'claude-2',
},
allowWindowAI: true
}
})