Files
simbarag/blueprints/conversation/models.py
T
ryan 395c97958f Fix history roles and persist tool results for cross-turn context
Two fixes for the agent losing track of conversation context:

- History replay compared msg.speaker (a Speaker enum) to the string
  "user", which is always false, so every prior message — including the
  user's — was sent to the LLM with role "assistant". Compare against
  Speaker.USER instead. Affected web, iMessage, WhatsApp, and email.

- Tool outputs (web searches, RAG chunks) were discarded after each
  turn, so follow-up questions about fetched content had nothing to
  reference. Persist them as speaker="tool" messages (capped at 4000
  chars) and replay them in history as assistant context. The
  conversation GET endpoint serves only their header line so the UI
  tool pill stays compact.

Also bumps the replayed history window from 10 to 20 messages since
tool messages now share it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-12 15:43:02 -04:00

69 lines
2.0 KiB
Python

import enum
from tortoise import fields
from tortoise.contrib.pydantic import (
pydantic_model_creator,
pydantic_queryset_creator,
)
from tortoise.models import Model
class Speaker(enum.Enum):
USER = "user"
SIMBA = "simba"
TOOL = "tool"
class Conversation(Model):
id = fields.UUIDField(primary_key=True)
name = fields.CharField(max_length=255)
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
user: fields.ForeignKeyRelation = fields.ForeignKeyField(
"models.User", related_name="conversations", null=True
)
channel = fields.CharField(max_length=20, default="web", null=True)
class Meta:
table = "conversations"
class ConversationMessage(Model):
id = fields.UUIDField(primary_key=True)
text = fields.TextField()
conversation = fields.ForeignKeyField(
"models.Conversation", related_name="messages"
)
created_at = fields.DatetimeField(auto_now_add=True)
speaker = fields.CharEnumField(enum_type=Speaker, max_length=10)
image_key = fields.CharField(max_length=512, null=True, default=None)
class Meta:
table = "conversation_messages"
class UserMemory(Model):
id = fields.UUIDField(primary_key=True)
user = fields.ForeignKeyField("models.User", related_name="memories")
content = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
class Meta:
table = "user_memories"
PydConversationMessage = pydantic_model_creator(ConversationMessage)
PydConversation = pydantic_model_creator(
Conversation, name="Conversation", allow_cycles=True, exclude=("user",)
)
PydConversationWithMessages = pydantic_model_creator(
Conversation,
name="ConversationWithMessages",
allow_cycles=True,
exclude=("user",),
include=("messages",),
)
PydListConversation = pydantic_queryset_creator(Conversation)
PydListConversationMessage = pydantic_queryset_creator(ConversationMessage)