Files
DEMO-AGENT/review_agent/services.py

91 lines
2.9 KiB
Python

from __future__ import annotations
from django.db.models import Q, QuerySet
from django.utils import timezone
from .llm import LLMConfigurationError, LLMRequestError, generate_reply
from .models import Conversation, Message
def list_conversations(user, search: str = "") -> QuerySet[Conversation]:
"""Returns a user's conversations, optionally filtered by title or content."""
conversations = Conversation.objects.filter(user=user)
if not search:
return conversations
return conversations.filter(
Q(title__icontains=search) | Q(messages__content__icontains=search)
).distinct()
def get_conversation_for_user(user, conversation_id: int | None) -> Conversation | None:
"""Loads a conversation only when it belongs to the current user."""
if not conversation_id:
return None
return Conversation.objects.filter(user=user, pk=conversation_id).first()
def create_conversation(user) -> Conversation:
"""Creates an empty conversation that can immediately accept messages."""
now = timezone.localtime()
return Conversation.objects.create(
user=user,
title=f"新对话 {now.strftime('%m-%d %H:%M')}",
)
def append_user_message(conversation: Conversation, content: str) -> Message:
"""Appends a user message and updates the conversation title from the first prompt."""
message = Message.objects.create(
conversation=conversation,
role=Message.Role.USER,
content=content.strip(),
)
if conversation.messages.filter(role=Message.Role.USER).count() == 1:
conversation.title = build_conversation_title(content)
conversation.save(update_fields=["title", "updated_at"])
return message
def append_assistant_message(conversation: Conversation, content: str) -> Message:
"""Appends the deterministic assistant reply."""
return Message.objects.create(
conversation=conversation,
role=Message.Role.ASSISTANT,
content=content,
)
def send_message(conversation: Conversation, content: str) -> tuple[Message, Message]:
"""Stores one user message and one provider-backed assistant reply."""
user_message = append_user_message(conversation, content)
try:
reply_content = generate_reply(conversation, content)
except (LLMConfigurationError, LLMRequestError) as exc:
reply_content = f"模型调用失败:{exc}"
assistant_message = append_assistant_message(conversation, reply_content)
if conversation.title.startswith("新对话"):
conversation.title = build_conversation_title(content)
conversation.save(update_fields=["title", "updated_at"])
return user_message, assistant_message
def build_conversation_title(content: str) -> str:
"""Creates a concise title from the first user message."""
normalized = " ".join(content.strip().split())
if not normalized:
return "新对话"
return normalized[:24]