conversations.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. """
  2. 对话API(简化版,完整版需包含流式响应和WebSocket)
  3. """
  4. from fastapi import APIRouter, Depends, HTTPException
  5. from sqlalchemy.ext.asyncio import AsyncSession
  6. from sqlalchemy import select
  7. from app.core.database import get_db
  8. from app.models.user import User
  9. from app.models.character import Character
  10. from app.models.conversation import Conversation, Message, UserActivity
  11. from app.models.affection import AffectionScore
  12. from app.schemas.conversation import MessageCreate, MessageResponse, ConversationResponse
  13. from app.api.auth import get_current_user
  14. from app.services.llm_provider import get_llm_provider
  15. from app.services.affection_service import AffectionService
  16. from app.core.security import decrypt_api_key
  17. from datetime import datetime
  18. from typing import List
  19. router = APIRouter()
  20. @router.post("/{conversation_id}/messages", response_model=MessageResponse)
  21. async def send_message(
  22. conversation_id: int,
  23. message_data: MessageCreate,
  24. current_user: User = Depends(get_current_user),
  25. db: AsyncSession = Depends(get_db)
  26. ):
  27. """发送消息并获取AI回复"""
  28. # 获取对话和角色
  29. result = await db.execute(
  30. select(Conversation, Character)
  31. .join(Character, Conversation.character_id == Character.id)
  32. .where(
  33. Conversation.id == conversation_id,
  34. Conversation.user_id == current_user.id
  35. )
  36. )
  37. conv_char = result.one_or_none()
  38. if not conv_char:
  39. raise HTTPException(status_code=404, detail="对话不存在")
  40. conversation, character = conv_char
  41. # 保存用户消息
  42. user_message = Message(
  43. conversation_id=conversation_id,
  44. role="user",
  45. content=message_data.content
  46. )
  47. db.add(user_message)
  48. await db.commit()
  49. # 获取对话历史
  50. history_result = await db.execute(
  51. select(Message)
  52. .where(Message.conversation_id == conversation_id)
  53. .order_by(Message.created_at.desc())
  54. .limit(10)
  55. )
  56. history = list(reversed(history_result.scalars().all()))
  57. # 构建消息列表
  58. messages = [{"role": "system", "content": character.system_prompt}]
  59. messages.extend([{"role": msg.role, "content": msg.content} for msg in history])
  60. # 调用AI
  61. provider = get_llm_provider(character.llm_provider)
  62. # 获取并解密API Key
  63. api_key_config = current_user.encrypted_api_keys.get(character.llm_provider)
  64. if not api_key_config:
  65. raise HTTPException(status_code=400, detail=f"请先配置{character.llm_provider}的API Key")
  66. api_key = decrypt_api_key(api_key_config["key"])
  67. # 调用AI
  68. ai_response = await provider.chat_completion(
  69. messages=messages,
  70. api_key=api_key,
  71. model=character.llm_model,
  72. temperature=character.config.get("temperature", 0.8)
  73. )
  74. # 解析情感分析
  75. from app.services.affection_service import AffectionService
  76. sentiment_result = AffectionService.analyze_sentiment_from_ai_response(ai_response)
  77. # 保存AI回复
  78. ai_message = Message(
  79. conversation_id=conversation_id,
  80. role="assistant",
  81. content=sentiment_result["content"]
  82. )
  83. db.add(ai_message)
  84. await db.commit()
  85. await db.refresh(ai_message)
  86. # 更新好感度
  87. affection = await AffectionService.get_or_create_affection(
  88. db, current_user.id, character.id
  89. )
  90. await AffectionService.update_affection(
  91. db,
  92. affection.id,
  93. sentiment_result["affection_change"],
  94. sentiment_result["reason"],
  95. ai_message.id,
  96. sentiment_result["sentiment_data"]
  97. )
  98. # 更新活跃状态
  99. activity_result = await db.execute(
  100. select(UserActivity).where(UserActivity.conversation_id == conversation_id)
  101. )
  102. activity = activity_result.scalar_one_or_none()
  103. if activity:
  104. activity.last_message_at = datetime.now()
  105. else:
  106. activity = UserActivity(
  107. conversation_id=conversation_id,
  108. last_message_at=datetime.now()
  109. )
  110. db.add(activity)
  111. await db.commit()
  112. # 构建响应
  113. response = MessageResponse.from_orm(ai_message)
  114. response.affection_change = sentiment_result["affection_change"]
  115. return response
  116. @router.get("", response_model=List[ConversationResponse])
  117. async def list_conversations(
  118. current_user: User = Depends(get_current_user),
  119. db: AsyncSession = Depends(get_db)
  120. ):
  121. """获取用户的所有对话列表"""
  122. result = await db.execute(
  123. select(Conversation)
  124. .where(Conversation.user_id == current_user.id)
  125. .order_by(Conversation.updated_at.desc())
  126. )
  127. conversations = result.scalars().all()
  128. return conversations