45 lines
1.9 KiB
Python
45 lines
1.9 KiB
Python
from sqlalchemy.orm import Session as DBSession
|
|
from app.db.models import Memory, Message, Session
|
|
from app.core.config import MEMORY_SUMMARIZE_THRESHOLD
|
|
from app.core import llm
|
|
|
|
|
|
def get_context_messages(db: DBSession, session_id: str) -> list[dict]:
|
|
"""短期メモリ(最近のメッセージ)と長期メモリ(要約)を結合してコンテキストを返す。"""
|
|
memories = db.query(Memory).filter(Memory.session_id == session_id).order_by(Memory.created_at).all()
|
|
messages = db.query(Message).filter(Message.session_id == session_id).order_by(Message.created_at).all()
|
|
|
|
context: list[dict] = []
|
|
|
|
if memories:
|
|
combined_summary = "\n\n".join(m.summary for m in memories)
|
|
context.append({
|
|
"role": "system",
|
|
"content": f"以下はこの会話の過去の要約です:\n\n{combined_summary}",
|
|
})
|
|
|
|
context.extend({"role": m.role, "content": m.content} for m in messages)
|
|
return context
|
|
|
|
|
|
async def maybe_summarize(db: DBSession, session: Session) -> None:
|
|
"""メッセージ数が閾値を超えたら古いメッセージを要約してMemoryに保存し、元メッセージを削除する。"""
|
|
messages = db.query(Message).filter(Message.session_id == session.id).order_by(Message.created_at).all()
|
|
if len(messages) < MEMORY_SUMMARIZE_THRESHOLD:
|
|
return
|
|
|
|
# 古いメッセージ(閾値の半分)を要約対象にする
|
|
half = MEMORY_SUMMARIZE_THRESHOLD // 2
|
|
to_summarize = messages[:half]
|
|
|
|
summary_prompt = [
|
|
{"role": "system", "content": "以下の会話を簡潔に要約してください。重要な事実・決定・文脈を保持してください。"},
|
|
*[{"role": m.role, "content": m.content} for m in to_summarize],
|
|
]
|
|
summary_text = await llm.complete(summary_prompt)
|
|
|
|
db.add(Memory(session_id=session.id, summary=summary_text))
|
|
for msg in to_summarize:
|
|
db.delete(msg)
|
|
db.commit()
|