Files
B.Tech-Project-III/negot8/backend/features/marketplace.py
2026-04-05 00:43:23 +05:30

120 lines
5.2 KiB
Python

from features.base_feature import BaseFeature
from tools.tavily_search import TavilySearchTool
_tavily = TavilySearchTool()
class MarketplaceFeature(BaseFeature):
async def get_context(self, preferences_a: dict, preferences_b: dict, user_a_id: int = None, user_b_id: int = None) -> str:
"""
Fetch real market prices via Tavily so agents negotiate around
actual reference prices, not guesses.
"""
raw_a = preferences_a.get("raw_details", {})
raw_b = preferences_b.get("raw_details", {})
item = (
raw_a.get("item") or raw_b.get("item")
or preferences_a.get("goal", "item")[:60]
)
seller_min = raw_a.get("minimum_price") or raw_a.get("min_price") or raw_a.get("asking_price") or ""
seller_asking = raw_a.get("asking_price") or raw_a.get("price") or ""
buyer_max = raw_b.get("maximum_budget") or raw_b.get("max_budget") or raw_b.get("budget") or ""
buyer_offer = raw_b.get("offer_price") or raw_b.get("price") or ""
# Flip if B is selling
role_a = raw_a.get("role", "")
role_b = raw_b.get("role", "")
if role_b == "seller":
seller_min = raw_b.get("minimum_price") or raw_b.get("min_price") or ""
seller_asking = raw_b.get("asking_price") or raw_b.get("price") or ""
buyer_max = raw_a.get("maximum_budget") or raw_a.get("max_budget") or raw_a.get("budget") or ""
buyer_offer = raw_a.get("offer_price") or raw_a.get("price") or ""
market_text = ""
try:
query = f"{item} used price India 2026"
result = await _tavily.execute(query)
answer = result.get("answer", "")
results = result.get("results", [])[:3]
parts = []
if answer:
parts.append(f"Market summary: {answer[:300]}")
for r in results:
title = r.get("title", "")
content = r.get("content", "")[:120]
if title:
parts.append(f"{title}: {content}")
market_text = "\n".join(parts)
except Exception as e:
market_text = f"Market search unavailable ({e}). Use your knowledge of {item} pricing."
lines = [
"MARKETPLACE NEGOTIATION DOMAIN RULES:",
"• Seller must NOT go below their minimum price (hard constraint).",
"• Buyer must NOT exceed their maximum budget (hard constraint).",
"• Classic anchoring: seller starts at asking price, buyer starts with lower offer.",
"• Concede in diminishing increments (e.g., ₹3K, ₹2K, ₹1K).",
"• Delivery/pickup can be offered as a non-cash concession worth ₹500-1000.",
"• If gap > 20% after 3 rounds, propose splitting the difference or escalate.",
"• Cite the market price from the data below to justify your position.",
]
if item:
lines.append(f"\nItem being traded: {item}")
if seller_asking:
lines.append(f"Seller asking: ₹{seller_asking}")
if seller_min:
lines.append(f"Seller minimum (hard floor): ₹{seller_min}")
if buyer_max:
lines.append(f"Buyer maximum budget (hard ceiling): ₹{buyer_max}")
if buyer_offer:
lines.append(f"Buyer's opening offer: ₹{buyer_offer}")
if market_text:
lines.append(f"\nMARKET PRICE DATA (cite this):\n{market_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", "")
raw_a = preferences_a.get("raw_details", {})
raw_b = preferences_b.get("raw_details", {})
item = raw_a.get("item") or raw_b.get("item") or "Item"
if status == "escalated":
return (
f"⚠️ *{item} Deal — Human Decision Needed*\n\n"
f"_{summary}_\n\n"
f"Agents couldn't bridge the price gap in {rounds} round(s). "
f"Please negotiate directly."
)
agreed_price = (
details.get("agreed_price") or details.get("price")
or details.get("final_price") or details.get("amount")
or final.get("summary", "")
)
delivery = details.get("delivery") or details.get("handover") or ""
market_ref = details.get("market_price") or details.get("market_reference") or ""
lines = [f"🛒 *Deal Closed!*\n"]
lines.append(f"📦 *Item:* {item}")
if agreed_price:
lines.append(f"💰 *Agreed price:* ₹{agreed_price}")
if delivery:
lines.append(f"🚚 *Delivery/Handover:* {delivery}")
if market_ref:
lines.append(f"📊 *Market reference:* ₹{market_ref}")
lines.append(f"\n⏱ Deal closed in {rounds} round(s)")
if summary and summary != "Agreement reached":
lines.append(f"_{summary}_")
return "\n".join(lines)