Spaces:
Build error
Build error
Update researchsimulation/InteractiveInterviewChatbot.py
Browse files
researchsimulation/InteractiveInterviewChatbot.py
CHANGED
|
@@ -43,7 +43,6 @@ def parse_question_with_llm(question, respondent_names, processor_llm):
|
|
| 43 |
- **Correct (British):** organised, prioritise, minimise, realise, behaviour, centre, defence, travelling, practise (verb), licence (noun), programme, aeroplane.
|
| 44 |
- **Incorrect (American):** organized, prioritize, minimize, realize, behavior, center, defense, traveling, practice (verb and noun), license (noun), program, airplane.
|
| 45 |
6. Ensure that you follow the **Formatting Rules** exactly. THIS IS EXTREMELY IMPORTANT.
|
| 46 |
-
|
| 47 |
### Examples:
|
| 48 |
- "Sourav, do you agree with this topic?" → "Do you agree with this topic?"
|
| 49 |
- "What do you think about this topic, Divya?" → "What do you think about this topic?"
|
|
@@ -55,7 +54,6 @@ def parse_question_with_llm(question, respondent_names, processor_llm):
|
|
| 55 |
- "Divya, what did you learn from this program?" → "What did you learn from this programme?"
|
| 56 |
- "How do you stay organized, Rahul?" → "How do you stay organised?"
|
| 57 |
- "Meena, how do you balance work and traveling?" → "How do you balance work and travelling?"
|
| 58 |
-
|
| 59 |
### **Formatting Rules**:
|
| 60 |
For each question identified, respond using **only** the following format:
|
| 61 |
- Respondent: <Respondent Name>
|
|
@@ -206,100 +204,85 @@ def validate_question_topics(parsed_questions, processor_llm):
|
|
| 206 |
|
| 207 |
|
| 208 |
|
| 209 |
-
def
|
| 210 |
-
"""
|
| 211 |
-
Generate a raw, generic answer in first person, British English, without applying any specific style or tone.
|
| 212 |
-
"""
|
| 213 |
-
task_prompt = f"""
|
| 214 |
-
You are {agent_name}. Respond to the question below **in first person**, using British English.
|
| 215 |
-
Focus only on answering naturally and authentically. Do not apply any specific tone or style.
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
### Question:
|
| 219 |
-
"{agent_question}"
|
| 220 |
-
"""
|
| 221 |
-
raw_response_task = Task(description=task_prompt, expected_output="", agent=respondent_agent)
|
| 222 |
-
crew = Crew(agents=[respondent_agent], tasks=[raw_response_task], process=Process.sequential)
|
| 223 |
-
crew.kickoff()
|
| 224 |
-
return raw_response_task.output.raw.strip()
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
def stylise_answer(raw_response, communication_style, agent_name, processor_llm):
|
| 230 |
"""
|
| 231 |
-
|
|
|
|
|
|
|
| 232 |
"""
|
| 233 |
-
style_prompt = f"""
|
| 234 |
-
Rephrase the following response into a {communication_style} tone using British English.
|
| 235 |
-
Keep it in first person and do not change the meaning.
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
### Original Response:
|
| 239 |
-
"{raw_response}"
|
| 240 |
-
"""
|
| 241 |
-
return processor_llm.invoke(style_prompt).content.strip()
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
def validate_final_answer(answer, agent_name):
|
| 247 |
-
"""
|
| 248 |
-
Validate the final answer. Returns a formatted string or an error message if invalid.
|
| 249 |
-
"""
|
| 250 |
-
if not answer:
|
| 251 |
-
return f"**{agent_name}**: I wasn't able to answer right now – can you try again?"
|
| 252 |
-
return f"**{agent_name}**: {answer}"
|
| 253 |
-
|
| 254 |
-
|
| 255 |
|
|
|
|
|
|
|
| 256 |
|
| 257 |
-
def run_interview_pipeline(respondent_agents_dict, last_active_agent, question, processor_llm):
|
| 258 |
-
logging.info(f"Received question: {question}")
|
| 259 |
agent_names = list(respondent_agents_dict.keys())
|
|
|
|
|
|
|
| 260 |
|
| 261 |
-
|
|
|
|
| 262 |
# Step 1: Parse question
|
|
|
|
| 263 |
parsed_questions = parse_question_with_llm(question, str(agent_names), processor_llm)
|
|
|
|
|
|
|
| 264 |
if not parsed_questions:
|
|
|
|
| 265 |
return ["**PreData Moderator**: No valid respondents were detected for this question."]
|
| 266 |
|
| 267 |
-
|
| 268 |
-
|
| 269 |
validated_questions = validate_question_topics(parsed_questions, processor_llm)
|
| 270 |
-
|
| 271 |
-
|
|
|
|
|
|
|
|
|
|
| 272 |
return ["**PreData Moderator**: The question is invalid. Please ask another question."]
|
| 273 |
-
parsed_questions = validated_questions
|
| 274 |
-
|
| 275 |
|
| 276 |
-
#
|
|
|
|
|
|
|
|
|
|
| 277 |
if len(parsed_questions) > 1:
|
| 278 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
|
| 280 |
|
| 281 |
-
# Handle "General" or "All"
|
| 282 |
-
# [Insert logic here – reuse your existing handling of General/All]
|
| 283 |
|
| 284 |
|
| 285 |
last_active_agent = list(parsed_questions.keys())
|
| 286 |
-
|
| 287 |
|
|
|
|
|
|
|
| 288 |
|
| 289 |
-
# === MAIN LOOP ===
|
| 290 |
for agent_name, agent_question in parsed_questions.items():
|
| 291 |
-
|
| 292 |
-
|
| 293 |
responses.append(f"**PreData Moderator**: {agent_name} is not a valid respondent.")
|
| 294 |
continue
|
| 295 |
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
communication_style = ""
|
| 301 |
|
| 302 |
-
|
| 303 |
question_task_description = f"""
|
| 304 |
You are {agent_name}. You are responding to a market research interview question. Your response must strictly follow the *style and tone* and *Hard Rules – You Must Follow These Without Exception* outlined below.
|
| 305 |
---
|
|
@@ -324,7 +307,7 @@ You are {agent_name}. You are responding to a market research interview question
|
|
| 324 |
-Example:
|
| 325 |
Q: Where are you from?
|
| 326 |
A: I’m from [city], [country](DO NOT ADD ANY EXTRA COMMENTS).
|
| 327 |
-
-For reflective or opinion-based questions (e.g., feelings, preferences, motivations), provide thoughtful but still clear and focused answers.
|
| 328 |
-Never repeat the question or add unrelated background information.
|
| 329 |
---
|
| 330 |
### **How to Answer:**
|
|
@@ -333,8 +316,8 @@ You are {agent_name}. You are responding to a market research interview question
|
|
| 333 |
- Adapt your **sentence structure, phrasing, and word choices** to match the intended communication style.
|
| 334 |
- If applicable, incorporate **culturally relevant expressions, regional nuances, or industry-specific terminology** that fit the given tone.
|
| 335 |
- **Adjust response length** based on the tone—**concise and direct** for casual styles, **structured and detailed** for professional styles.
|
| 336 |
-
- **Always answer in first person (
|
| 337 |
-
-Always answer as if you are the individual being directly spoken to. Use first-person language such as “I,” “me,” “my,” and “mine” in every response. Imagine you are having a real conversation — your tone should feel natural, personal, and authentic. Do not refer to yourself in the third person (e.g., “She is from Trichy” or “Meena likes…”). Avoid describing yourself as if someone else is talking about you.
|
| 338 |
-Everything you say should come from your own perspective, just like you would in everyday speech. The goal is to sound human, relatable, and direct — like you're truly present in the conversation.
|
| 339 |
---
|
| 340 |
### **Guidelines for Ensuring Authenticity & Alignment:**
|
|
@@ -354,7 +337,7 @@ You are {agent_name}. You are responding to a market research interview question
|
|
| 354 |
- If the tone is formal, use a structured and professional format.
|
| 355 |
- **Do not include emojis or hashtags in the response.**
|
| 356 |
- Maintain **narrative and thematic consistency** across all answers to simulate a coherent personality.
|
| 357 |
-
-**Personality Profile Alignment:
|
| 358 |
-Consider your assigned personality traits across these dimensions:
|
| 359 |
-Big Five Traits:
|
| 360 |
-Openness: Reflect your level of curiosity, creativity, and openness to new experiences
|
|
@@ -387,24 +370,84 @@ Your final answer should be **a well-structured response that directly answers t
|
|
| 387 |
**"{agent_question}"**
|
| 388 |
"""
|
| 389 |
|
| 390 |
-
|
| 391 |
question_task_expected_output = f"""
|
| 392 |
A culturally authentic and conversational response to the question: '{agent_question}'.
|
| 393 |
- The response must reflect the respondent's **local cultural background and geographic influences**, ensuring it aligns with their **speech patterns, preferences, and linguistic style**.
|
| 394 |
-
- The language must follow **strict British English spelling conventions**, ensuring it is **natural, personal, and free-flowing**, while strictly avoiding American spelling, phrasing, or grammar under any circumstances, regardless of the spelling, grammar, or vocabulary used in the input question.
|
| 395 |
- The response **must not introduce the respondent**, nor include placeholders like "[Your Name]" or "[Brand Name]".
|
| 396 |
-
- The response **must always be written in first person (
|
| 397 |
- The final output should be a **single, well-structured paragraph that directly answers the question** while staying fully aligned with the specified communication style.
|
| 398 |
"""
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
- **Correct (British):** organised, prioritise, minimise, realise, behaviour, centre, defence, travelling, practise (verb), licence (noun), programme, aeroplane.
|
| 44 |
- **Incorrect (American):** organized, prioritize, minimize, realize, behavior, center, defense, traveling, practice (verb and noun), license (noun), program, airplane.
|
| 45 |
6. Ensure that you follow the **Formatting Rules** exactly. THIS IS EXTREMELY IMPORTANT.
|
|
|
|
| 46 |
### Examples:
|
| 47 |
- "Sourav, do you agree with this topic?" → "Do you agree with this topic?"
|
| 48 |
- "What do you think about this topic, Divya?" → "What do you think about this topic?"
|
|
|
|
| 54 |
- "Divya, what did you learn from this program?" → "What did you learn from this programme?"
|
| 55 |
- "How do you stay organized, Rahul?" → "How do you stay organised?"
|
| 56 |
- "Meena, how do you balance work and traveling?" → "How do you balance work and travelling?"
|
|
|
|
| 57 |
### **Formatting Rules**:
|
| 58 |
For each question identified, respond using **only** the following format:
|
| 59 |
- Respondent: <Respondent Name>
|
|
|
|
| 204 |
|
| 205 |
|
| 206 |
|
| 207 |
+
def ask_interview_question(respondent_agents_dict, last_active_agent, question, processor_llm):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
"""
|
| 209 |
+
Handles both individual and group interview questions while tracking conversation flow.
|
| 210 |
+
Uses OpenAI's LLM to extract the intended respondent(s) and their specific question(s).
|
| 211 |
+
Uses Groq's LLM for response generation.
|
| 212 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
|
| 214 |
+
logging.info(f"START: Processing new interview question: {question}")
|
| 215 |
+
responses = []
|
| 216 |
|
|
|
|
|
|
|
| 217 |
agent_names = list(respondent_agents_dict.keys())
|
| 218 |
+
logging.info(f"Available respondents: {agent_names}")
|
| 219 |
+
print(f"Available respondents: {agent_names}")
|
| 220 |
|
| 221 |
+
# Use OpenAI LLM to parse questions into individual respondent-specific sub-questions and validate them
|
| 222 |
+
|
| 223 |
# Step 1: Parse question
|
| 224 |
+
logging.info("STEP 1: Parsing question with LLM...")
|
| 225 |
parsed_questions = parse_question_with_llm(question, str(agent_names), processor_llm)
|
| 226 |
+
logging.info(f"Parsed Questions Output: {parsed_questions}")
|
| 227 |
+
|
| 228 |
if not parsed_questions:
|
| 229 |
+
logging.warning("No questions were parsed from input.")
|
| 230 |
return ["**PreData Moderator**: No valid respondents were detected for this question."]
|
| 231 |
|
| 232 |
+
# Step 2: Validate question content (scope + spelling)
|
| 233 |
+
logging.info("STEP 2: Validating questions for topic relevance and British English...")
|
| 234 |
validated_questions = validate_question_topics(parsed_questions, processor_llm)
|
| 235 |
+
logging.info(f"Validated Questions: {validated_questions}")
|
| 236 |
+
|
| 237 |
+
for resp_name, extracted_question in validated_questions.items():
|
| 238 |
+
if extracted_question == "INVALID":
|
| 239 |
+
logging.warning(f"Invalid question detected for {resp_name}: {extracted_question}")
|
| 240 |
return ["**PreData Moderator**: The question is invalid. Please ask another question."]
|
|
|
|
|
|
|
| 241 |
|
| 242 |
+
# Use validated questions from this point on
|
| 243 |
+
parsed_questions = validated_questions
|
| 244 |
+
logging.info(f"Validated questions: {parsed_questions}")
|
| 245 |
+
|
| 246 |
if len(parsed_questions) > 1:
|
| 247 |
+
logging.warning("More than one respondent specified. Exiting function.")
|
| 248 |
+
return "**PreData Moderator**: Please ask each respondent one question at a time."
|
| 249 |
+
else:
|
| 250 |
+
print(f"Parsed questions are: {parsed_questions}")
|
| 251 |
+
|
| 252 |
+
if "General" in parsed_questions:
|
| 253 |
+
if "General" in parsed_questions:
|
| 254 |
+
if isinstance(last_active_agent, list) and all(name in agent_names for name in last_active_agent):
|
| 255 |
+
logging.info(f"General case detected. Continuing with last active agent: {last_active_agent}")
|
| 256 |
+
parsed_questions = {name: parsed_questions["General"] for name in last_active_agent}
|
| 257 |
+
else:
|
| 258 |
+
logging.info("General case detected without a valid previous active agent. Assigning question to all respondents.")
|
| 259 |
+
parsed_questions = {name: parsed_questions["General"] for name in agent_names}
|
| 260 |
+
elif "All" in parsed_questions:
|
| 261 |
+
logging.info("All case detected. Assigning question to all respondents.")
|
| 262 |
+
validated_question = parsed_questions["All"]
|
| 263 |
+
parsed_questions = {name: validated_question for name in agent_names}
|
| 264 |
|
| 265 |
|
|
|
|
|
|
|
| 266 |
|
| 267 |
|
| 268 |
last_active_agent = list(parsed_questions.keys())
|
| 269 |
+
logging.info(f"Final parsed questions: {parsed_questions}")
|
| 270 |
|
| 271 |
+
# Construct one crew and task for each agent and question
|
| 272 |
+
responses = []
|
| 273 |
|
|
|
|
| 274 |
for agent_name, agent_question in parsed_questions.items():
|
| 275 |
+
if agent_name not in respondent_agents_dict:
|
| 276 |
+
logging.warning(f"No valid respondent found for {agent_name}. Skipping.")
|
| 277 |
responses.append(f"**PreData Moderator**: {agent_name} is not a valid respondent.")
|
| 278 |
continue
|
| 279 |
|
| 280 |
+
respondent_agent = respondent_agents_dict[agent_name].get_agent()
|
| 281 |
+
user_profile = respondent_agents_dict[agent_name].get_user_profile()
|
| 282 |
+
|
| 283 |
+
# communication_style = user_profile.get_field("Communication", "Style")
|
| 284 |
communication_style = ""
|
| 285 |
|
|
|
|
| 286 |
question_task_description = f"""
|
| 287 |
You are {agent_name}. You are responding to a market research interview question. Your response must strictly follow the *style and tone* and *Hard Rules – You Must Follow These Without Exception* outlined below.
|
| 288 |
---
|
|
|
|
| 307 |
-Example:
|
| 308 |
Q: Where are you from?
|
| 309 |
A: I’m from [city], [country](DO NOT ADD ANY EXTRA COMMENTS).
|
| 310 |
+
-For reflective or opinion-based questions (e.g., feelings, preferences, motivations), provide thoughtful but still clear and focused answers.
|
| 311 |
-Never repeat the question or add unrelated background information.
|
| 312 |
---
|
| 313 |
### **How to Answer:**
|
|
|
|
| 316 |
- Adapt your **sentence structure, phrasing, and word choices** to match the intended communication style.
|
| 317 |
- If applicable, incorporate **culturally relevant expressions, regional nuances, or industry-specific terminology** that fit the given tone.
|
| 318 |
- **Adjust response length** based on the tone—**concise and direct** for casual styles, **structured and detailed** for professional styles.
|
| 319 |
+
- **Always answer in first person ("I", "my", "me", "mine", etc.) as if you are personally responding to the question. You are an individual representing yourself, not speaking in third person.**
|
| 320 |
+
-Always answer as if you are the individual being directly spoken to. Use first-person language such as “I,” “me,” “my,” and “mine” in every response. Imagine you are having a real conversation — your tone should feel natural, personal, and authentic. Do not refer to yourself in the third person (e.g., “She is from Trichy” or “Meena likes…”). Avoid describing yourself as if someone else is talking about you.
|
| 321 |
-Everything you say should come from your own perspective, just like you would in everyday speech. The goal is to sound human, relatable, and direct — like you're truly present in the conversation.
|
| 322 |
---
|
| 323 |
### **Guidelines for Ensuring Authenticity & Alignment:**
|
|
|
|
| 337 |
- If the tone is formal, use a structured and professional format.
|
| 338 |
- **Do not include emojis or hashtags in the response.**
|
| 339 |
- Maintain **narrative and thematic consistency** across all answers to simulate a coherent personality.
|
| 340 |
+
-**Personality Profile Alignment:**
|
| 341 |
-Consider your assigned personality traits across these dimensions:
|
| 342 |
-Big Five Traits:
|
| 343 |
-Openness: Reflect your level of curiosity, creativity, and openness to new experiences
|
|
|
|
| 370 |
**"{agent_question}"**
|
| 371 |
"""
|
| 372 |
|
|
|
|
| 373 |
question_task_expected_output = f"""
|
| 374 |
A culturally authentic and conversational response to the question: '{agent_question}'.
|
| 375 |
- The response must reflect the respondent's **local cultural background and geographic influences**, ensuring it aligns with their **speech patterns, preferences, and linguistic style**.
|
| 376 |
+
- The language must follow **strict British English spelling conventions**, ensuring it is **natural, personal, and free-flowing**, while strictly avoiding American spelling, phrasing, or grammar under any circumstances, regardless of the spelling, grammar, or vocabulary used in the input question.
|
| 377 |
- The response **must not introduce the respondent**, nor include placeholders like "[Your Name]" or "[Brand Name]".
|
| 378 |
+
- The response **must always be written in first person ("I", "my", "me", etc.) as if the respondent is personally answering the question directly. Third-person narration is never allowed.**
|
| 379 |
- The final output should be a **single, well-structured paragraph that directly answers the question** while staying fully aligned with the specified communication style.
|
| 380 |
"""
|
| 381 |
+
|
| 382 |
+
question_task = Task(
|
| 383 |
+
description=question_task_description,
|
| 384 |
+
expected_output=question_task_expected_output,
|
| 385 |
+
agent=respondent_agent
|
| 386 |
+
)
|
| 387 |
+
|
| 388 |
+
logging.debug(f"Created task for agent '{agent_name}' with description: {question_task_description}")
|
| 389 |
+
|
| 390 |
+
# Log before starting task execution
|
| 391 |
+
logging.info(f"Executing task for agent '{agent_name}'")
|
| 392 |
+
|
| 393 |
+
# Create a new crew for each agent-question pair
|
| 394 |
+
crew = Crew(
|
| 395 |
+
agents=[respondent_agent],
|
| 396 |
+
tasks=[question_task],
|
| 397 |
+
process=Process.sequential
|
| 398 |
+
)
|
| 399 |
+
logging.debug(f"Crew initialized for agent '{agent_name}' with 1 task and sequential process")
|
| 400 |
+
|
| 401 |
+
max_attempts = 3
|
| 402 |
+
attempt = 0
|
| 403 |
+
validated = False
|
| 404 |
+
validated_answer = None
|
| 405 |
+
while attempt < max_attempts and not validated:
|
| 406 |
+
try:
|
| 407 |
+
logging.info(f"Starting Response validation attempt {attempt+1} for agent '{agent_name}'")
|
| 408 |
+
crew_output = crew.kickoff()
|
| 409 |
+
logging.info(f"Task execution completed for agent '{agent_name}' (attempt {attempt+1})")
|
| 410 |
+
task_output = question_task.output
|
| 411 |
+
logging.debug(f"Raw output from agent '{agent_name}': {getattr(task_output, 'raw', str(task_output))}")
|
| 412 |
+
answer = task_output.raw if hasattr(task_output, 'raw') else str(task_output)
|
| 413 |
+
logging.info(f"Validating response for agent '{agent_name}' (attempt {attempt+1}): {answer}")
|
| 414 |
+
# Validate the response using validate_response from validation_utils
|
| 415 |
+
is_valid = validate_response(
|
| 416 |
+
question=agent_question,
|
| 417 |
+
answer=answer,
|
| 418 |
+
user_profile_str=str(user_profile),
|
| 419 |
+
fast_facts_str="",
|
| 420 |
+
interview_transcript_text="",
|
| 421 |
+
respondent_type=agent_name,
|
| 422 |
+
ai_evaluator_agent=None,
|
| 423 |
+
processor_llm=processor_llm
|
| 424 |
+
)
|
| 425 |
+
logging.info(f"Response Validation result for agent '{agent_name}' (attempt {attempt+1}): {is_valid}")
|
| 426 |
+
if is_valid:
|
| 427 |
+
validated = True
|
| 428 |
+
validated_answer = answer
|
| 429 |
+
logging.info(f"Response for agent '{agent_name}' passed validation on attempt {attempt+1}")
|
| 430 |
+
break
|
| 431 |
+
else:
|
| 432 |
+
attempt += 1
|
| 433 |
+
logging.warning(f"Response failed response validation for agent '{agent_name}' (attempt {attempt}). Retrying...")
|
| 434 |
+
except Exception as e:
|
| 435 |
+
logging.error(f"Error during task execution for agent '{agent_name}' (attempt {attempt+1}): {str(e)}", exc_info=True)
|
| 436 |
+
attempt += 1
|
| 437 |
+
# --- End validation and retry loop ---
|
| 438 |
+
|
| 439 |
+
if validated_answer:
|
| 440 |
+
formatted_response = f"**{agent_name}**: {validated_answer}"
|
| 441 |
+
responses.append(formatted_response)
|
| 442 |
+
logging.info(f"Validated response from agent '{agent_name}' added to responses")
|
| 443 |
+
else:
|
| 444 |
+
fallback_response = f"**PreData Moderator**: Unable to pass validation after {max_attempts} attempts for {agent_name}."
|
| 445 |
+
responses.append(fallback_response)
|
| 446 |
+
logging.warning(f"No validated output from agent '{agent_name}' after {max_attempts} attempts. Added fallback response.")
|
| 447 |
+
logging.info(f"All responses generated: {responses}")
|
| 448 |
+
|
| 449 |
+
if len(set(parsed_questions.values())) == 1:
|
| 450 |
+
combined_output = "\n\n".join(responses)
|
| 451 |
+
return [combined_output]
|
| 452 |
+
else:
|
| 453 |
+
return responses
|