Este artigo é baseado no discurso "Kitex Thrift Streaming Implemented in AI Scenarios" de Du Shaofeng, engenheiro de P&D da ByteDance-Flow, no evento "Cloud Native✖️Microservice Architecture and Technical Practice in the AI Era" CloudWeGo Technology Salon Beijing, evento realizado em Pequim em 30 de março de 2024. Compilado de "Prática".
Visão geral
A plataforma ByteDance Prompt tem como objetivo fornecer aos usuários funções abrangentes de desenvolvimento, ajuste, avaliação e ciclo de vida completo do Prompt. Entre esses recursos, o streaming de resultados de modelos grandes para efeitos de máquina de escrever é um recurso crucial. Embora a implementação baseada em SSE (Server-Sent Events) seja viável, ela requer escrita adicional de serviços HTTP, o que aumenta a complexidade do desenvolvimento. Embora o método de votação seja simples, a experiência do usuário não é ideal e parece muito desajeitada. Quanto ao gRPC, embora seu desempenho seja excelente, pode apresentar problemas de compatibilidade, complicando a implantação e a manutenção. Portanto, implementamos com sucesso a interface de streaming com a ajuda do recurso de streaming Thrift da Kitex, proporcionando aos usuários uma experiência de saída de resultados de modelo grande com efeito de máquina de escrever suave e eficiente.
1. Histórico empresarial
Com o desenvolvimento contínuo da tecnologia de IA, a vida das pessoas está passando por mudanças profundas. Tomemos como exemplo o produto de IA da Byte, Doubao. Os agentes nele trouxeram muitas experiências novas para as pessoas. Entre eles, robôs inteligentes interessantes, como o namorado AI e a namorada AI, são particularmente populares. Eles não só podem interagir com os usuários de maneira humorística, mas também mostrar um lado gentil e atencioso.
Tudo isso é indissociável de um conceito intimamente relacionado aos grandes modelos - os prompts. Simplificando, Prompt é a entrada de texto para o modelo pré-treinado para orientar o modelo a gerar uma saída de texto que atenda a necessidades específicas. Em termos figurados, o Prompt é como criar um sonho exclusivo para o grande modelo. Por meio dele, podemos orientar o grande modelo para dar respostas mais adequadas e direcionadas em cenários específicos.
Tomando a namorada IA como exemplo, diremos à grande modelo, por meio de instruções cuidadosamente elaboradas, que seu papel é uma namorada virtual gentil e atenciosa. Ao mesmo tempo, também estabeleceremos algumas restrições, como exigir que ele se comunique com os usuários de forma gentil e atenciosa, e que tenha habilidades como escuta, compreensão, incentivo e sugestões. Além disso, também descreveremos seu fluxo de trabalho em detalhes, como orientar os usuários a dizerem seus nomes ao cumprimentar, dar aos usuários um apelido adequado e, em seguida, conduzir uma comunicação aprofundada com os usuários e fornecer sugestões úteis.
Por meio desses prompts, construímos um “sonho” completo para o modelo grande, permitindo que ele entenda que se trata de uma namorada de IA e como deve interagir com os usuários. Quando este prompt for ativado, quando tivermos uma sessão de perguntas e respostas com o modelo grande, ele dará respostas correspondentes com base em nossos prompts. Por exemplo, quando lhe dizemos olá, ele nos orienta a dizer nosso nome, nos dá um apelido fofo e depois nos dá incentivo e alívio.
Como pode ser visto neste exemplo, o Prompt desempenha um papel decisivo na saída de grandes modelos em cenários específicos. Além disso, também afetará o consumo de tokens e o tempo de resposta de grandes modelos durante o processo de saída. Portanto, um excelente Prompt é crucial para melhorar o resultado do modelo.
2. Cenários de demanda
A equipe ByteDance Flow está trabalhando para construir uma plataforma/método abrangente e maduro projetado para ajudar os desenvolvedores de prompt a projetar, iterar, avaliar e otimizar seus prompts, aumentando assim a expressividade do LLM (modelo de linguagem grande). Durante a fase de desenvolvimento, planejamos fornecer geração estruturada e geração guiada para ajudar os usuários a escrever prompts eficientes e precisos e a depurar adequadamente.
À medida que o desenvolvimento avança, introduziremos ainda mais tecnologias de ajuste automático, como COT (Chain of Thought) e Few shots, bem como o método APO (Auto Prompt Optimization) para ajudar o Prompt a melhorar a precisão de suas respostas. Ao mesmo tempo, também forneceremos a capacidade de expandir prompts para otimizar a eficiência de grandes modelos no consumo de tokens.
Além disso, para avaliar de forma abrangente a eficácia do Prompt, pontuaremos o Prompt com base em diversos conjuntos de dados e realizaremos análises aprofundadas de seus gargalos de desempenho para fazer melhorias direcionadas. Eventualmente, forneceremos recursos de implantação com um clique, permitindo que os desenvolvedores integrem facilmente os recursos do Prompt e os grandes modelos por trás deles em seus aplicativos.
Claro, a realização destas funções é inseparável do suporte da tecnologia
de streaming em tempo real
. Assim como os recursos de IA que você experimentou, como pesquisa GPT, Doubao e Baidu AI, todos eles usam respostas no estilo de máquina de escrever depois que os usuários fazem perguntas, permitindo que os usuários sintam que os dados estão fluindo constantemente na tela, melhorando assim a fluência de bate-papo e velocidade de resposta. Essa tecnologia
de streaming em tempo real
é o recurso mais básico que nossa plataforma Prompt precisa oferecer. Ao dividir os dados em vários fluxos de dados para transmissão em rede, podemos reduzir efetivamente a latência da rede, melhorar o desempenho e garantir que os usuários tenham uma experiência melhor ao interagir com grandes modelos de linguagem.
3. Solução
Para implementar a função de saída de streaming, conduzimos uma pesquisa aprofundada e consideramos uma variedade de opções:
-
votação
-
SSE HTTP
-
Streaming Kitex gRPC (protobuf)
-
Streaming de Kitex Thrift
Primeiro, o esquema eleitoral foi excluído devido à sua natureza inflexível e não atendeu às nossas necessidades. Em segundo lugar, embora o SSE baseado em HTTP seja uma solução viável, considerando que também temos requisitos rigorosos para RPC (chamada de procedimento remoto), também precisamos encontrar uma solução mais adequada. Além disso, descobrimos que o suporte de streaming do protocolo Protobuf não atendia totalmente às nossas necessidades, especialmente em termos da interface Thrift. Finalmente, notamos o suporte do Kitex para Thrift Streaming. Naquela época, o Kitex Thrift Streaming estava em fase de desenvolvimento e decidimos nos tornar seus primeiros usuários e construir a estrutura básica de toda a plataforma Prompt baseada nele.
Em termos de projeto de arquitetura, primeiro comparamos LangChain e estabelecemos serviços de engenharia LLM. Com base nisso, construímos ainda mais o serviço Prompt para fornecer os recursos mais básicos de gerenciamento e aplicativo do Prompt. Para interagir com o front-end, disponibilizamos uma interface HTTP através do API Gateway. Em termos de comunicação entre microsserviços, usamos a estrutura Kitex para fornecer suporte para interfaces de streaming e interfaces não-streaming para garantir transmissão e processamento eficiente de dados.
Através desta solução, implementamos com sucesso a função de saída de streaming, proporcionando aos usuários uma experiência de interação de IA mais suave e eficiente. Ao mesmo tempo, também estabelecemos uma base sólida para expansão e otimização futuras.
4. Prática e armadilhas
-
Processo de chamada de streaming
O processo de chamada de streaming começa quando o usuário inicia uma pergunta. Essa solicitação é enviada primeiro ao gateway, que então estabelece uma conexão com a interface Prompt RPC downstream. A interface Prompt RPC estabelece ainda a comunicação com o serviço de engenharia LLM, que é responsável por interagir continuamente com o modelo e obter os resultados de saída do modelo. Esses resultados são transmitidos para cima, camada por camada, em streaming, até chegarem à camada de gateway e, finalmente, são exibidos ao usuário em streaming.
Durante esse processo, escrevemos uma interface de streaming no serviço Prompt para lidar com chamadas de streaming. A interface primeiro estabelece uma conexão com o downstream chamando a interface downstream e, em seguida, recebe continuamente o resultado do pacote de streaming enviado para nós pelo downstream por meio de um loop for. Assim que o pacote de dados é recebido, nós o transmitimos de forma transparente para a camada superior por meio do método send até que um erro seja encontrado ou o fluxo seja fechado e o ciclo termine.
Durante o processo de implementação, experimentamos a simplicidade do Kitex Thrift Streaming. No entanto, também encontramos alguns problemas. Principalmente em termos de tratamento de erros, descobrimos que o código não conseguia obter os resultados esperados durante a execução e até fazia com que a carga da CPU fosse muito alta.
Após uma análise mais aprofundada dos logs de erros, descobrimos que havia mensagens de erro em solicitações individuais, especificamente em relação ao problema de limite de QPM (Consulta por Segundo) para o primeiro pacote. De acordo com nossa lógica de código, devemos sair do loop for rapidamente ao encontrar tais erros, mas esta não é a situação real. Portanto, começamos a usar os métodos de solução de problemas fornecidos pela Kitex para localizar o problema. Kitex fornece pontos de enterramento para RPCStart e RPCEnd, bem como pontos de enterramento mais refinados para eventos de recebimento e envio de pacotes. Através da análise desses pontos ocultos, descobrimos que Kitex reconheceu toda a solicitação como uma resposta normal e um grande número de pacotes de dados foi enviado no link de chamada. Uma verificação mais aprofundada das informações de gestão de uma única embalagem também mostra que esta é reconhecida como uma resposta normal pela Kitex.
Após julgamento preliminar, acreditamos que erros de negócios podem ter sido ignorados no processamento de streaming da Kitex, resultando na não identificação correta dos erros. Depois de se comunicar com a equipe da Kitex, eles fizeram os ajustes correspondentes, como adicionar reconhecimento de erros de status de negócios (erros de status de negócios) ao código.
Com base nessa experiência de tratamento de erros, analisamos ainda outros cenários anormais que podem ser encontrados em chamadas de streaming, como erros de permissão na fase de estabelecimento da conexão, saturação de TPM/QPM na primeira fase do pacote, tempo limite do stream e conteúdo na fase intermediária do pacote. Rever erros, etc. Nós nos concentramos no desempenho do tratamento de erros do Kitex Thrift Streaming nesses cenários, como se ele pode retornar rapidamente informações de erro ao estabelecer uma conexão e se pode interromper rapidamente a espera do fluxo quando o primeiro pacote e os pacotes intermediários retornam erros. Após ajustes e testes conjuntos com a equipe Kitex, o tratamento de erros nesses cenários finalmente atendeu às expectativas.
-
Em termos de governança de serviço
Em termos de governança de serviço, prestamos especial atenção aos dois aspectos principais do tempo limite e da limitação de corrente.
Primeiro, o gerenciamento do tempo limite é crucial. Como nossos módulos interagem com modelos grandes, essa interação pode envolver tempos de resposta da ordem de segundos ou até minutos. Portanto, definimos limites de tempo limite em nível de minuto para processamento de fluxo tanto na camada HTTP quanto na camada RPC. Isso pode evitar o bloqueio do serviço causado pela impossibilidade de sair do loop for e garantir a estabilidade e disponibilidade do serviço.
Em termos de limitação de corrente, embora o Kitex suporte a limitação de corrente ao criar um fluxo, para o cenário LLM, nosso foco não está apenas na limitação de corrente QPM ao estabelecer uma conexão, mas também na limitação de corrente do consumo de token de modelo grande. O processo de inferência de grandes modelos gerará uma grande quantidade de consumo de tokens, o que pode levar ao esgotamento de recursos e falhas de serviços se não for restringido. Portanto, usamos o Kitex para implementar o limite atual de Jianlian e, ao mesmo tempo, usamos nossos próprios componentes distribuídos para calcular o consumo de token em diferentes modelos e implementar o limite atual no nível do token de acordo. Isso pode controlar efetivamente o uso de recursos e evitar a sobrecarga do serviço.
Porém, também temos expectativas para a Kitex. Esperamos que o Kitex possa fornecer recursos personalizados de limitação de corrente na granularidade de pacotes no futuro. Desta forma, podemos definir as regras de limitação atuais de forma mais flexível e controlar a utilização de recursos com mais precisão, melhorando ainda mais a estabilidade e o desempenho do serviço.
5. Expectativas futuras
Com o desenvolvimento e a aplicação contínuos da tecnologia de IA, temos maiores expectativas em relação aos recursos das estruturas de microsserviços em cenários de IA. Especialmente em termos de conveniência, capacidades em cenários de IA e adaptação das capacidades da estrutura tradicional, esperamos ver mais inovação e progresso.
-
Conveniência
Em primeiro lugar, em termos de conveniência,
esperamos que a estrutura de microsserviços suporte o acesso a mais ferramentas de teste
, especialmente para testes de interfaces de streaming. Atualmente, ainda existem certas limitações no teste da interface de streaming Kitex Thrift, que depende principalmente da gravação de interfaces sem streaming para empacotar chamadas. No futuro, esperamos tornar a interface de streaming mais conveniente para suportar várias ferramentas de teste e melhorar a eficiência do desenvolvimento por meio de chamadas generalizadas e outros métodos.
-
Habilidade em cenários de IA
Com o desenvolvimento vigoroso da tecnologia de IA, cada vez mais produtos estão começando a incorporar recursos de IA para otimizar a experiência e as funções do usuário. No cenário de IA, temos maiores expectativas para estruturas de microsserviços como o Kitex, esperando que ele possa apoiar melhor a integração e orquestração de componentes de IA e se adaptar aos recursos de estruturas tradicionais.
-
Recursos de orquestração de componentes de IA prontos para uso
Nas práticas de desenvolvimento atuais, quando os recursos de IA precisam ser integrados, os desenvolvedores geralmente precisam lidar com lógicas complexas, como chamar prompts, analisar grandes resultados de modelos e converter resultados em linguagem de máquina. Isto não só aumenta a dificuldade de desenvolvimento, mas também reduz a eficiência do desenvolvimento. Portanto, esperamos que a estrutura Kitex forneça recursos prontos para uso de orquestração de componentes de IA.
Especificamente, esperamos que a estrutura pré-instale uma série de componentes de IA encapsulados, como componentes de prompt, componentes de modelo grande, componentes de análise de resultados e componentes de chamada RPC. Esses componentes devem ser altamente configuráveis e extensíveis para que possam ser adaptados às diferentes necessidades do negócio. Os desenvolvedores só precisam passar a lógica de negócios para esses componentes sem se preocupar com os detalhes de implementação dentro dos componentes, para que possam se concentrar mais na implementação da lógica de negócios.
-
Capacidades flexíveis de orquestração de componentes de IA
Além de fornecer componentes de IA predefinidos, também esperamos que a estrutura Kitex suporte recursos flexíveis de orquestração de componentes de IA. Isso significa que a estrutura deve fornecer uma linguagem de expressão ou ferramenta de visualização que permita aos desenvolvedores orquestrar facilmente esses componentes de IA de acordo com as necessidades do negócio. Desta forma, os desenvolvedores podem definir a ordem de execução, métodos de comunicação, estratégias de processamento paralelo, etc. entre componentes sem entrar nos detalhes das interações entre os componentes. Isto melhorará muito a eficiência do desenvolvimento e a capacidade de manutenção das aplicações de IA.
-
Os recursos da estrutura tradicional são adaptados em links LLM
Em cenários de IA, as capacidades da estrutura tradicional, como governança de serviços, transmissão transparente de metadados e observabilidade, ainda são de grande importância
. Portanto, esperamos que o framework Kitex seja capaz de se adaptar e otimizar nesses aspectos.
Primeiro, em termos de governança de serviços, uma vez que as aplicações de IA podem envolver processos de inferência de longo prazo, a estrutura precisa fornecer tempo limite e estratégias atuais de limitação para tempos de resposta da ordem de segundos ou até minutos. Ao mesmo tempo, você também precisa considerar como lidar com exceções relacionadas aos componentes de IA.
Em segundo lugar, em termos de transmissão transparente de metadados, esperamos que o quadro apoie a transmissão de metadados entre componentes de IA para monitorização e depuração mais refinadas. Isso nos ajudará a entender melhor o status operacional dos aplicativos de IA e a localizar problemas rapidamente.
Finalmente, em termos de observabilidade, esperamos que a estrutura Kitex forneça funções abrangentes de registro, rastreamento e coleta de indicadores para monitoramento e análise abrangentes de links de IA. Isso nos ajudará a descobrir potenciais gargalos de desempenho e pontos de otimização no tempo, melhorando assim o desempenho e a estabilidade dos aplicativos de IA.
Resumindo, nossas expectativas futuras para a estrutura Kitex em cenários de IA estão focadas principalmente em
recursos prontos para uso de orquestração de componentes de IA
,
recursos flexíveis de orquestração de componentes de IA
e adaptação de
recursos de estrutura tradicional em
links
LLM
. Acreditamos que com o avanço contínuo da tecnologia e a profunda cooperação da equipe, essas expectativas gradualmente se tornarão realidade, trazendo maior comodidade e eficiência ao desenvolvimento de aplicações de IA.
Na verdade, nossa equipe conduziu uma cooperação profunda com a equipe Kitex para discutir como oferecer melhor suporte a cenários de IA na estrutura de microsserviços. Acreditamos que, num futuro próximo, seremos capazes de lançar uma versão MVP da solução para fornecer aos desenvolvedores de negócios uma estrutura que possa ser integrada de maneira fácil e perfeita com os recursos de IA. Será um momento emocionante e estamos ansiosos por isso.
{{o.nome}}
{{m.nome}}