mirror of
https://github.com/arkorty/B.Tech-Project-III.git
synced 2026-04-19 20:51:49 +00:00
126 lines
5.3 KiB
Python
126 lines
5.3 KiB
Python
import asyncio
|
|
import json
|
|
from agents.negotiator_agent import NegotiatorAgent
|
|
import database as db
|
|
|
|
async def run_negotiation(negotiation_id: str, preferences_a: dict, preferences_b: dict,
|
|
user_a_id: int, user_b_id: int, feature_type: str,
|
|
personality_a: str = "balanced", personality_b: str = "balanced",
|
|
on_round_update=None, on_resolution=None,
|
|
feature_context: str = ""):
|
|
"""
|
|
Main negotiation loop with personality-aware agents and analytics tracking.
|
|
"""
|
|
await db.update_negotiation_status(negotiation_id, "active")
|
|
|
|
# Create personality-aware negotiators
|
|
negotiator_a = NegotiatorAgent(personality=personality_a)
|
|
negotiator_b = NegotiatorAgent(personality=personality_b)
|
|
|
|
current_proposal = None
|
|
max_rounds = 7
|
|
satisfaction_timeline = []
|
|
|
|
for round_num in range(1, max_rounds + 1):
|
|
await asyncio.sleep(1.5) # Rate limit protection for Gemini
|
|
|
|
if round_num == 1:
|
|
response = await negotiator_a.generate_initial_proposal(
|
|
my_preferences=preferences_a, feature_type=feature_type,
|
|
feature_context=feature_context
|
|
)
|
|
proposer_id = user_a_id
|
|
elif round_num % 2 == 0:
|
|
response = await negotiator_b.evaluate_and_respond(
|
|
received_proposal=current_proposal, my_preferences=preferences_b,
|
|
feature_type=feature_type, round_number=round_num,
|
|
feature_context=feature_context
|
|
)
|
|
proposer_id = user_b_id
|
|
else:
|
|
response = await negotiator_a.evaluate_and_respond(
|
|
received_proposal=current_proposal, my_preferences=preferences_a,
|
|
feature_type=feature_type, round_number=round_num,
|
|
feature_context=feature_context
|
|
)
|
|
proposer_id = user_a_id
|
|
|
|
# Handle errors
|
|
if "error" in response:
|
|
response = {
|
|
"action": "counter" if round_num < max_rounds else "escalate",
|
|
"proposal": current_proposal or {"summary": "Let's discuss further", "details": {}},
|
|
"satisfaction_score": 50, "reasoning": "Agent encountered an issue",
|
|
"concessions_made": [], "concessions_requested": []
|
|
}
|
|
|
|
action = response.get("action", "counter")
|
|
current_proposal = response.get("proposal", {})
|
|
satisfaction = response.get("satisfaction_score", 50)
|
|
concessions = response.get("concessions_made", [])
|
|
|
|
# Track satisfaction for analytics
|
|
# The proposer's score is the one returned; estimate the other party's
|
|
if proposer_id == user_a_id:
|
|
sat_a, sat_b = satisfaction, max(30, 100 - satisfaction * 0.4)
|
|
else:
|
|
sat_b, sat_a = satisfaction, max(30, 100 - satisfaction * 0.4)
|
|
|
|
satisfaction_timeline.append({
|
|
"round": round_num, "score_a": sat_a, "score_b": sat_b
|
|
})
|
|
|
|
# Save round with analytics data
|
|
await db.save_round(
|
|
negotiation_id=negotiation_id, round_number=round_num,
|
|
proposer_id=proposer_id, proposal=response,
|
|
response_type=action, reasoning=response.get("reasoning", ""),
|
|
satisfaction_a=sat_a, satisfaction_b=sat_b,
|
|
concessions_made=concessions
|
|
)
|
|
|
|
# Notify via callback
|
|
round_data = {
|
|
"negotiation_id": negotiation_id, "round_number": round_num,
|
|
"action": action, "proposal": current_proposal,
|
|
"satisfaction_score": satisfaction, "reasoning": response.get("reasoning", ""),
|
|
"proposer_id": proposer_id,
|
|
"satisfaction_a": sat_a, "satisfaction_b": sat_b
|
|
}
|
|
if on_round_update:
|
|
await on_round_update(round_data)
|
|
|
|
# Check outcome
|
|
if action == "accept":
|
|
resolution = {
|
|
"status": "resolved", "final_proposal": current_proposal,
|
|
"rounds_taken": round_num, "summary": current_proposal.get("summary", "Agreement reached"),
|
|
"satisfaction_timeline": satisfaction_timeline
|
|
}
|
|
await db.update_negotiation_status(negotiation_id, "resolved", resolution)
|
|
if on_resolution:
|
|
await on_resolution(resolution)
|
|
return resolution
|
|
|
|
if action == "escalate":
|
|
resolution = {
|
|
"status": "escalated", "final_proposal": current_proposal,
|
|
"rounds_taken": round_num, "summary": "Agents couldn't fully agree. Options for human decision.",
|
|
"satisfaction_timeline": satisfaction_timeline
|
|
}
|
|
await db.update_negotiation_status(negotiation_id, "escalated", resolution)
|
|
if on_resolution:
|
|
await on_resolution(resolution)
|
|
return resolution
|
|
|
|
# Exhausted rounds
|
|
resolution = {
|
|
"status": "escalated", "final_proposal": current_proposal,
|
|
"rounds_taken": max_rounds, "summary": "Max rounds reached. Best proposal for human decision.",
|
|
"satisfaction_timeline": satisfaction_timeline
|
|
}
|
|
await db.update_negotiation_status(negotiation_id, "escalated", resolution)
|
|
if on_resolution:
|
|
await on_resolution(resolution)
|
|
return resolution
|