Ir para o conteúdo
DedicatedPHP Contato

Memória conversacional em PHP: como isolar o contexto entre usuários e organizações

Projete a memória de um assistente em PHP para que cada conversa respeite a identidade, a organização e as permissões vigentes, sem cruzamentos de contexto.

Diagrama conceitual de conversas separadas por usuário e organização em uma aplicação PHP

Quando um assistente responde com informações de outra pessoa ou empresa, o problema não é apenas de qualidade: pode haver uma violação de privacidade e de controle de acesso. Em uma aplicação PHP multiusuário, a memória conversacional deve ser tratada como dados com proprietário, escopo e ciclo de vida definidos. Não basta salvar mensagens e recuperá-las por um identificador de sessão.

O isolamento do contexto conversacional em aplicações PHP consiste em garantir que o material usado para gerar uma resposta pertence à conversa atual e continua autorizado. Isso inclui mensagens anteriores, resumos e quaisquer dados recuperados. A busca em documentos pode complementar o contexto, mas tem regras de acesso e objetivos distintos.

Separar memória conversacional, histórico e documentos

Separar memória conversacional, histórico e documentos — guía visual de DedicatedPHP

O histórico completo é o registro das mensagens de uma conversa. A memória, por outro lado, é o subconjunto que a aplicação decide recuperar para uma tarefa: por exemplo, os turnos mais recentes ou um resumo atualizado. Os documentos recuperados por meio de busca são outra fonte, selecionada com base em uma consulta e nas permissões dos documentos. Eles não devem ser confundidos nem armazenados como se fossem mensagens ditas pelo usuário.

Essa distinção facilita decisões verificáveis. É possível manter o histórico por motivos de auditoria ou de produto e, ao mesmo tempo, limitar a memória enviada ao modelo. Além disso, cada trecho de documento pode manter sua própria origem e seu controle de acesso. Se essas fontes forem misturadas sem identificação, fica difícil explicar quais dados influenciaram uma resposta e aplicar a política de retenção correspondente.

Definir quem é proprietário de cada conversa

Antes de projetar a recuperação, estabeleça uma identidade estável para a conversa. No mínimo, considere:

  • Conversa: identificador aleatório ou imprevisível, sem presumir que conhecê-lo concede acesso.
  • Usuário: identidade autenticada que iniciou a interação ou tem permissão para consultá-la.
  • Organização: escopo de dados ao qual ela pertence, caso a aplicação opere com várias empresas ou espaços de trabalho.
  • Permissões vigentes: autorização avaliada no momento de cada leitura, não uma cópia indefinida das permissões iniciais.

A sessão web pode ser usada para autenticar uma solicitação, mas não deveria ser a única chave de propriedade persistente. Uma pessoa pode encerrar a sessão, mudar de organização ou perder uma permissão enquanto uma conversa continua armazenada. Em cada solicitação, a aplicação deve verificar se o usuário atual pode acessar essa conversa dentro da organização ativa.

Convém definir explicitamente as mudanças de contexto. Se alguém mudar de organização, poderá continuar a conversa anterior, deverá iniciar uma nova ou poderá conservar apenas um resumo aprovado? Não há uma resposta universal: depende do produto e de seus requisitos de privacidade. A decisão deve se refletir em regras verificáveis, não em uma suposição implícita da interface.

Aplicar o escopo de acesso antes de recuperar o contexto

A autorização deve fazer parte da consulta que obtém os dados, antes de incorporá-los ao prompt. Recuperar primeiro uma coleção ampla e filtrá-la depois em PHP aumenta o risco de que um erro, um caminho alternativo ou um registro de depuração exponha conteúdo de terceiros.

Em um banco de dados relacional, a consulta pode incluir ao mesmo tempo o identificador da conversa, o usuário e a organização autorizados. Por exemplo, conceitualmente:

SELECT message_id, role, content, created_at
FROM conversation_messages
WHERE conversation_id = :conversation_id
  AND organization_id = :organization_id
  AND conversation_id IN (
      SELECT conversation_id
      FROM conversations
      WHERE owner_user_id = :user_id
         OR EXISTS (/* verificar uma concessão vigente */)
  )
ORDER BY created_at DESC
LIMIT :message_limit

O esquema real pode ser diferente, mas a propriedade importante é que o escopo de acesso restrinja os registros recuperados. Use parâmetros vinculados e uma camada de autorização consistente para as operações de leitura, gravação, exportação e exclusão. Se for usado um banco de dados vetorial ou um serviço de busca, as restrições por organização e permissões devem ser aplicadas na consulta de recuperação; não basta pedir ao modelo que ignore os resultados não autorizados.

