Ir para o conteúdo

Crie um chat LLM de múltiplas interações com histórico de conversação no Jitterbit Studio

Introdução

Uma conversa de múltiplas interações requer mais do que enviar uma única mensagem de usuário para um LLM: o modelo precisa do histórico completo da troca para responder de forma coerente a perguntas de acompanhamento e manter o contexto entre as interações. Este guia cobre o padrão de baixo nível para construir e persistir um array de histórico de conversação no Studio, usando o Cloud Datastore como o armazenamento de sessão e SumCSV para acumular mensagens entre execuções.

Este guia é distinto do Como construir um agente de IA contextual, que cobre a arquitetura geral do agente. O foco aqui está nos padrões de script e transformação que constroem o array messages: como formatar cada mensagem como uma linha CSV, como persistir e recuperar o histórico completo entre execuções de operação e como lidar com campos opcionais como tool_call_id ao combinar o histórico de conversação com chamadas de função.

Este guia se baseia em:

Nota

Este guia gerencia o histórico de conversação explicitamente, que é o que você precisa ao chamar o LLM através do conector HTTP v2. Se você enviar prompts através de um conector LLM nativo em vez disso, o conector pode reter o contexto do chat para você: os conectores OpenAI, Azure OpenAI e Amazon Bedrock têm uma configuração de Armazenar contexto de chat entre operações que mantém o histórico entre operações que compartilham o mesmo chatId em grupos de agentes na nuvem, e agentes privados retêm o contexto do chat na memória automaticamente.

Padrão de design

O padrão de histórico de conversação adiciona duas etapas em torno de uma chamada padrão de LLM: uma etapa de recuperação de histórico antes da solicitação e uma etapa de atualização de histórico após a resposta.

