Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -976,9 +976,8 @@ import logging
|
|
| 976 |
|
| 977 |
class ConversationalAIHandler:
|
| 978 |
def __init__(self):
|
| 979 |
-
#
|
| 980 |
-
|
| 981 |
-
self.base_url = "https://api.elevenlabs.io/v1"
|
| 982 |
self.api_key = os.getenv("ELEVENLABS_API_KEY")
|
| 983 |
self.headers = {
|
| 984 |
"xi-api-key": self.api_key,
|
|
@@ -987,7 +986,6 @@ class ConversationalAIHandler:
|
|
| 987 |
|
| 988 |
def get_british_male_voice_id(self):
|
| 989 |
"""Get British male voice ID"""
|
| 990 |
-
# This method's logic is sound and remains unchanged.
|
| 991 |
try:
|
| 992 |
logger.info(f"[VOICE] Using known voice ID for Daniel: {KNOWN_VOICE_IDS['Daniel']}")
|
| 993 |
return KNOWN_VOICE_IDS["Daniel"]
|
|
@@ -1000,55 +998,59 @@ class ConversationalAIHandler:
|
|
| 1000 |
try:
|
| 1001 |
logger.info(f"[AGENT] Starting agent creation/retrieval for project: {project_id}")
|
| 1002 |
|
| 1003 |
-
#
|
|
|
|
| 1004 |
existing_agent_id = db_ref.child(f'projects/{project_id}/agent_id').get()
|
| 1005 |
if existing_agent_id:
|
| 1006 |
-
logger.info(f"[AGENT] Found existing agent ID: {existing_agent_id}.
|
| 1007 |
-
|
| 1008 |
-
|
| 1009 |
-
|
| 1010 |
-
response = requests.get(verify_url, headers=self.headers, timeout=15)
|
| 1011 |
-
if response.status_code == 200:
|
| 1012 |
-
logger.info(f"[AGENT] Existing agent {existing_agent_id} verified and active.")
|
| 1013 |
-
return existing_agent_id
|
| 1014 |
-
else:
|
| 1015 |
-
logger.warning(f"[AGENT] Verification failed for agent {existing_agent_id} (Status: {response.status_code}). Creating a new one.")
|
| 1016 |
-
except Exception as e:
|
| 1017 |
-
logger.warning(f"[AGENT] Error verifying existing agent: {str(e)}. Creating a new one.")
|
| 1018 |
-
|
| 1019 |
-
# Step 2: If no valid agent exists, create a new one.
|
| 1020 |
-
logger.info(f"[AGENT] Creating new agent.")
|
| 1021 |
voice_id = self.get_british_male_voice_id()
|
| 1022 |
|
| 1023 |
diy_expert_prompt = f"""
|
| 1024 |
You are an experienced DIY expert with years of hands-on experience in Home Appliance Repair, Automotive Maintenance, Gardening & Urban Farming,
|
| 1025 |
-
Upcycling & Sustainable Crafts, or DIY Project Creation. You speak in a friendly, knowledgeable British manner and provide
|
| 1026 |
practical, actionable advice. You're working on this specific project:
|
| 1027 |
Project: {project_data.get('projectTitle', 'DIY Project')}
|
| 1028 |
Description: {project_data.get('projectDescription', '')}
|
| 1029 |
Initial Plan: {project_data.get('initialPlan', '')}
|
| 1030 |
-
Provide helpful, step-by-step guidance while being encouraging and safety-conscious.
|
| 1031 |
Ask clarifying questions when needed and share relevant tips from your experience.
|
| 1032 |
"""
|
| 1033 |
|
| 1034 |
-
#
|
| 1035 |
-
|
| 1036 |
-
|
| 1037 |
-
"
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
| 1041 |
-
|
| 1042 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1043 |
}
|
| 1044 |
|
| 1045 |
-
#
|
| 1046 |
creation_url = f"{self.base_url}/agents"
|
| 1047 |
-
logger.info(f"[AGENT] Posting to
|
| 1048 |
|
| 1049 |
-
response = requests.post(creation_url, headers=self.headers, json=
|
| 1050 |
|
| 1051 |
-
|
|
|
|
| 1052 |
agent_info = response.json()
|
| 1053 |
agent_id = agent_info.get("agent_id")
|
| 1054 |
logger.info(f"[AGENT] New agent created successfully: {agent_id}")
|
|
@@ -1060,7 +1062,6 @@ class ConversationalAIHandler:
|
|
| 1060 |
logger.info(f"[AGENT] Agent ID stored in database.")
|
| 1061 |
return agent_id
|
| 1062 |
else:
|
| 1063 |
-
# This will now give a much more informative error if the payload is wrong.
|
| 1064 |
logger.error(f"[AGENT] Failed to create agent. Status: {response.status_code}, Response: {response.text}")
|
| 1065 |
raise Exception(f"Failed to create agent: HTTP {response.status_code} - {response.text}")
|
| 1066 |
|
|
@@ -1070,12 +1071,13 @@ class ConversationalAIHandler:
|
|
| 1070 |
|
| 1071 |
def start_conversation(self, agent_id):
|
| 1072 |
"""Start a conversation with the agent"""
|
| 1073 |
-
logger.info(f"[CONVERSATION] Starting conversation with agent: {agent_id}")
|
| 1074 |
-
# CORRECTED: Use the single, correct endpoint for starting a conversation with an agent.
|
| 1075 |
-
conversation_url = f"{self.base_url}/agents/{agent_id}/conversations"
|
| 1076 |
try:
|
|
|
|
|
|
|
|
|
|
| 1077 |
response = requests.post(conversation_url, headers=self.headers, json={}, timeout=30)
|
| 1078 |
-
|
|
|
|
| 1079 |
conversation_info = response.json()
|
| 1080 |
conversation_id = conversation_info.get("conversation_id")
|
| 1081 |
logger.info(f"[CONVERSATION] Conversation started successfully: {conversation_id}")
|
|
@@ -1083,31 +1085,31 @@ class ConversationalAIHandler:
|
|
| 1083 |
else:
|
| 1084 |
logger.error(f"[CONVERSATION] Failed to start conversation. Status: {response.status_code}, Response: {response.text}")
|
| 1085 |
raise Exception(f"Failed to start conversation: {response.text}")
|
|
|
|
| 1086 |
except Exception as e:
|
| 1087 |
logger.error(f"[CONVERSATION] An exception occurred in start_conversation: {e}")
|
| 1088 |
raise
|
| 1089 |
|
| 1090 |
def send_message(self, agent_id, conversation_id, message):
|
| 1091 |
"""Send a message to the conversation"""
|
| 1092 |
-
# The 'agent_id' is not required for this endpoint, but we'll keep the signature for compatibility with your calling code.
|
| 1093 |
-
logger.info(f"[MESSAGE] Sending message to conversation: {conversation_id}")
|
| 1094 |
-
# CORRECTED: Use the single, correct endpoint for sending a message.
|
| 1095 |
-
message_url = f"{self.base_url}/conversations/{conversation_id}/messages"
|
| 1096 |
-
|
| 1097 |
-
# CORRECTED: The payload for sending a message is simpler.
|
| 1098 |
-
message_payload = {
|
| 1099 |
-
"text": message
|
| 1100 |
-
}
|
| 1101 |
-
|
| 1102 |
try:
|
| 1103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1104 |
if response.status_code == 200:
|
| 1105 |
logger.info(f"[MESSAGE] Message sent successfully to {conversation_id}.")
|
| 1106 |
-
# The response is streaming audio, but we can return the successful JSON confirmation.
|
| 1107 |
return response.json()
|
| 1108 |
else:
|
| 1109 |
logger.error(f"[MESSAGE] Failed to send message. Status: {response.status_code}, Response: {response.text}")
|
| 1110 |
raise Exception(f"Failed to send message: {response.text}")
|
|
|
|
| 1111 |
except Exception as e:
|
| 1112 |
logger.error(f"[MESSAGE] An exception occurred in send_message: {e}")
|
| 1113 |
raise
|
|
|
|
| 976 |
|
| 977 |
class ConversationalAIHandler:
|
| 978 |
def __init__(self):
|
| 979 |
+
# The base URL for the specific Conversational AI API
|
| 980 |
+
self.base_url = "https://api.elevenlabs.io/v1/conversational-ai"
|
|
|
|
| 981 |
self.api_key = os.getenv("ELEVENLABS_API_KEY")
|
| 982 |
self.headers = {
|
| 983 |
"xi-api-key": self.api_key,
|
|
|
|
| 986 |
|
| 987 |
def get_british_male_voice_id(self):
|
| 988 |
"""Get British male voice ID"""
|
|
|
|
| 989 |
try:
|
| 990 |
logger.info(f"[VOICE] Using known voice ID for Daniel: {KNOWN_VOICE_IDS['Daniel']}")
|
| 991 |
return KNOWN_VOICE_IDS["Daniel"]
|
|
|
|
| 998 |
try:
|
| 999 |
logger.info(f"[AGENT] Starting agent creation/retrieval for project: {project_id}")
|
| 1000 |
|
| 1001 |
+
# Verification of conversational agents requires listing all agents, which is inefficient.
|
| 1002 |
+
# We will rely on the database ID and create a new one if it fails to be used later.
|
| 1003 |
existing_agent_id = db_ref.child(f'projects/{project_id}/agent_id').get()
|
| 1004 |
if existing_agent_id:
|
| 1005 |
+
logger.info(f"[AGENT] Found existing agent ID in DB: {existing_agent_id}. Assuming it is active.")
|
| 1006 |
+
return existing_agent_id
|
| 1007 |
+
|
| 1008 |
+
logger.info(f"[AGENT] No existing agent ID found in DB. Creating a new agent.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1009 |
voice_id = self.get_british_male_voice_id()
|
| 1010 |
|
| 1011 |
diy_expert_prompt = f"""
|
| 1012 |
You are an experienced DIY expert with years of hands-on experience in Home Appliance Repair, Automotive Maintenance, Gardening & Urban Farming,
|
| 1013 |
+
Upcycling & Sustainable Crafts, or DIY Project Creation. You speak in a friendly, knowledgeable British manner and provide
|
| 1014 |
practical, actionable advice. You're working on this specific project:
|
| 1015 |
Project: {project_data.get('projectTitle', 'DIY Project')}
|
| 1016 |
Description: {project_data.get('projectDescription', '')}
|
| 1017 |
Initial Plan: {project_data.get('initialPlan', '')}
|
| 1018 |
+
Provide helpful, step-by-step guidance while being encouraging and safety-conscious.
|
| 1019 |
Ask clarifying questions when needed and share relevant tips from your experience.
|
| 1020 |
"""
|
| 1021 |
|
| 1022 |
+
# This is the correct, detailed payload required by the conversational-ai endpoint.
|
| 1023 |
+
agent_data = {
|
| 1024 |
+
"name": f"DIY Expert - {project_data.get('projectTitle', project_data.get('title', 'Project'))}",
|
| 1025 |
+
"conversation_config": {
|
| 1026 |
+
"agent": {
|
| 1027 |
+
"prompt": {"prompt": diy_expert_prompt},
|
| 1028 |
+
"first_message": "Hello! I'm your Sozo DIY expert assistant. I'm here to help you with your project. What would you like to work on today?",
|
| 1029 |
+
"language": "en"
|
| 1030 |
+
},
|
| 1031 |
+
"asr": {
|
| 1032 |
+
"provider": "deepgram",
|
| 1033 |
+
"user_input_audio_format": "pcm_16000"
|
| 1034 |
+
},
|
| 1035 |
+
"tts": {"voice_id": voice_id},
|
| 1036 |
+
"llm": {
|
| 1037 |
+
"provider": "openai",
|
| 1038 |
+
"model": "gpt-4"
|
| 1039 |
+
}
|
| 1040 |
+
},
|
| 1041 |
+
"platform_settings": {
|
| 1042 |
+
"webhook_url": f"{os.getenv('BASE_URL', 'https://rairo-neofix-api.hf.space')}/api/webhook/agent/{project_id}"
|
| 1043 |
+
}
|
| 1044 |
}
|
| 1045 |
|
| 1046 |
+
# This is the correct endpoint that was causing the 404 Not Found error.
|
| 1047 |
creation_url = f"{self.base_url}/agents"
|
| 1048 |
+
logger.info(f"[AGENT] Posting to the correct endpoint: {creation_url}")
|
| 1049 |
|
| 1050 |
+
response = requests.post(creation_url, headers=self.headers, json=agent_data, timeout=30)
|
| 1051 |
|
| 1052 |
+
# A successful creation with this endpoint returns 201 Created.
|
| 1053 |
+
if response.status_code == 201:
|
| 1054 |
agent_info = response.json()
|
| 1055 |
agent_id = agent_info.get("agent_id")
|
| 1056 |
logger.info(f"[AGENT] New agent created successfully: {agent_id}")
|
|
|
|
| 1062 |
logger.info(f"[AGENT] Agent ID stored in database.")
|
| 1063 |
return agent_id
|
| 1064 |
else:
|
|
|
|
| 1065 |
logger.error(f"[AGENT] Failed to create agent. Status: {response.status_code}, Response: {response.text}")
|
| 1066 |
raise Exception(f"Failed to create agent: HTTP {response.status_code} - {response.text}")
|
| 1067 |
|
|
|
|
| 1071 |
|
| 1072 |
def start_conversation(self, agent_id):
|
| 1073 |
"""Start a conversation with the agent"""
|
|
|
|
|
|
|
|
|
|
| 1074 |
try:
|
| 1075 |
+
logger.info(f"[CONVERSATION] Starting conversation with agent: {agent_id}")
|
| 1076 |
+
conversation_url = f"{self.base_url}/agents/{agent_id}/conversations"
|
| 1077 |
+
|
| 1078 |
response = requests.post(conversation_url, headers=self.headers, json={}, timeout=30)
|
| 1079 |
+
|
| 1080 |
+
if response.status_code == 201:
|
| 1081 |
conversation_info = response.json()
|
| 1082 |
conversation_id = conversation_info.get("conversation_id")
|
| 1083 |
logger.info(f"[CONVERSATION] Conversation started successfully: {conversation_id}")
|
|
|
|
| 1085 |
else:
|
| 1086 |
logger.error(f"[CONVERSATION] Failed to start conversation. Status: {response.status_code}, Response: {response.text}")
|
| 1087 |
raise Exception(f"Failed to start conversation: {response.text}")
|
| 1088 |
+
|
| 1089 |
except Exception as e:
|
| 1090 |
logger.error(f"[CONVERSATION] An exception occurred in start_conversation: {e}")
|
| 1091 |
raise
|
| 1092 |
|
| 1093 |
def send_message(self, agent_id, conversation_id, message):
|
| 1094 |
"""Send a message to the conversation"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1095 |
try:
|
| 1096 |
+
logger.info(f"[MESSAGE] Sending message to conversation: {conversation_id}")
|
| 1097 |
+
message_url = f"{self.base_url}/agents/{agent_id}/conversations/{conversation_id}/messages"
|
| 1098 |
+
|
| 1099 |
+
payload = {
|
| 1100 |
+
"message": message,
|
| 1101 |
+
"message_type": "text"
|
| 1102 |
+
}
|
| 1103 |
+
|
| 1104 |
+
response = requests.post(message_url, headers=self.headers, json=payload, timeout=30)
|
| 1105 |
+
|
| 1106 |
if response.status_code == 200:
|
| 1107 |
logger.info(f"[MESSAGE] Message sent successfully to {conversation_id}.")
|
|
|
|
| 1108 |
return response.json()
|
| 1109 |
else:
|
| 1110 |
logger.error(f"[MESSAGE] Failed to send message. Status: {response.status_code}, Response: {response.text}")
|
| 1111 |
raise Exception(f"Failed to send message: {response.text}")
|
| 1112 |
+
|
| 1113 |
except Exception as e:
|
| 1114 |
logger.error(f"[MESSAGE] An exception occurred in send_message: {e}")
|
| 1115 |
raise
|