Um Guia para Iniciantes no Desenvolvimento de Modelos de Linguagem Personalizáveis para Resolver Casos de Uso Simples
Autora: Rachel Martinez | Função: Desenvolvedora | Marca: AI Agents
Introdução
Bem-vindo ao nosso blog técnico, onde tornamos conceitos complexos acessíveis a todos, independentemente de sua formação. Hoje, estamos mergulhando em um projeto emocionante: desenvolver um Agente de Modelo de Linguagem Grande (LLM) que possa se adaptar a várias tarefas.
Vamos criar uma infraestrutura robusta de Recuperação, Aumento e Geração (RAG) para nos ajudar a selecionar o LLM mais adequado para cada tarefa. Empresas como a H2O e a HuggingFace já lançaram sistemas semelhantes, e recebemos interesse de startups ansiosas para integrar nossa tecnologia AI em suas aplicações.
Nosso caso de uso específico exige a capacidade de solicitar ao LLM usando uma única entrada (one-shot) ou encadeando várias solicitações. Isso exige a criação de módulos LLM personalizáveis e fáceis de usar para diversos cenários.
Fique ligado enquanto embarcamos nesta jornada, desvendando cada etapa de forma simples e envolvente.
Caso de Uso Atual
No nosso caso de uso atual, aprimoramos o conteúdo do currículo de um usuário por meio de um processo em duas etapas:
- O usuário insere as seções “Resumo Profissional” e “Experiência” de seu currículo no sistema e consulta o LLM para gerar uma versão mais refinada do texto.
- Revisão: O usuário revisa o conteúdo gerado pelo LLM e fornece instruções ou orientações adicionais para refinar e personalizar a saída, garantindo que esteja alinhada com suas habilidades e experiências únicas.
Ao seguir essa abordagem, os usuários podem aproveitar o poder do LLM para criar um currículo convincente que se destaque aos empregadores em potencial.
Alvo
Nosso objetivo é desenvolver um módulo LLM totalmente personalizável que atenda ao nosso caso de uso e automatize, pelo menos parcialmente, o processo de criação do currículo.
Implementação
Passo 1: Escolha do LLM
Ao selecionar o LLM adequado para suas necessidades, há duas categorias principais a considerar: LLMs de código aberto e LLMs proprietários. Discutiremos as opções populares de ambos os grupos, com foco nos benefícios de escolher LLMs de código aberto.
LLMs de código aberto
Mistral AI, Phi 3, LLaMa 3.
Vantagens:
- Suporte da comunidade: grandes comunidades ativas de desenvolvedores e usuários oferecem orientação, compartilham recursos e colaboram para melhorar o projeto.
- Personalização: O acesso ao código-fonte permite modificações e adaptações para atender a casos de uso específicos.
- Transparência: Compreender o funcionamento interno do modelo é crucial para aplicações com diretrizes rigorosas de ética ou privacidade.
LLMs proprietários
GPT-4.
Vantagens: Desempenho impressionante e recursos exclusivos.
Limitações:
- Falta de Personalização: Limitado a usar o modelo como está.
- Custo: As taxas baseadas no uso podem aumentar ao longo do tempo.
- Natureza Opaca: Difícil de entender as mecânicas subjacentes, o que pode ser uma preocupação para aqueles que priorizam a transparência e a explicabilidade.
Em conclusão, embora os LLMs de código aberto e os proprietários tenham suas vantagens e desvantagens, os LLMs de código aberto, como Mistral AI, Phi 3 e LLaMa 3, oferecem acessibilidade, customizabilidade e transparência que podem ser altamente benéficos para uma ampla gama de usuários.
Passo 2: Analisando os custos e as funcionalidades
Os LLMs de código aberto geralmente são econômicos, pois podem ser hospedados em seus próprios servidores ou com provedores como Azure ou AWS, utilizando um modelo de pagamento conforme o uso. Aqui está um resumo dos custos e recursos para hospedar vários modelos de linguagem (LLMs):
| LLM | Detalhes | Comprimento do contexto | Custo |
|---|---|---|---|
| Mixtral 8x7B | MoE LLM por Mistral A | Treinado: 8192 tokens | $0.7/1M tokens (chea |
| Mixtral 8x22B | Sucessor do Mixtral | Treinado: 32768 token | $2/1M tokens (disponível |
| LLaMa 3 70B | Modelo Não-MoE por Met | Treinado: 2048 tokens | $0.02/1K tokens (Azu |
| Phi 3 128K | Multimodal-SLM por mim | Treinado e Total: 3 | $0.002/1K tokens (Az |
| Turbo GPT-4 | Proprietário LLM por O | 16K padrão, maior | Não disponível no AWS |
Passo 3: Testes usando APIs públicas compatíveis com OpenRouter
Selecionar e testar o melhor LLM exige uma maneira simplificada de acessar e avaliar diferentes modelos. O OpenRouter, um padrão aberto do API, permite a alternância perfeita entre vários modelos e serviços do AI. Escolhemos a Fireworks AI como nossa provedora porque:
- Diversidade de Modelos: Oferece uma ampla variedade de modelos AI, incluindo LLMs populares de código aberto como Mistral AI, Phi 3 e LLaMa 3.
- Facilidade de integração: está em conformidade com o padrão OpenRouter, simplificando a integração na infraestrutura existente.
- Escalabilidade: Projetada para lidar com grandes volumes de solicitações e escalar sem problemas.
Aqui está uma função de exemplo para invocar respostas do modelo e os resultados de latência usando o mesmo hardware:
import json
def get_sanitized_json_response(user_input, guardrail):
final = chain.invoke({"text": f"Sanitize {user_input}. Guardrail: {guardrail}"})
final = chain.invoke({"text": final.content})
return json.loads(final.content.replace("<json>", "").replace("</json>", "").replace("\n",""))
| Modelo | Latência | Observações |
|---|---|---|
| Mixtral 8x7B | 2,1s | Modelo mais leve, perf |
| Mixtral 8x22B | 5,3s | Modelo sucessor, sim |
| LLaMa 3 70B | 2,6s | Resposta decente, mas |
| Phi 3 128K | 1.5 min | Modelo multimodal com |
Foi utilizado um guarda-roupa e uma entrada muito simples para testar o acima:
guardrail = """Format details as bullets and use the XYZ method to format the relevant detail.
For example:
- I did X boosting Y percent resulting in Z.
"""
Recebemos a seguinte resposta JSON sanitizada após sua invocação:
get_sanitized_json_response("""I served as Junior as a Software Engineer at TechCorp in Sydney in January 2011 and worked there until December 2018. During my tenure,
Liderei a equipe que desenvolveu ferramentas avançadas de análise financeira baseadas em AI para processar centenas de milhões de registros em um
ambiente distribuído e criou a versão inicial do pipeline de dados proprietário da empresa. Na minha função, fui responsável por
desenvolvendo soluções e implementando múltiplas APIs. No meu último ano gerenciando uma equipe focada em soluções de blockchain.
{'experience': [{'title': 'Engenheiro de Software',
'empresa': 'TechCorp',
'localização': 'Sydney',
'start_date': '2011-01',
'end_date': '2018-12',
'- Projetado sistemas de banco de dados escaláveis em um grande projeto que melhorou a velocidade de processamento de dados dos clientes em 40%.'
'- Liderou uma equipe focada em soluções impulsionadas por AI.',
'- Desenvolvi ferramentas de análise financeira baseadas em AI que processam mais de 100 milhões de registros em ambientes distribuídos.',
'- Criou o pipeline de dados proprietário da empresa.',
- Liderou equipe em soluções de blockchain no último ano.
In conclusion, since the response quality was fairly comparable among all these models, it came down to latency and cost. The experiment was run 3 times achieving very similar results. So we chose Mistral AI’s Mixtral 8x7B due to its favorable balance of latency and cost.
Step 4: Building an Orchestration Layer
Managing and coordinating multiple large-scale language models or a single model across various applications is crucial for optimal performance and adaptability. Instead of building from scratch using vanilla PyTorch, employing an orchestration framework is more practical and efficient. Here are three options:
Langchain
Advantages: Vast array of integrations, supports Python and JavaScript, extensive community support.
Drawbacks: Introduces an additional dependency, potential learning curve.
LlamaIndex
Advantages: Backed by Meta, offers interoperability with Langchain.
Drawbacks: Less developer-friendly syntax.
Haystack
Advantages: User-friendly syntax, supported by prominent tech corporations.
Drawbacks: Limited integrations as it’s still maturing.
Using an orchestration framework simplifies development, improves scalability, and provides access to a supportive community, making it a more favorable choice for our project.
Design and Data Flow
The following image shows the design diagram:
The data flow within our AI-driven system is an essential aspect of ensuring a seamless and efficient user experience. While the design diagram provides a visual representation of the process, a detailed explanation can help clarify the steps involved:
- User Input: The journey begins when the user enters their details, such as the “about” and “experience” sections of their resume, into the system.
- Prompt Generation: The user’s input is then processed and transformed into one or more prompts, which will be used to query the Large Language Model (LLM) for a more polished and impressive version of the text.
- LLM Integration via Langchain: The generated prompts are passed to Langchain, our chosen orchestrator framework, which facilitates the interaction with the LLM client. Langchain leverages a Pydantic schema in the form of a class to parse and validate the data using kor, ensuring that it adheres to the required format.
- JSONResponse Generation: Once the data is validated, it is converted into a final JSONResponse, a structured and easy-to-work-with data format that simplifies further processing and manipulation.
- Content Extraction and Indexing: The content part of the JSONResponse is extracted using kor and indexed by computing embeddings, which are mathematical representations of the text. These embeddings are then stored in a vector database, such as Qdrant, for efficient retrieval and comparison during subsequent queries.
- Caching for Context Module: The entire JSONResponse is cached for the context module to function correctly. This ensures that the system can maintain the context of the user’s input and the LLM’s output during follow-up queries.
- Follow-up Queries: When the user provides additional input or requests further refinement of the generated text, the cached JSONResponse is modified according to the new context and chained to the updated prompt. This modified prompt then goes through the entire process again, from LLM integration to content extraction and indexing, to provide the user with a tailored and accurate response.
By understanding the data flow within our system, we can appreciate the importance of each step and the role of the orchestrator framework in streamlining the process, ultimately resulting in an efficient and user-friendly AI-driven solution.
Construção e encadeamento de prompts usando LCEL
Este é um exemplo de uma amostra PromptTemplate:
from langchain.core.output_parsers import PydanticOutputParser
prompt = PromptTemplate(
template="Please extract the following information from the given text and format it as a JSON object according to the schema:\n\n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": output_parser.get_format_instructions()},
)
chain = prompt | chat_model | output_parser
Um modelo típico consiste em dois argumentos principais (existem outros, mas isso está fora do escopo deste blog): input_variables e template. O primeiro argumento aceita uma lista de strings que seriam injetadas no modelo de prompt em tempo de execução. Esta variável tipicamente age como as do Jinja2Template ou f-strings. O chat_model aqui seria o LLM que estamos usando e está sendo encadeado ao prompt. O operador | (pipe), semelhante ao operador | do BASH, representa uma cadeia. Esta é uma abreviação conveniente fornecida pela especificação LCEL (LangChain Expression Language). Isso nos permitiria encadear a resposta de um prompt com a entrada de outro. Também suporta chamadas de função, ou seja, é possível encadear expressões lambda ou algumas funções para tipicamente sanitizar a saída. Isso reduz a complexidade do código ao escrever cadeias em vez de funções grandes.
Passo 5: Usando VectorDBs
Bancos de dados vetoriais (VectorDBs) armazenam, gerenciam e buscam eficientemente vetores de alta dimensão, como embeddings de texto gerados por LLMs. Aqui está uma comparação das opções populares:
Qdrant
Vantagens: Alto desempenho, fácil integração, comunidade ativa.
Desvantagens: Nenhuma significativa.
Milvus
Vantagens: Múltiplas métricas de distância, ferramenta de visualização de dados.
Desvantagens: Curva de aprendizado mais acentuada.
Croma
Vantagens: Fácil de usar Python API, design modular.
Desvantagens: Relativamente novo, com suporte de comunidade menos extenso.
PGVector
Vantagens: Aproveita as capacidades do PostgreSQL, consultas baseadas em SQL.
Desvantagens: Menos eficiente para busca vetorial de alta dimensionalidade.
FAISS
Vantagens: Pesquisa de alto desempenho, suporte ao GPU.
Desvantagens: Requer integração com outros bancos de dados.
A escalabilidade, a facilidade de integração e o desenvolvimento ativo do Qdrant tornam-no uma escolha adequada para a nossa solução baseada em AI.
Aproveitando o VectorDBs como uma solução robusta de IR
Criar uma solução de Recuperação de Informação (IR) usando VectorDBs envolve:
- Pré-processamento de Texto: Limpar e pré-processar dados brutos.
- Geração de Incorporações de Texto: Converta o texto pré-processado em vetores de alta dimensão usando um LLM.
- Armazenamento de Embeddings em VectorDB: Indexação de embeddings para busca eficiente.
- Processamento de Consultas: Pré-processar e converter consultas de usuários em embeddings.
- Busca por similaridade: Realize uma busca por similaridade no VectorDB para encontrar embeddings relevantes.
- Classificação e Exibição de Resultados: Classifique as embeddings recuperadas e converta-as de volta para texto para exibição.
Ao seguir este processo e utilizar o VectorDBs, podemos construir um sistema IR eficiente e eficaz.