mirror of
https://github.com/arkorty/B.Tech-Project-III.git
synced 2026-04-19 20:51:49 +00:00
init
This commit is contained in:
121
negot8/backend/features/collaborative.py
Normal file
121
negot8/backend/features/collaborative.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from features.base_feature import BaseFeature
|
||||
from tools.tavily_search import TavilySearchTool
|
||||
from tools.calculator import CalculatorTool
|
||||
from urllib.parse import quote as _url_quote
|
||||
|
||||
_tavily = TavilySearchTool()
|
||||
_calc = CalculatorTool()
|
||||
|
||||
|
||||
class CollaborativeFeature(BaseFeature):
|
||||
|
||||
async def get_context(self, preferences_a: dict, preferences_b: dict, user_a_id: int = None, user_b_id: int = None) -> str:
|
||||
"""
|
||||
Use Tavily to fetch REAL restaurant/activity/venue options matching
|
||||
both parties' preferences. Inject real names so agents cite real places.
|
||||
"""
|
||||
raw_a = preferences_a.get("raw_details", {})
|
||||
raw_b = preferences_b.get("raw_details", {})
|
||||
|
||||
decision_type = (
|
||||
raw_a.get("decision_type") or raw_b.get("decision_type")
|
||||
or preferences_a.get("goal", "")
|
||||
)
|
||||
location = (
|
||||
raw_a.get("location") or raw_b.get("location")
|
||||
or raw_a.get("city") or raw_b.get("city")
|
||||
or "Mumbai"
|
||||
)
|
||||
cuisine_a = raw_a.get("cuisine") or raw_a.get("food_preference") or ""
|
||||
cuisine_b = raw_b.get("cuisine") or raw_b.get("food_preference") or ""
|
||||
budget_a = raw_a.get("budget") or raw_a.get("budget_per_person") or ""
|
||||
budget_b = raw_b.get("budget") or raw_b.get("budget_per_person") or ""
|
||||
|
||||
# Build a smart Tavily query
|
||||
cuisine_part = f"{cuisine_a} or {cuisine_b}" if cuisine_a and cuisine_b else (cuisine_a or cuisine_b or "good")
|
||||
query = f"best {cuisine_part} restaurants in {location}"
|
||||
|
||||
tavily_text = ""
|
||||
try:
|
||||
result = await _tavily.execute(query)
|
||||
answer = result.get("answer", "")
|
||||
results = result.get("results", [])[:4]
|
||||
place_lines = []
|
||||
if answer:
|
||||
place_lines.append(f"AI Summary: {answer[:300]}")
|
||||
for r in results:
|
||||
title = r.get("title", "")
|
||||
content = r.get("content", "")[:150]
|
||||
if title:
|
||||
place_lines.append(f" • {title}: {content}")
|
||||
tavily_text = "\n".join(place_lines)
|
||||
except Exception as e:
|
||||
tavily_text = f"Search unavailable ({e}). Use your knowledge of {location} restaurants."
|
||||
|
||||
lines = [
|
||||
"COLLABORATIVE DECISION DOMAIN RULES:",
|
||||
"• ONLY recommend real venues from the search results below. Do NOT invent names.",
|
||||
"• Budget ceiling = the LOWER of both parties' budgets.",
|
||||
"• Both parties' dietary restrictions are absolute (hard constraints).",
|
||||
"• Aim for cuisine intersection first; if no overlap, find a multi-cuisine option.",
|
||||
"",
|
||||
f"Current decision type: {decision_type}",
|
||||
f"Location: {location}",
|
||||
]
|
||||
if cuisine_a:
|
||||
lines.append(f"Person A prefers: {cuisine_a}")
|
||||
if cuisine_b:
|
||||
lines.append(f"Person B prefers: {cuisine_b}")
|
||||
if budget_a:
|
||||
lines.append(f"Person A budget: ₹{budget_a}/person")
|
||||
if budget_b:
|
||||
lines.append(f"Person B budget: ₹{budget_b}/person")
|
||||
|
||||
if tavily_text:
|
||||
lines.append(f"\nREAL OPTIONS from web search (use these):\n{tavily_text}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def format_resolution(
|
||||
self, resolution: dict, preferences_a: dict, preferences_b: dict
|
||||
) -> str:
|
||||
status = resolution.get("status", "resolved")
|
||||
final = resolution.get("final_proposal", {})
|
||||
details = final.get("details", {})
|
||||
rounds = resolution.get("rounds_taken", "?")
|
||||
summary = resolution.get("summary", "")
|
||||
|
||||
if status == "escalated":
|
||||
return (
|
||||
f"⚠️ *Joint Decision — Your Input Needed*\n\n"
|
||||
f"_{summary}_\n\n"
|
||||
f"Agents proposed options but couldn't finalize. "
|
||||
f"Please pick from the options above."
|
||||
)
|
||||
|
||||
venue = (
|
||||
details.get("venue") or details.get("restaurant") or details.get("place")
|
||||
or details.get("recommendation") or final.get("summary", "")
|
||||
)
|
||||
cuisine = details.get("cuisine") or details.get("food_type") or ""
|
||||
price = details.get("price_range") or details.get("budget") or ""
|
||||
why = details.get("reason") or details.get("why") or summary
|
||||
alternatives = details.get("alternatives") or []
|
||||
|
||||
lines = ["🍽 *Decision Made!*\n"]
|
||||
if venue:
|
||||
venue_str = str(venue) if not isinstance(venue, str) else venue
|
||||
maps_url = f"https://maps.google.com/?q={_url_quote(venue_str)}"
|
||||
lines.append(f"📍 *Recommendation:* [{venue_str}]({maps_url})")
|
||||
if cuisine:
|
||||
lines.append(f"🍴 *Cuisine:* {cuisine}")
|
||||
if price:
|
||||
lines.append(f"💰 *Price range:* {price}")
|
||||
if why:
|
||||
lines.append(f"\n💬 _{why}_")
|
||||
if alternatives and isinstance(alternatives, list):
|
||||
alt_text = ", ".join(str(a) for a in alternatives[:2])
|
||||
lines.append(f"\n_Alternatives considered: {alt_text}_")
|
||||
lines.append(f"\n⏱ Decided in {rounds} round(s)")
|
||||
|
||||
return "\n".join(lines)
|
||||
Reference in New Issue
Block a user