Repository navigation
Expand file tree
/
Copy pathmessage.py
More file actions
63 lines (53 loc) · 2.19 KB
/
Copy pathmessage.py
File metadata and controls
63 lines (53 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
"""Chat message model."""
from datetime import UTC, datetime
from app.extensions import db
class Message(db.Model):
"""A single message exchanged within a conversation.
``role`` is one of ``user`` or ``assistant``. Prompt text and assistant
responses are stored verbatim so conversation history can be replayed or
exported.
"""
__tablename__ = "messages"
id = db.Column(db.Integer, primary_key=True)
conversation_id = db.Column(
db.Integer,
db.ForeignKey("conversations.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
role = db.Column(db.String(20), nullable=False)
content = db.Column(db.Text, nullable=False)
# Token usage recorded for the provider response that produced this message
# (issue #13). ``None`` for user messages and for historical rows.
prompt_tokens = db.Column(db.Integer, nullable=True)
completion_tokens = db.Column(db.Integer, nullable=True)
total_tokens = db.Column(db.Integer, nullable=True)
created_at = db.Column(
db.DateTime(timezone=True), nullable=False, default=lambda: datetime.now(UTC)
)
conversation = db.relationship("Conversation", back_populates="messages")
attachments = db.relationship(
"MessageAttachment",
back_populates="message",
cascade="all, delete-orphan",
order_by="MessageAttachment.created_at",
)
def to_dict(self) -> dict:
"""Serialize the message for JSON API responses."""
usage = None
if self.total_tokens is not None:
usage = {
"prompt_tokens": self.prompt_tokens or 0,
"completion_tokens": self.completion_tokens or 0,
"total_tokens": self.total_tokens or 0,
}
return {
"id": self.id,
"role": self.role,
"content": self.content,
"attachments": [attachment.to_dict() for attachment in self.attachments],
"token_usage": usage,
"created_at": self.created_at.isoformat() if self.created_at else None,
}
def __repr__(self) -> str: # pragma: no cover - debugging aid
return f"<Message id={self.id} role={self.role!r}>"