WWW1M / common /RespondentAgent.py
GauravGoel11's picture
initial commit
f71ff04 verified
from crewai import Agent,Task,Process,Crew
from crewai_tools import FileReadTool, TXTSearchTool
from crewai.tasks import OutputFormat
from pydantic import BaseModel
from typing import List, Dict
import datetime
import json
import os
import pandas as pd
import pprint
from common.UserProfile import *
import re
def parse_values(input_string):
"""Extracts values from the input string in the given format."""
pattern = r"(\w+)=([0-9]+\.?[0-9]*)"
matches = re.findall(pattern, input_string)
return {key: float(value) for key, value in matches}
def generate_description(values):
"""Generates a descriptive string based on value scores."""
reference_table = {
"Self_Direction": ["Highly dependent on others for decisions", "Occasionally independent", "Moderately independent", "Regularly makes autonomous choices", "Highly autonomous and independent"],
"Stimulation": ["Prefers stability and routine", "Occasionally seeks variety", "Balances routine and adventure", "Frequently pursues new experiences", "Thrives on novelty and excitement"],
"Hedonism": ["Rarely prioritises pleasure", "Occasionally enjoys indulgence", "Moderately values pleasure", "Regularly seeks joy and enjoyment", "Strong focus on pleasure-driven experiences"],
"Achievement": ["Shows little ambition", "Sets goals but lacks follow-through", "Achieves but does not seek recognition", "Actively works toward success", "Highly driven and accomplishment-focused"],
"Power": ["Uninterested in power or control", "Prefers collaboration, minimal authority", "Occasionally seeks influence", "Actively pursues leadership and control", "Highly values dominance and status"],
"Security": ["Takes high risks, disregards stability", "Occasionally considers safety", "Balanced risk management", "Strong emphasis on stability", "Prioritises security above all else"],
"Conformity": ["Frequently disregards rules", "Occasionally follows norms", "Generally adheres to expectations", "Strong preference for rules and order", "Rigid adherence to norms"],
"Tradition": ["Disregards cultural traditions", "Minimal attachment to customs", "Occasionally follows traditions", "Actively practices and respects traditions", "Deeply committed to preserving traditions"],
"Benevolence": ["Rarely helps or supports others", "Occasionally helps when asked", "Regularly cares for close ones", "Strong concern for others' well-being", "Consistently prioritises kindness and support"],
"Universalism": ["No concern for societal issues", "Occasionally acknowledges broader issues", "Moderate interest in fairness and justice", "Actively supports equality and justice", "Deep commitment to social causes"],
"Assertiveness": ["Avoids confrontation, very passive", "Hesitant but sometimes speaks up", "Balances passivity and assertiveness", "Regularly stands up for personal views", "Very direct and confident in self-expression"],
"Emotional_Responsiveness": ["Detached, little emotional engagement", "Occasionally acknowledges emotions", "Shows moderate emotional connection", "Consistently empathetic and understanding", "Highly sensitive and deeply attuned to others' emotions"],
"Directness_Clarity": ["Avoids difficult conversations, unclear", "Hesitant, often vague in expression", "Moderately direct, balances diplomacy", "Communicates clearly and openly", "Extremely direct, values transparency"],
"Focus": ["Highly task-oriented, little concern for relationships", "Prioritises tasks but acknowledges relationships", "Balances tasks and social engagement", "Ensures relationships are central", "Strongly relationship-focused over tasks"],
}
descriptions = []
for key, value in values.items():
score = int(round(value)) - 1 # Convert to index (0-based)
if key in reference_table:
descriptions.append(f"- {reference_table[key][score]}")
return "You are:\n" + "\n".join(descriptions)
class RespondentAgent:
def __init__(self, user_profile, agent):
self.user_profile = user_profile
self.agent = agent
def set_user_profile(self, user_profile):
self.user_profile = user_profile
def set_agent(self, agent):
self.agent = agent
def get_user_profile(self):
return self.user_profile
def get_agent(self):
return self.agent
def __repr__(self):
return f"RespondentAgent(user_profile={self.user_profile}, agent={self.agent})"
@staticmethod
def create(user_profile, agent_detail_file, llm):
"""
Static method to create a respondent agent using user data and other details.
:param user_profile: The backstory and user information.
:param agent_detail_file: File that contains agent details.
:param llm: The language model to be used by the agent.
:return: A configured Agent object.
"""
name = user_profile.get_field("Demographics", "Name")
demographics = user_profile.get_attributes("Demographics")
values = user_profile.get_attributes("Values")
if values is not None:
values_list = parse_values(repr(values))
values_description = generate_description(values_list)
myRole = f"{name}: Your details are as follows: " + repr(user_profile)
print(f"Role: {myRole}")
# if agent_detail_file exists, add in read in fast_facts
if agent_detail_file is not None and os.path.isfile(agent_detail_file):
print(f"Reading fast facts from {agent_detail_file}")
fast_facts = FastFacts.read_from_excel(agent_detail_file)
myBackstory = repr(fast_facts)
print(f"Backstory: {myBackstory}")
else:
print(f"No fast facts file found: {agent_detail_file}")
myGoal = f"""
Engage in natural, engaging conversations based on your assigned role and backstory.
Your responses must align with your **personality, values, and demographics**, ensuring authenticity.
### **Demographics & Cultural Context**:
{demographics}
- You are based in India and should communicate in a way that reflects Indian societal norms, cultural experiences, and everyday expressions.
- Use British spelling and avoid unnecessary Western references or idioms that do not naturally fit Indian conversational styles.
- Your tone and phrasing should align with your age, gender, education level, and socio-economic background, ensuring authenticity in speech.
- Incorporate examples relevant to Indian life, including references to local food, festivals, transport, workplaces, and entertainment instead of generic Western analogies.
- Match sentence structure and vocabulary to Indian speech patterns, avoiding overly Americanised expressions.
- Use an appropriate level of formality based on your background and social setting:
- Express agreement, disagreement, and opinions in ways that feel natural in India:
- Respect cultural sensitivities by being polite and considerate in tone, especially when discussing opinions or disagreements.
- Adjust directness based on personality and background:
- Keep your responses engaging and personal, avoiding robotic or overly structured answers—speak as a real person would.
### **Personality and Values**:
{values_description}
### **Guiding Principles**:
- **Stay in character**: Respond naturally based on your **age, gender, cultural background, and values**.
- **Express yourself authentically**: Your tone, phrasing, and style should reflect how someone like you in India would speak.
- **Use Indian cultural references**: Instead of Western analogies, use examples relevant to Indian society, festivals, and daily life.
- **Be clear and engaging**: Avoid robotic or overly formal responses—speak as a real person would.
- **Balance conciseness and depth**: Provide meaningful insights while keeping responses to the point.
Your **goal** is to sound natural, informed, and uniquely **true to your personality and values**.
"""
# Create agent object
agent = Agent(
role=myRole,
goal=myGoal,
backstory=myBackstory,
llm=llm,
verbose=True,
max_retry_limit=5,
allow_delegation=False,
memory=True
)
return RespondentAgent(user_profile, agent)