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:
119
negot8/backend/features/marketplace.py
Normal file
119
negot8/backend/features/marketplace.py
Normal file
@@ -0,0 +1,119 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user