Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import duckdb
|
3 |
+
import pandas as pd
|
4 |
+
from datetime import datetime
|
5 |
+
import random
|
6 |
+
|
7 |
+
# --- MCP Registry ---
|
8 |
+
class MCP:
|
9 |
+
def __init__(self):
|
10 |
+
self.agents = {}
|
11 |
+
self.services = {} # To map service types to agent names
|
12 |
+
|
13 |
+
def register_agent(self, name, agent, services=None):
|
14 |
+
self.agents[name] = agent
|
15 |
+
if services:
|
16 |
+
for service in services:
|
17 |
+
if service not in self.services:
|
18 |
+
self.services[service] = []
|
19 |
+
self.services[service].append(name)
|
20 |
+
|
21 |
+
def get_agent(self, name):
|
22 |
+
return self.agents.get(name)
|
23 |
+
|
24 |
+
def find_agents_by_service(self, service_type):
|
25 |
+
return self.services.get(service_type, [])
|
26 |
+
|
27 |
+
mcp_registry = MCP()
|
28 |
+
|
29 |
+
# --- Data Management Agent ---
|
30 |
+
class DataManagementAgent:
|
31 |
+
def __init__(self, db_path="market_ai_duckdb.db"):
|
32 |
+
self.conn = duckdb.connect(db_path)
|
33 |
+
self._create_tables()
|
34 |
+
|
35 |
+
def _create_tables(self):
|
36 |
+
try:
|
37 |
+
self.conn.execute("""
|
38 |
+
CREATE TABLE IF NOT EXISTS demand_forecasts (
|
39 |
+
item_name VARCHAR,
|
40 |
+
location VARCHAR,
|
41 |
+
forecast_date VARCHAR,
|
42 |
+
predicted_demand INTEGER
|
43 |
+
);
|
44 |
+
""")
|
45 |
+
except Exception as e:
|
46 |
+
print(f"Error creating demand_forecasts table: {e}")
|
47 |
+
|
48 |
+
try:
|
49 |
+
self.conn.execute("""
|
50 |
+
CREATE TABLE IF NOT EXISTS consumer_requests (
|
51 |
+
id INTEGER,
|
52 |
+
consumer_name VARCHAR,
|
53 |
+
item_name VARCHAR,
|
54 |
+
requested_qty INTEGER,
|
55 |
+
unit VARCHAR,
|
56 |
+
required_date VARCHAR
|
57 |
+
);
|
58 |
+
""")
|
59 |
+
except Exception as e:
|
60 |
+
print(f"Error creating consumer_requests table: {e}")
|
61 |
+
|
62 |
+
try:
|
63 |
+
self.conn.execute("""
|
64 |
+
CREATE TABLE IF NOT EXISTS farmer_stock (
|
65 |
+
id INTEGER,
|
66 |
+
farmer_name VARCHAR,
|
67 |
+
item_name VARCHAR,
|
68 |
+
available_qty INTEGER,
|
69 |
+
unit VARCHAR,
|
70 |
+
quality_grade VARCHAR,
|
71 |
+
available_date VARCHAR
|
72 |
+
);
|
73 |
+
""")
|
74 |
+
except Exception as e:
|
75 |
+
print(f"Error creating farmer_stock table: {e}")
|
76 |
+
self.conn.commit()
|
77 |
+
|
78 |
+
|
79 |
+
def insert(self, table_name, data):
|
80 |
+
cursor = self.conn.cursor()
|
81 |
+
placeholders = ', '.join(['?'] * len(data))
|
82 |
+
query = f"INSERT INTO {table_name} VALUES ({placeholders})"
|
83 |
+
try:
|
84 |
+
cursor.execute(query, data)
|
85 |
+
self.conn.commit()
|
86 |
+
except Exception as e:
|
87 |
+
print(f"Error inserting into {table_name}: {e}")
|
88 |
+
|
89 |
+
def fetch(self, query):
|
90 |
+
try:
|
91 |
+
df = self.conn.execute(query).df()
|
92 |
+
return df
|
93 |
+
except Exception as e:
|
94 |
+
print(f"Error fetching data: {e}")
|
95 |
+
return pd.DataFrame()
|
96 |
+
|
97 |
+
data_agent = DataManagementAgent()
|
98 |
+
mcp_registry.register_agent("data_agent", data_agent, services=["data_storage"])
|
99 |
+
|
100 |
+
# --- Demand Forecasting Agent (Simplified) ---
|
101 |
+
class DemandForecastingAgent:
|
102 |
+
def __init__(self, data_agent):
|
103 |
+
self.data_agent = data_agent
|
104 |
+
|
105 |
+
def predict_demand(self, item_name, location, forecast_date):
|
106 |
+
predicted_demand = random.randint(10, 100)
|
107 |
+
self.data_agent.insert("demand_forecasts", (item_name, location, forecast_date, predicted_demand))
|
108 |
+
return f"Predicted demand for {item_name} in {location} on {forecast_date}: {predicted_demand}"
|
109 |
+
|
110 |
+
demand_forecaster = DemandForecastingAgent(data_agent)
|
111 |
+
mcp_registry.register_agent("demand_forecaster", demand_forecaster, services=["demand_forecasting"])
|
112 |
+
|
113 |
+
# --- Vendor Agent (Illustrative) ---
|
114 |
+
class VendorAgent:
|
115 |
+
def __init__(self, mcp_registry):
|
116 |
+
self.mcp_registry = mcp_registry
|
117 |
+
|
118 |
+
def get_demand_forecast(self, item_name, location, forecast_date):
|
119 |
+
forecasting_agents = self.mcp_registry.find_agents_by_service("demand_forecasting")
|
120 |
+
if forecasting_agents:
|
121 |
+
forecaster_name = forecasting_agents[0]
|
122 |
+
forecaster = self.mcp_registry.get_agent(forecaster_name)
|
123 |
+
return forecaster.predict_demand(item_name, location, forecast_date)
|
124 |
+
else:
|
125 |
+
return "No demand forecasting agent available."
|
126 |
+
|
127 |
+
vendor_agent = VendorAgent(mcp_registry)
|
128 |
+
mcp_registry.register_agent("vendor_agent", vendor_agent)
|
129 |
+
|
130 |
+
# --- Consumer Agent ---
|
131 |
+
class ConsumerAgent:
|
132 |
+
def __init__(self, data_agent):
|
133 |
+
self.data_agent = data_agent
|
134 |
+
|
135 |
+
def submit_request(self, consumer_name, item_name, requested_qty, unit, required_date):
|
136 |
+
data = (int(datetime.now().timestamp()), consumer_name, item_name, requested_qty, unit, required_date)
|
137 |
+
self.data_agent.insert("consumer_requests", data)
|
138 |
+
return "Consumer request submitted successfully."
|
139 |
+
|
140 |
+
consumer_agent = ConsumerAgent(data_agent)
|
141 |
+
mcp_registry.register_agent("consumer_agent", consumer_agent, services=["consumer_request_submission"])
|
142 |
+
|
143 |
+
# --- Farmer Agent ---
|
144 |
+
class FarmerAgent:
|
145 |
+
def __init__(self, data_agent):
|
146 |
+
self.data_agent = data_agent
|
147 |
+
|
148 |
+
def submit_stock(self, farmer_name, item_name, available_qty, unit, quality_grade, available_date):
|
149 |
+
data = (int(datetime.now().timestamp()), farmer_name, item_name, available_qty, unit, quality_grade, available_date)
|
150 |
+
self.data_agent.insert("farmer_stock", data)
|
151 |
+
return "Farmer stock submitted successfully."
|
152 |
+
|
153 |
+
farmer_agent = FarmerAgent(data_agent)
|
154 |
+
mcp_registry.register_agent("farmer_agent", farmer_agent, services=["farmer_stock_submission"])
|
155 |
+
|
156 |
+
# --- Matching Agent ---
|
157 |
+
class MatchingAgent:
|
158 |
+
def __init__(self, data_agent):
|
159 |
+
self.data_agent = data_agent
|
160 |
+
|
161 |
+
def view_matches(self):
|
162 |
+
query = """
|
163 |
+
SELECT c.consumer_name, c.item_name, c.requested_qty, c.unit AS consumer_unit, c.required_date,
|
164 |
+
f.farmer_name, f.available_qty, f.unit AS farmer_unit, f.quality_grade, f.available_date
|
165 |
+
FROM consumer_requests c
|
166 |
+
LEFT JOIN farmer_stock f ON c.item_name = f.item_name AND c.unit = f.unit
|
167 |
+
WHERE c.required_date <= f.available_date
|
168 |
+
"""
|
169 |
+
df = self.data_agent.fetch(query)
|
170 |
+
return df
|
171 |
+
|
172 |
+
matching_agent = MatchingAgent(data_agent)
|
173 |
+
mcp_registry.register_agent("matching_agent", matching_agent, services=["market_matching"])
|
174 |
+
|
175 |
+
# --- Pre-Booking Agent ---
|
176 |
+
class PreBookingAgent:
|
177 |
+
def pre_book_item(self, consumer_name, item_name):
|
178 |
+
return f"{consumer_name} pre-booked {item_name}. Please proceed to checkout during market day."
|
179 |
+
|
180 |
+
prebooking_agent = PreBookingAgent()
|
181 |
+
mcp_registry.register_agent("prebooking_agent", prebooking_agent, services=["pre_booking"])
|
182 |
+
|
183 |
+
# --- GRADIO UI ---
|
184 |
+
def submit_consumer_ui(consumer_name, item_name, requested_qty, unit, required_date):
|
185 |
+
agent = mcp_registry.get_agent("consumer_agent")
|
186 |
+
return agent.submit_request(consumer_name, item_name, requested_qty, unit, required_date)
|
187 |
+
|
188 |
+
def submit_farmer_ui(farmer_name, item_name, available_qty, unit, quality_grade, available_date):
|
189 |
+
agent = mcp_registry.get_agent("farmer_agent")
|
190 |
+
return agent.submit_stock(farmer_name, item_name, available_qty, unit, quality_grade, available_date)
|
191 |
+
|
192 |
+
def view_market_matches_ui():
|
193 |
+
agent = mcp_registry.get_agent("matching_agent")
|
194 |
+
return agent.view_matches()
|
195 |
+
|
196 |
+
def pre_book_item_ui(consumer_name, item_name):
|
197 |
+
agent = mcp_registry.get_agent("prebooking_agent")
|
198 |
+
return agent.pre_book_item(consumer_name, item_name)
|
199 |
+
|
200 |
+
def get_demand_forecast_ui(item_name, location, forecast_date):
|
201 |
+
vendor = mcp_registry.get_agent("vendor_agent")
|
202 |
+
return vendor.get_demand_forecast(item_name, location, forecast_date)
|
203 |
+
|
204 |
+
with gr.Blocks() as app:
|
205 |
+
gr.Markdown("## Agentic AI Market App with MCP")
|
206 |
+
|
207 |
+
with gr.Tab("Consumer Request"):
|
208 |
+
uid = gr.Textbox(label="Consumer Name")
|
209 |
+
item = gr.Textbox(label="Item Name")
|
210 |
+
qty = gr.Number(label="Quantity Required")
|
211 |
+
unit = gr.Textbox(label="Unit (e.g., kg, liters)")
|
212 |
+
req_date = gr.Textbox(label="Required Date (YYYY-MM-DD)")
|
213 |
+
consumer_btn = gr.Button("Submit Request")
|
214 |
+
consumer_output = gr.Textbox()
|
215 |
+
consumer_btn.click(submit_consumer_ui, inputs=[uid, item, qty, unit, req_date], outputs=consumer_output)
|
216 |
+
|
217 |
+
with gr.Tab("Farmer Stock"):
|
218 |
+
fid = gr.Textbox(label="Farmer Name")
|
219 |
+
item_stock = gr.Textbox(label="Item Name")
|
220 |
+
qty_stock = gr.Number(label="Available Quantity")
|
221 |
+
unit_stock = gr.Textbox(label="Unit (e.g., kg, liters)")
|
222 |
+
quality = gr.Textbox(label="Quality Grade")
|
223 |
+
avail_date = gr.Textbox(label="Available Date (YYYY-MM-DD)")
|
224 |
+
farmer_btn = gr.Button("Submit Stock")
|
225 |
+
farmer_output = gr.Textbox()
|
226 |
+
farmer_btn.click(submit_farmer_ui, inputs=[fid, item_stock, qty_stock, unit_stock, quality, avail_date], outputs=farmer_output)
|
227 |
+
|
228 |
+
with gr.Tab("Market Matches"):
|
229 |
+
match_btn = gr.Button("View Matches")
|
230 |
+
match_output = gr.Dataframe()
|
231 |
+
match_btn.click(view_market_matches_ui, outputs=match_output)
|
232 |
+
|
233 |
+
with gr.Tab("Pre-Booking"):
|
234 |
+
consumer_name_prebook = gr.Textbox(label="Consumer Name")
|
235 |
+
item_name_prebook = gr.Textbox(label="Item Name")
|
236 |
+
prebook_btn = gr.Button("Pre-Book Item")
|
237 |
+
prebook_output = gr.Textbox()
|
238 |
+
prebook_btn.click(pre_book_item_ui, inputs=[consumer_name_prebook, item_name_prebook], outputs=prebook_output)
|
239 |
+
|
240 |
+
with gr.Tab("Vendor Services"):
|
241 |
+
item_forecast = gr.Textbox(label="Item Name")
|
242 |
+
location_forecast = gr.Textbox(label="Location")
|
243 |
+
date_forecast = gr.Textbox(label="Forecast Date (YYYY-MM-DD)")
|
244 |
+
forecast_btn = gr.Button("Get Demand Forecast")
|
245 |
+
forecast_output = gr.Textbox()
|
246 |
+
forecast_btn.click(get_demand_forecast_ui, inputs=[item_forecast, location_forecast, date_forecast], outputs=forecast_output)
|
247 |
+
|
248 |
+
app.launch()
|