Quando a busca documental e a memória conversacional forem combinadas, aplique primeiro a autorização correspondente a cada fonte. Mantenha metadados de procedência e evite transformar resultados documentais em memória permanente sem uma política explícita.

Evitar cruzamentos em caches, filas e componentes compartilhados

Um acesso correto ao banco de dados não garante o isolamento se outras camadas compartilharem estado. Uma chave de cache como conversation:123 pode ser insuficiente se o mesmo identificador for usado em mais de um escopo, reutilizado ou se uma configuração de cache permitir colisões. Inclua na chave os identificadores da organização e da conversa e, quando apropriado, uma versão das permissões ou dos dados. Não use conteúdo sensível como parte da chave.

Em trabalhos em segundo plano, transporte um contexto mínimo e explícito: organização, conversa, ator e finalidade do trabalho. Ao executá-lo, valide novamente se a tarefa ainda tem autorização e se não está usando uma identidade obtida de um estado global compartilhado. Evite variáveis estáticas, serviços singleton com dados de usuário mutáveis e objetos de sessão reutilizados entre solicitações, especialmente em processos PHP persistentes.

Defina também o que acontece em caso de erros e novas tentativas. Um trabalho repetido não deveria mudar de organização por causa do estado de outro processo, e uma resposta armazenada em cache não deveria permanecer após uma revogação se a política exigir sua invalidação. O comportamento deve ser deliberado e observável.

Limitar a memória ao necessário para a tarefa

Isolar não significa enviar todo o histórico ao modelo. Recupere os turnos recentes ou um resumo que agregue valor à solicitação atual, com limites de quantidade e tamanho. Considere a atualidade: preferências antigas, dados corrigidos e decisões revogadas não deveriam ser tratados automaticamente como fatos atuais.

Se forem usados resumos, armazene seu escopo e procedência e atualize-os segundo regras claras. Um resumo não é uma fonte de verdade nem substitui a verificação de permissões. Para dados críticos, consulte o sistema de registro autorizado em vez de confiar em uma afirmação salva em uma conversa anterior. Uma janela de contexto pequena reduz a exposição e o custo, mas não compensa uma autorização incorreta.

Testar se uma conversa não influencia outra

Os testes devem cobrir tanto os acessos permitidos quanto os negados. Crie casos com usuários e organizações diferentes e verifique se uma solicitação não recupera mensagens, resumos nem documentos de outra identidade. Inclua situações-limite:

  • Um usuário muda de organização e tenta abrir novamente um identificador de conversa antigo.
  • Uma permissão é revogada depois da criação da conversa, mas antes da recuperação da memória.
  • Dois usuários fazem consultas simultâneas e compartilham processos, cache ou infraestrutura de filas.
  • Um identificador inexistente ou pertencente a outra pessoa gera uma resposta controlada, sem revelar se pertence a alguém.
  • Uma tarefa é repetida após uma mudança de permissões ou de organização.

Além dos testes unitários, teste o fluxo completo, da solicitação autenticada à construção do contexto. Você pode inserir mensagens marcadoras em conversas separadas e verificar se o resultado recuperado para cada uma nunca contém o marcador da outra. O objetivo é testar a fronteira dos dados, não avaliar se o modelo redige uma resposta convincente.

Investigar incidentes sem registrar conteúdo sensível

Investigar incidentes sem registrar conteúdo sensível — guía visual de DedicatedPHP

A observabilidade deve permitir acompanhar o fluxo sem copiar mensagens privadas para os logs. Registre identificadores técnicos adequados, a decisão de autorização, o número de itens recuperados, a origem dos dados, a duração e o resultado de cada etapa. Use identificadores pseudônimos quando possível e restrinja o acesso e a retenção dos registros.

Sinais como uma recuperação inesperadamente vazia, uma organização divergente, uma taxa incomum de negações ou uma chave de cache reutilizada fora do próprio escopo ajudam a detectar falhas. Evite registrar prompts completos, documentos ou respostas por padrão. Se for necessário um diagnóstico detalhado, estabeleça um procedimento temporário, autorizado e limitado, com redação dos dados sensíveis.

Um projeto seguro explicita o proprietário, o escopo e a atualidade de cada trecho de contexto. Aplicar essas regras nas consultas, nos caches e nos trabalhos assíncronos, e verificar os casos negativos, transforma o isolamento em uma propriedade verificável da aplicação PHP, e não em uma expectativa depositada no assistente.

Deseja aplicar essas ideias ao seu projeto?Vamos discutir sua plataforma PHP.
Veja os serviços relacionados