prompt_util.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import json
  2. from datetime import datetime
  3. from typing import List, Dict
  4. from openai import OpenAI
  5. from pqai_agent import logging_service, chat_service
  6. from pqai_agent.response_type_detector import ResponseTypeDetector
  7. from pqai_agent.user_profile_extractor import UserProfileExtractor
  8. from pqai_agent.dialogue_manager import DialogueManager
  9. from pqai_agent.mq_message import MessageType
  10. from pqai_agent.utils.prompt_utils import format_agent_profile
  11. logger = logging_service.logger
  12. def compose_openai_chat_messages_no_time(dialogue_history, multimodal=False):
  13. messages = []
  14. for entry in dialogue_history:
  15. role = entry["role"]
  16. msg_type = entry.get("type", MessageType.TEXT)
  17. fmt_time = DialogueManager.format_timestamp(entry["timestamp"])
  18. if msg_type in (MessageType.IMAGE_GW, MessageType.IMAGE_QW, MessageType.GIF):
  19. if multimodal:
  20. messages.append(
  21. {
  22. "role": role,
  23. "content": [
  24. {
  25. "type": "image_url",
  26. "image_url": {"url": entry["content"]},
  27. }
  28. ],
  29. }
  30. )
  31. else:
  32. logger.warning("Image in non-multimodal mode")
  33. messages.append({"role": role, "content": "[图片]"})
  34. else:
  35. messages.append({"role": role, "content": f'{entry["content"]}'})
  36. return messages
  37. def create_llm_client(model_name):
  38. volcengine_models = [
  39. chat_service.VOLCENGINE_MODEL_DOUBAO_PRO_32K,
  40. chat_service.VOLCENGINE_MODEL_DOUBAO_PRO_1_5,
  41. chat_service.VOLCENGINE_MODEL_DOUBAO_1_5_VISION_PRO,
  42. chat_service.VOLCENGINE_MODEL_DEEPSEEK_V3,
  43. ]
  44. deepseek_models = [
  45. chat_service.DEEPSEEK_CHAT_MODEL,
  46. ]
  47. volcengine_bots = [
  48. chat_service.VOLCENGINE_BOT_DEEPSEEK_V3_SEARCH,
  49. ]
  50. if model_name in volcengine_models:
  51. llm_client = OpenAI(
  52. api_key=chat_service.VOLCENGINE_API_TOKEN,
  53. base_url=chat_service.VOLCENGINE_BASE_URL,
  54. )
  55. elif model_name in volcengine_bots:
  56. llm_client = OpenAI(
  57. api_key=chat_service.VOLCENGINE_API_TOKEN,
  58. base_url=chat_service.VOLCENGINE_BOT_BASE_URL,
  59. )
  60. elif model_name in deepseek_models:
  61. llm_client = OpenAI(
  62. api_key=chat_service.DEEPSEEK_API_TOKEN,
  63. base_url=chat_service.DEEPSEEK_BASE_URL,
  64. )
  65. else:
  66. raise Exception("model not supported")
  67. return llm_client
  68. def run_openai_chat(messages, model_name, **kwargs):
  69. llm_client = create_llm_client(model_name)
  70. response = llm_client.chat.completions.create(
  71. messages=messages, model=model_name, **kwargs
  72. )
  73. logger.debug(response)
  74. return response
  75. def run_extractor_prompt(req_data) -> Dict[str, str]:
  76. prompt = req_data["prompt"]
  77. user_profile = req_data["user_profile"]
  78. dialogue_history = req_data["dialogue_history"]
  79. model_name = req_data["model_name"]
  80. llm_client = create_llm_client(model_name)
  81. extractor = UserProfileExtractor(model_name=model_name, llm_client=llm_client)
  82. profile_to_update = extractor.extract_profile_info_v2(user_profile, dialogue_history, prompt)
  83. logger.info(profile_to_update)
  84. if not profile_to_update:
  85. return {}
  86. return profile_to_update
  87. def run_chat_prompt(req_data):
  88. prompt = req_data["prompt"]
  89. staff_profile = req_data.get("staff_profile", {})
  90. user_profile = req_data.get("user_profile", {})
  91. dialogue_history = req_data.get("dialogue_history", [])
  92. model_name = req_data["model_name"]
  93. current_timestamp = req_data["current_timestamp"] / 1000
  94. prompt_context = {
  95. 'formatted_staff_profile': format_agent_profile(staff_profile),
  96. **user_profile
  97. }
  98. current_hour = datetime.fromtimestamp(current_timestamp).hour
  99. prompt_context["last_interaction_interval"] = 0
  100. prompt_context["current_time_period"] = DialogueManager.get_time_context(
  101. current_hour
  102. )
  103. prompt_context["current_hour"] = current_hour
  104. prompt_context["if_first_interaction"] = False if dialogue_history else True
  105. last_message = dialogue_history[-1] if dialogue_history else {"role": "assistant"}
  106. prompt_context["if_active_greeting"] = (
  107. False if last_message["role"] == "user" else True
  108. )
  109. current_time_str = datetime.fromtimestamp(current_timestamp).strftime(
  110. "%Y-%m-%d %H:%M:%S"
  111. )
  112. system_prompt = {"role": "system", "content": prompt.format(**prompt_context)}
  113. messages = [system_prompt]
  114. if req_data["scene"] == "custom_debugging":
  115. messages.extend(compose_openai_chat_messages_no_time(dialogue_history))
  116. if "头像" in system_prompt["content"]:
  117. messages.append(
  118. {
  119. "role": "user",
  120. "content": [
  121. {
  122. "type": "image_url",
  123. "image_url": {"url": user_profile["avatar"]},
  124. }
  125. ],
  126. }
  127. )
  128. else:
  129. messages.extend(
  130. DialogueManager.compose_chat_messages_openai_compatible(
  131. dialogue_history, current_time_str
  132. )
  133. )
  134. return run_openai_chat(
  135. messages, model_name, temperature=1, top_p=0.7, max_tokens=1024
  136. )
  137. def run_response_type_prompt(req_data):
  138. prompt = req_data["prompt"]
  139. dialogue_history = req_data["dialogue_history"]
  140. model_name = req_data["model_name"]
  141. composed_dialogue = ResponseTypeDetector.compose_dialogue(dialogue_history[:-1])
  142. next_message = DialogueManager.format_dialogue_content(dialogue_history[-1])
  143. prompt = prompt.format(dialogue_history=composed_dialogue, message=next_message)
  144. messages = [
  145. {"role": "system", "content": "你是一个专业的智能助手"},
  146. {"role": "user", "content": prompt},
  147. ]
  148. return run_openai_chat(messages, model_name, temperature=0.2, max_tokens=128)
  149. def format_dialogue_history(dialogue: List[Dict]) -> str:
  150. role_map = {'user': '用户', 'assistant': '客服'}
  151. messages = []
  152. for msg in dialogue:
  153. if not msg['content']:
  154. continue
  155. if msg['role'] not in role_map:
  156. continue
  157. format_dt = datetime.fromtimestamp(msg['timestamp'] / 1000).strftime('%Y-%m-%d %H:%M:%S')
  158. msg_type = MessageType(msg.get('type', MessageType.TEXT.value)).description
  159. messages.append('[{}][{}][{}]{}'.format(role_map[msg['role']], format_dt, msg_type, msg['content']))
  160. return '\n'.join(messages)