Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -976,9 +976,12 @@ import logging
|
|
| 976 |
|
| 977 |
class ConversationalAIHandler:
|
| 978 |
def __init__(self):
|
| 979 |
-
# The base URL for the
|
| 980 |
-
self.base_url = "https://api.elevenlabs.io/v1
|
| 981 |
self.api_key = os.getenv("ELEVENLABS_API_KEY")
|
|
|
|
|
|
|
|
|
|
| 982 |
self.headers = {
|
| 983 |
"xi-api-key": self.api_key,
|
| 984 |
"Content-Type": "application/json"
|
|
@@ -989,68 +992,58 @@ class ConversationalAIHandler:
|
|
| 989 |
try:
|
| 990 |
logger.info(f"[VOICE] Using known voice ID for Daniel: {KNOWN_VOICE_IDS['Daniel']}")
|
| 991 |
return KNOWN_VOICE_IDS["Daniel"]
|
| 992 |
-
except
|
| 993 |
-
logger.error(
|
| 994 |
-
return
|
| 995 |
|
| 996 |
def create_or_get_agent(self, project_id, project_data):
|
| 997 |
"""Create or retrieve existing agent for the project"""
|
| 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}.
|
| 1006 |
-
|
| 1007 |
-
|
| 1008 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1009 |
voice_id = self.get_british_male_voice_id()
|
| 1010 |
|
| 1011 |
diy_expert_prompt = f"""
|
| 1012 |
-
You are an experienced DIY expert
|
| 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 |
-
|
| 1019 |
-
Ask clarifying questions when needed and share relevant tips from your experience.
|
| 1020 |
"""
|
| 1021 |
|
| 1022 |
-
#
|
| 1023 |
-
|
| 1024 |
-
"name": f"DIY Expert - {project_data.get('projectTitle',
|
| 1025 |
-
"
|
| 1026 |
-
|
| 1027 |
-
|
| 1028 |
-
|
| 1029 |
-
|
| 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 |
-
#
|
| 1047 |
creation_url = f"{self.base_url}/agents"
|
| 1048 |
-
logger.info(f"[AGENT] Posting to
|
| 1049 |
-
|
| 1050 |
-
response = requests.post(creation_url, headers=self.headers, json=
|
| 1051 |
-
|
| 1052 |
-
# A successful creation
|
| 1053 |
-
if response.status_code ==
|
| 1054 |
agent_info = response.json()
|
| 1055 |
agent_id = agent_info.get("agent_id")
|
| 1056 |
logger.info(f"[AGENT] New agent created successfully: {agent_id}")
|
|
@@ -1073,11 +1066,13 @@ class ConversationalAIHandler:
|
|
| 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 |
-
|
|
|
|
| 1081 |
conversation_info = response.json()
|
| 1082 |
conversation_id = conversation_info.get("conversation_id")
|
| 1083 |
logger.info(f"[CONVERSATION] Conversation started successfully: {conversation_id}")
|
|
@@ -1094,17 +1089,16 @@ class ConversationalAIHandler:
|
|
| 1094 |
"""Send a message to the conversation"""
|
| 1095 |
try:
|
| 1096 |
logger.info(f"[MESSAGE] Sending message to conversation: {conversation_id}")
|
| 1097 |
-
|
|
|
|
| 1098 |
|
| 1099 |
-
payload
|
| 1100 |
-
|
| 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
|
| 1108 |
return response.json()
|
| 1109 |
else:
|
| 1110 |
logger.error(f"[MESSAGE] Failed to send message. Status: {response.status_code}, Response: {response.text}")
|
|
|
|
| 976 |
|
| 977 |
class ConversationalAIHandler:
|
| 978 |
def __init__(self):
|
| 979 |
+
# CORRECT: The base URL for the API is /v1. All endpoints branch from here.
|
| 980 |
+
self.base_url = "https://api.elevenlabs.io/v1"
|
| 981 |
self.api_key = os.getenv("ELEVENLABS_API_KEY")
|
| 982 |
+
if not self.api_key:
|
| 983 |
+
logger.critical("[AGENT] ELEVENLABS_API_KEY environment variable not set.")
|
| 984 |
+
raise ValueError("ELEVENLABS_API_KEY environment variable not set.")
|
| 985 |
self.headers = {
|
| 986 |
"xi-api-key": self.api_key,
|
| 987 |
"Content-Type": "application/json"
|
|
|
|
| 992 |
try:
|
| 993 |
logger.info(f"[VOICE] Using known voice ID for Daniel: {KNOWN_VOICE_IDS['Daniel']}")
|
| 994 |
return KNOWN_VOICE_IDS["Daniel"]
|
| 995 |
+
except KeyError:
|
| 996 |
+
logger.error("[VOICE] Voice ID for 'Daniel' not found. Using hardcoded fallback.")
|
| 997 |
+
return "onwK4e9ZLuTAKqWW03F9"
|
| 998 |
|
| 999 |
def create_or_get_agent(self, project_id, project_data):
|
| 1000 |
"""Create or retrieve existing agent for the project"""
|
| 1001 |
try:
|
| 1002 |
logger.info(f"[AGENT] Starting agent creation/retrieval for project: {project_id}")
|
| 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 in DB: {existing_agent_id}. Verifying...")
|
| 1007 |
+
verify_url = f"{self.base_url}/agents/{existing_agent_id}"
|
| 1008 |
+
try:
|
| 1009 |
+
response = requests.get(verify_url, headers=self.headers, timeout=15)
|
| 1010 |
+
if response.status_code == 200:
|
| 1011 |
+
logger.info(f"[AGENT] Existing agent {existing_agent_id} verified and active.")
|
| 1012 |
+
return existing_agent_id
|
| 1013 |
+
else:
|
| 1014 |
+
logger.warning(f"[AGENT] Verification failed for agent {existing_agent_id} (Status: {response.status_code}). Creating a new one.")
|
| 1015 |
+
except Exception as e:
|
| 1016 |
+
logger.warning(f"[AGENT] Error verifying agent: {e}. Creating a new one.")
|
| 1017 |
+
|
| 1018 |
+
logger.info(f"[AGENT] Creating new agent.")
|
| 1019 |
voice_id = self.get_british_male_voice_id()
|
| 1020 |
|
| 1021 |
diy_expert_prompt = f"""
|
| 1022 |
+
You are an experienced DIY expert... [Your full prompt here] ...
|
|
|
|
|
|
|
| 1023 |
Project: {project_data.get('projectTitle', 'DIY Project')}
|
| 1024 |
Description: {project_data.get('projectDescription', '')}
|
| 1025 |
Initial Plan: {project_data.get('initialPlan', '')}
|
| 1026 |
+
...
|
|
|
|
| 1027 |
"""
|
| 1028 |
|
| 1029 |
+
# CORRECT PAYLOAD: The detailed, structured payload is correct.
|
| 1030 |
+
agent_payload = {
|
| 1031 |
+
"name": f"DIY Expert - {project_data.get('projectTitle', project_id)}",
|
| 1032 |
+
"prompt": diy_expert_prompt,
|
| 1033 |
+
"voice_id": voice_id,
|
| 1034 |
+
"initial_message": "Hello! I'm your Sozo DIY assistant. I'm here to help you with your project. What would you like to work on today?",
|
| 1035 |
+
"webhook_url": f"{os.getenv('BASE_URL', 'https://rairo-neofix-api.hf.space')}/api/webhook/agent/{project_id}",
|
| 1036 |
+
"model": "eleven_turbo_v2"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1037 |
}
|
| 1038 |
|
| 1039 |
+
# CORRECT ENDPOINT: The creation URL is /v1/agents.
|
| 1040 |
creation_url = f"{self.base_url}/agents"
|
| 1041 |
+
logger.info(f"[AGENT] Posting to correct endpoint: {creation_url}")
|
| 1042 |
+
|
| 1043 |
+
response = requests.post(creation_url, headers=self.headers, json=agent_payload, timeout=30)
|
| 1044 |
+
|
| 1045 |
+
# A successful creation returns HTTP 200 OK.
|
| 1046 |
+
if response.status_code == 200:
|
| 1047 |
agent_info = response.json()
|
| 1048 |
agent_id = agent_info.get("agent_id")
|
| 1049 |
logger.info(f"[AGENT] New agent created successfully: {agent_id}")
|
|
|
|
| 1066 |
"""Start a conversation with the agent"""
|
| 1067 |
try:
|
| 1068 |
logger.info(f"[CONVERSATION] Starting conversation with agent: {agent_id}")
|
| 1069 |
+
# CORRECT ENDPOINT: Follows the /agents/{id}/conversations pattern.
|
| 1070 |
conversation_url = f"{self.base_url}/agents/{agent_id}/conversations"
|
| 1071 |
|
| 1072 |
response = requests.post(conversation_url, headers=self.headers, json={}, timeout=30)
|
| 1073 |
+
|
| 1074 |
+
# A successful start returns HTTP 200 OK.
|
| 1075 |
+
if response.status_code == 200:
|
| 1076 |
conversation_info = response.json()
|
| 1077 |
conversation_id = conversation_info.get("conversation_id")
|
| 1078 |
logger.info(f"[CONVERSATION] Conversation started successfully: {conversation_id}")
|
|
|
|
| 1089 |
"""Send a message to the conversation"""
|
| 1090 |
try:
|
| 1091 |
logger.info(f"[MESSAGE] Sending message to conversation: {conversation_id}")
|
| 1092 |
+
# CORRECT ENDPOINT: Uses the /conversations/{id}/messages pattern.
|
| 1093 |
+
message_url = f"{self.base_url}/conversations/{conversation_id}/messages"
|
| 1094 |
|
| 1095 |
+
# CORRECT PAYLOAD: The payload requires the "text" of the message.
|
| 1096 |
+
payload = {"text": message}
|
|
|
|
|
|
|
| 1097 |
|
| 1098 |
response = requests.post(message_url, headers=self.headers, json=payload, timeout=30)
|
| 1099 |
|
| 1100 |
if response.status_code == 200:
|
| 1101 |
+
logger.info(f"[MESSAGE] Message sent successfully.")
|
| 1102 |
return response.json()
|
| 1103 |
else:
|
| 1104 |
logger.error(f"[MESSAGE] Failed to send message. Status: {response.status_code}, Response: {response.text}")
|