flowchart LR A["Consulta Cloud Datastore
Recuperar histórico por chave de sessão"] --> B["Script
Construir mensagens CSV"] --> C["Transformação
Converter CSV em JSON
chamar LLM"] --> D["Script
Anexar usuário + assistente
Atualizar CDS"]

Cada mensagem do usuário e resposta do assistente é armazenada no Cloud Datastore como uma linha em uma string CSV, identificada por um identificador de sessão (tipicamente um ID de canal do Slack ou ID de usuário). Antes de cada chamada ao LLM, o histórico completo é recuperado e montado no array messages. Após a resposta do LLM, a mensagem atual do usuário e a resposta do assistente são ambas anexadas ao histórico, e a string atualizada é gravada de volta no Cloud Datastore.

Parte 1: Configurar o armazenamento do Cloud Datastore

Crie um armazenamento de chave com um campo ConversationHistory para manter a string de histórico CSV para cada sessão. Siga Armazenar e recuperar o estado da sessão usando o Cloud Datastore para as etapas completas de configuração. Para adicionar campos, no portal Harmony, navegue até Menu do portal Harmony > Console de Gerenciamento > Cloud Datastore, abra o armazenamento de chave e adicione um campo chamado ConversationHistory com o tipo Texto Grande. Os campos embutidos Key, Alternative Key e Value estão sempre presentes e não precisam ser adicionados.

Nota

Campos de Texto Grande suportam até 25.000 bytes por item. Para conversas de longa duração, implemente uma estratégia de truncamento: mantenha apenas as N trocas mais recentes antes de gravar de volta no Cloud Datastore, ou resuma turnos anteriores usando o próprio LLM antes de armazenar.

Parte 2: Recuperar histórico e construir o array de mensagens

Recuperar o histórico

A primeira etapa na operação consulta o Cloud Datastore pelo registro da sessão, usando o identificador da sessão (por exemplo, um ID de canal do Slack) como filtro de chave. Após a atividade de Consulta de Itens, leia o resultado em uma etapa de script:

<trans>
$historyMessages = "";
if(Source.json.pagination.totalItems > 0,
    $historyMessages = Source.json.items.item[0].ConversationHistory
);
</trans>

Isso define historyMessages como a string CSV armazenada, ou como uma string vazia se esta for a primeira interação na sessão.

Construir o array de mensagens

No próximo passo do script, monte o array completo de mensagens como uma string CSV usando SumCSV. Cada chamada a SumCSV produz uma linha CSV a partir de um array de valores de campo:

<trans>
// System message (always first, not stored in history)
message = Array();
message[0] = "system";
message[1] = $systemPrompt;
$messages = SumCSV(message);

// Append stored conversation history (all prior user/assistant pairs)
if(length(trim($historyMessages)) > 0,
    $messages = $messages + "\n" + $historyMessages
);

// Append the current user message
message[0] = "user";
message[1] = $userInput;
$messages = $messages + "\n" + SumCSV(message);
</trans>

messages agora contém uma string CSV com uma linha por mensagem. A mensagem do sistema é sempre a primeira; o histórico armazenado segue na ordem em que foi acumulado; a mensagem do usuário atual é a última.

Dica

Armazene a chave da sessão em uma variável global antes desta operação para que a atualização do Cloud Datastore em Parte 4 use a mesma chave.

Parte 3: Converter o array de mensagens para JSON e chamar o LLM

Configurar o esquema de origem da transformação

Adicione uma transformação à operação e defina seus dados de origem como a variável messages, analisada como CSV. Defina um esquema de origem CSV de duas colunas:

  • role (string)
  • content (string)

Mapear o array de mensagens para a solicitação do LLM

Mapeie as colunas CSV para o corpo da solicitação de Completions do OpenAI Chat. O caminho de destino para cada entrada de mensagem é json/messages/item:

  • json/messages/item/role → coluna de origem role
  • json/messages/item/content → coluna de origem content

Se a operação também adicionar resultados de chamadas de ferramentas ao histórico (para uso com o padrão de loop de chamadas de ferramentas), o CSV pode incluir colunas adicionais. Use Unmap no script do campo de destino para omitir o campo quando a coluna estiver vazia, em vez de enviar um valor nulo ou uma string vazia:

// No script de destino para json/messages/item/tool_call_id
if(length(trim(tool_call_id)) == 0, Unmap(), tool_call_id)

Aplique o mesmo padrão ao name se incluir uma coluna tool_name:

// No script de destino para json/messages/item/name
if(length(trim(tool_name)) == 0, Unmap(), tool_name)

Isso garante que o campo esteja ausente do objeto JSON serializado quando vazio. A API do OpenAI requer que tool_call_id e name estejam ausentes (não nulos ou vazios) para mensagens padrão de user e assistant.

Conectar ao endpoint LLM

Coloque a atividade HTTP v2 POST direcionando para o endpoint de Conclusões de Chat do OpenAI após a transformação. Para configuração de conexão e autenticação, veja Usar OpenAI para processar dados em uma operação de Estúdio.

Parte 4: Anexar a resposta e atualizar o Cloud Datastore

Após a chamada LLM, um passo de script extrai a resposta do assistente, anexa tanto a mensagem do usuário quanto a resposta do assistente ao histórico armazenado e grava a string atualizada de volta no Cloud Datastore.

Construir a string de histórico atualizada

<trans>
// Extract the assistant response
$assistantReply = TrimChars(GetJSONString($jitterbit.response, "/choices/0/message/content"), "\"");

// Build the two new rows to append
userMessage = Array();
userMessage[0] = "user";
userMessage[1] = $userInput;

assistantMessage = Array();
assistantMessage[0] = "assistant";
assistantMessage[1] = $assistantReply;

newExchange = SumCSV(userMessage) + "\n" + SumCSV(assistantMessage);

// Combine prior history with the new exchange
$updatedHistory = trim($historyMessages);
if(length($updatedHistory) > 0,
    $updatedHistory = $updatedHistory + "\n"
);
$updatedHistory = $updatedHistory + newExchange;
</trans>

updatedHistory contém todas as trocas anteriores mais a mensagem atual do usuário e a resposta do assistente. A mensagem do sistema não está incluída: ela é adicionada dinamicamente no início de cada turno na Parte 2 e não precisa ser armazenada.

Escrever o histórico atualizado no Cloud Datastore

Use o padrão de consulta-inserção-atualização de Armazenar e recuperar o estado da sessão usando o Cloud Datastore para gravar updatedHistory no campo ConversationHistory, indexado pelo mesmo identificador de sessão usado na Parte 2.

Nota

A atividade Atualizar Itens corresponde ao registro a ser atualizado pelo seu campo Key. Se o resultado da Consulta da Parte 2 retornou totalItems = 0, a operação de Inserção deve ser executada em vez disso. Estruture a cadeia pós-atualização para corresponder ao padrão no guia do Cloud Datastore.

Abordagem alternativa: GetInstance()

A função GetInstance fornece uma maneira alternativa de atribuir papéis às mensagens quando as mensagens já estão armazenadas como um array estruturado (por exemplo, recuperadas de um array JSON ou de uma tabela de banco de dados com uma linha por mensagem). Em uma transformação que itera sobre instâncias de mensagens, use TargetInstanceCount para obter o índice da linha atual e atribuir papéis com base na posição par/impar:

<trans>
// Assign alternating user/assistant roles based on row position (1-based)
$role = if(TargetInstanceCount() % 2 == 1, "user", "assistant");
</trans>

Mapeie role para json/messages/item/role. Essa abordagem funciona quando todas as falas estão armazenadas com seus valores de conteúdo em ordem cronológica e a atribuição de papéis pode ser derivada apenas da posição. Não suporta uma mensagem de sistema como uma entrada distinta ou metadados de papel por mensagem.

A abordagem SumCSV na Parte 2 é mais flexível para o padrão de agente conversacional: suporta uma mensagem de sistema explícita, permite qualquer papel por linha e armazena todo o histórico como um único campo no Cloud Datastore, sem exigir um esquema separado de linha por mensagem.

Verifique a integração

  1. Implante e execute a operação com uma chave de sessão que ainda não existe no armazenamento. Forneça uma mensagem inicial do usuário.

  2. Nos logs da operação, confirme que o resultado da Consulta mostra totalItems = 0 e que a operação de Inserção foi executada para criar o registro da sessão.

  3. No Console de Gerenciamento > Cloud Datastore, abra o armazenamento e confirme que um registro com a chave esperada existe e que ConversationHistory contém uma linha do usuário e uma linha do assistente.

  4. Execute a operação novamente com a mesma chave de sessão e uma pergunta de acompanhamento que se refere à primeira troca.

  5. Confirme que a resposta do LLM reflete o contexto anterior. No Cloud Datastore, confirme que ConversationHistory agora contém dois pares de usuário/assistente.

  6. Se a resposta do LLM ignorar o contexto anterior, use WriteToOperationLog para registrar messages antes da transformação e confirme que as interações anteriores aparecem na string CSV.

  7. Se a transformação gerar um erro de incompatibilidade de esquema, confirme que a contagem de colunas do esquema de origem CSV corresponde ao número de valores passados para cada chamada de SumCSV. Todas as linhas devem ter o mesmo número de colunas.