Nesta postagem do blog, compartilharei como usar o LangChain, uma estrutura flexível para criar aplicativos orientados por IA, para extrair e gerar dados JSON estruturados com GPTs e Node.js. Fornecerei trechos de código e instruções concisas para ajudá-lo a configurar e executar o projeto.
LangChain é uma estrutura inovadora e versátil projetada para agilizar o desenvolvimento de aplicativos orientados a IA.
Com sua arquitetura modular, ele fornece um conjunto abrangente de componentes para criar modelos de prompt, conectar-se a diversas fontes de dados e interagir perfeitamente com várias ferramentas.
Ao simplificar a engenharia imediata, a integração da fonte de dados e a interação da ferramenta, o LangChain permite que os desenvolvedores se concentrem na lógica principal do aplicativo, acelerando o processo de desenvolvimento.
Disponível nas APIs Python e JavaScript, o LangChain é altamente adaptável, capacitando os desenvolvedores a aproveitar o poder do processamento de linguagem natural e da IA em várias plataformas e casos de uso.
LangChain contém ferramentas que tornam a saída estruturada (como no formato JSON) de LLMs. Vamos usá-los a nosso favor.
Presumo que você tenha uma das versões mais recentes do NodeJS. Eu usei o nó 18. Visite o site da LangChain se precisar de mais detalhes.
Primeiro, crie um novo projeto de nó, ou seja:
Crie um novo diretório para seu projeto e navegue até ele em seu terminal.
Execute npm init para inicializar um novo projeto Node.js.
Crie um arquivo index.js
.
Então, vamos instalar o LangChain e configurar as chaves API. Outras dependências estão incluídas.
npm i langchain # configure credentials (easiest) export OPENAI_API_KEY=XXX export SERPAPI_API_KEY=XXX
Isto é apenas para uso demonstrativo. Prefiro não exportar variáveis; Em vez disso, estou usando a popular biblioteca dotenv
npm.
Vamos importar as dependências necessárias sobre nosso arquivo JS.
import { z } from "zod"; import { OpenAI } from "langchain/llms/openai"; import { PromptTemplate } from "langchain/prompts"; import { StructuredOutputParser, OutputFixingParser, } from "langchain/output_parsers";
Vamos começar gerando alguns dados falsos para ver as possibilidades de análise.
Primeiro, precisamos dizer à biblioteca o que queremos obter. LangChain suporta a definição do esquema esperado usando uma biblioteca popular chamada Zod:
const parser = StructuredOutputParser.fromZodSchema( z.object({ name: z.string().describe("Human name"), surname: z.string().describe("Human surname"), age: z.number().describe("Human age"), appearance: z.string().describe("Human appearance description"), shortBio: z.string().describe("Short bio secription"), university: z.string().optional().describe("University name if attended"), gender: z.string().describe("Gender of the human"), interests: z .array(z.string()) .describe("json array of strings human interests"), }) );
Para usar este modelo, precisamos criar uma construção LangChain chamada PromptTemplate. Ele conterá instruções de formato do analisador:
const formatInstructions = parser.getFormatInstructions(); const prompt = new PromptTemplate({ template: `Generate details of a hypothetical person.\n{format_instructions} Person description: {description}`, inputVariables: ["description"], partialVariables: { format_instructions: formatInstructions }, });
Para executar a saída estruturada, chame o modelo OpenAI com a entrada:
const model = new OpenAI({ temperature: 0.5, model: "gpt-3.5-turbo" }); const input = await prompt.format({ description: "A man, living in Poland", }); const response = await model.call(input);
Aqui está o que será enviado para o modelo AI. Isso provavelmente mudará nas versões futuras do LangChain.
Generate details of a hypothetical person. You must format your output as a JSON value that adheres to a given "JSON Schema" instance. "JSON Schema" is a declarative language that allows you to annotate and validate JSON documents. For example, the example "JSON Schema" instance {{"properties": {{"foo": {{"description": "a list of test words", "type": "array", "items": {{"type": "string"}}}}}}, "required": ["foo"]}}}} would match an object with one required property, "foo". The "type" property specifies "foo" must be an "array", and the "description" property semantically describes it as "a list of test words". The items within "foo" must be strings. Thus, the object {{"foo": ["bar", "baz"]}} is a well-formatted instance of this example "JSON Schema". The object {{"properties": {{"foo": ["bar", "baz"]}}}} is not well-formatted. Your output will be parsed and type-checked according to the provided schema instance, so make sure all fields in your output match exactly! Here is the JSON Schema instance your output must adhere to: '''json {"type":"object","properties":{"name":{"type":"string","description":"Human name"},"surname":{"type":"string","description":"Human surname"},"age":{"type":"number","description":"Human age"},"appearance":{"type":"string","description":"Human appearance description"},"shortBio":{"type":"string","description":"Short bio secription"},"university":{"type":"string","description":"University name if attended"},"gender":{"type":"string","description":"Gender of the human"},"interests":{"type":"array","items":{"type":"string"},"description":"json array of strings human interests"}},"required":["name","surname","age","appearance","shortBio","gender","interests"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"} ''' Person description: A man, living in Poland.
A saída do modelo ficará assim:
{ "name": "Adam", "surname": "Kowalski", "age": 21, "appearance": "Adam is a tall and slim man with short dark hair and blue eyes.", "shortBio": "Adam is a 21 year old man from Poland. He is currently studying computer science at the University of Warsaw.", "university": "University of Warsaw", "gender": "Male", "interests": ["Computer Science", "Cooking", "Photography"] }
Como você pode ver, conseguimos exatamente o que precisávamos. Podemos gerar identidades inteiras com descrições complexas correspondentes a outras partes da persona. Se precisássemos enriquecer nosso conjunto de dados simulado, poderíamos pedir a outro modelo de IA para gerar uma foto com base na aparência.
Você pode se perguntar se o uso do LLM em um aplicativo de produção é seguro de alguma forma. Felizmente, a LangChain está focada em problemas como este. Caso a saída precise ser corrigida, use o OutputFixingParser. Ele tentará corrigir erros caso seu LLM forneça algo que não corresponda aos seus requisitos.
try { console.log(await parser.parse(response)); } catch (e) { console.error("Failed to parse bad output: ", e); const fixParser = OutputFixingParser.fromLLM( new OpenAI({ temperature: 0, model: "gpt-3.5-turbo" }), parser ); const output = await fixParser.parse(response); console.log("Fixed output: ", output); }
Para carregar e extrair dados de arquivos usando LangChain, você pode seguir estas etapas. Neste exemplo, vamos carregar o arquivo PDF. Convenientemente, o LangChain possui utilitários apenas para esse fim. Precisamos de uma dependência extra.
npm install pdf-parse
Vamos carregar uma pequena biografia de Elon Musk e extrair as informações que geramos anteriormente. Baixe o arquivo PDF aqui: google drive .
Primeiro, vamos criar um novo arquivo, por exemplo, structured-pdf.js
. Vamos começar carregando o PDF.
import { PDFLoader } from "langchain/document_loaders/fs/pdf"; const loader = new PDFLoader("./elon.pdf"); const docs = await loader.load(); console.log(docs);
Precisamos modificar o modelo de prompt para indicar extração, não geração. Também tive que modificar um prompt para corrigir o problema de renderização JSON, pois os resultados às vezes eram inconsistentes.
const prompt = new PromptTemplate({ template: "Extract information from the person description.\n{format_instructions}\nThe response should be presented in a markdown JSON codeblock.\nPerson description: {inputText}", inputVariables: ["inputText"], partialVariables: { format_instructions: formatInstructions }, });
Por fim, precisamos estender o comprimento de saída que permitimos (é um pouco mais de dados do que no caso gerado), pois o padrão é 256 tokens. Também precisamos chamar o modelo usando nosso documento carregado, não uma descrição de pessoa predeterminada.
const model = new OpenAI({ temperature: 0.5, model: "gpt-3.5-turbo", maxTokens: 2000 }); const input = await prompt.format({ inputText: docs[0].pageContent, });
Graças a essas modificações, obtemos a seguinte saída:
{ name: 'Elon', surname: 'Musk', age: 51, appearance: 'normal build, short-cropped hair, and a trimmed beard', // truncated by me shortBio: "Elon Musk, a 51-year-old male entrepreneur, inventor, and CEO, is best known for his...', gender: 'male', interests: [ 'space exploration', 'electric vehicles', 'artificial intelligence', 'sustainable energy', 'tunnel construction', 'neural interfaces', 'Mars colonization', 'hyperloop transportation' ] }
Seguindo essas etapas, extraímos dados JSON estruturados de um arquivo PDF! Essa abordagem é versátil e pode ser adaptada para se adequar ao seu caso de uso específico.
Concluindo, aproveitando LangChain, GPTs e Node.js, você pode criar aplicativos poderosos para extrair e gerar dados JSON estruturados de várias fontes.
As aplicações potenciais são vastas e, com um pouco de criatividade, você pode usar essa tecnologia para criar aplicativos e soluções inovadoras.
Você pode encontrar o código para este tutorial aqui: https://gist.github.com/horosin/5351ae4dc3eebbf181f9db212f5d3ebc
Inscreva-se no meu perfil preenchendo seu endereço de e-mail à esquerda e fique por dentro dos meus artigos!
Não se esqueça de me seguir no Twitter @ horosin e assinar o boletim informativo no meu blog para obter mais dicas e insights!
Se você não tem Twitter, também pode me seguir no LinkedIn .