File size: 8,806 Bytes
93d806b 138ff91 c3ed5c3 c281029 db2d72c b8a1d5c 138ff91 9441e7e 8f715b7 02813bf a9a3550 901f984 2ee34e0 1b59ee1 f86003d 3fa47c1 93d806b 138ff91 93d806b 8818cad 9441e7e c281029 8f715b7 c281029 02813bf a9a3550 c729264 6425363 901f984 2ee34e0 1b59ee1 f86003d 3fa47c1 02813bf c3ed5c3 8818cad c3ed5c3 8f715b7 8818cad c3ed5c3 8818cad c3ed5c3 8818cad c3ed5c3 8818cad c3ed5c3 a222658 f86003d 8818cad c3ed5c3 8818cad c3ed5c3 8818cad c3ed5c3 8818cad c3ed5c3 8818cad c3ed5c3 8818cad c3ed5c3 8818cad c3ed5c3 8818cad db2d72c a222658 02813bf 8f715b7 02813bf 8f715b7 02813bf 8f715b7 02813bf a9a3550 02813bf f86003d 02813bf 8f715b7 8818cad f86003d 8f715b7 e797a33 3859ff0 8818cad 1cba26d 8818cad 8f715b7 8818cad a222658 8f715b7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | import gradio as gr
import os
import psycopg2
import json
import shopify
import threading
import select
import psycopg2.extensions
from datetime import datetime
from openai import OpenAI
from dotenv import load_dotenv
from hubspot import HubSpot
from orchestrator import Orchestrator
from ucp_wrapper import ucp_get_order_details
from shopify_tools import get_product_details
from research_tools import web_search, summarize_content, analyze_product_trends
from fulfillment_tools import fulfill_shopify_order
from product_builder_tools import create_shopify_product
from email_tools import list_emails, send_email
from auditor_tools import check_margin, log_audit_event
from supplier_tools import evaluate_supplier, log_evaluation
# Load environment variables
load_dotenv()
# Initialize Clients
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
hubspot = HubSpot(access_token=os.getenv("HUBSPOT_ACCESS_TOKEN", ""))
shopify_session = shopify.Session(os.getenv("SHOPIFY_SHOP_URL", ""), "2024-04", os.getenv("SHOPIFY_ACCESS_TOKEN", ""))
shopify.ShopifyResource.activate_session(shopify_session)
orchestrator = Orchestrator()
# Map tool names to functions
tool_map = {
"ucp_get_order_details": ucp_get_order_details,
"get_product_details": get_product_details,
"web_search": web_search,
"summarize_content": summarize_content,
"analyze_product_trends": analyze_product_trends,
"fulfill_shopify_order": fulfill_shopify_order,
"create_shopify_product": create_shopify_product,
"list_emails": list_emails,
"send_email": send_email,
"check_margin": check_margin,
"log_audit_event": log_audit_event,
"evaluate_supplier": evaluate_supplier,
"log_evaluation": log_evaluation
}
# Database Manager (Supabase/PostgreSQL)
class DatabaseManager:
def __init__(self):
self.db_url = os.getenv("DATABASE_URL")
self._init_db()
def _get_conn(self):
return psycopg2.connect(self.db_url)
def _init_db(self):
conn = self._get_conn()
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS sessions (id SERIAL PRIMARY KEY, name TEXT, created_at TIMESTAMP)")
cursor.execute("""CREATE TABLE IF NOT EXISTS messages
(id SERIAL PRIMARY KEY, session_id INTEGER, role TEXT, content TEXT, timestamp TIMESTAMP)""")
cursor.execute("""CREATE TABLE IF NOT EXISTS research_reports
(id SERIAL PRIMARY KEY, session_id INTEGER, topic TEXT, content TEXT, timestamp TIMESTAMP)""")
# Create transaction_logs table if not exists
cursor.execute("""CREATE TABLE IF NOT EXISTS transaction_logs (
id SERIAL PRIMARY KEY, session_id INTEGER, agent_name TEXT, tool_name TEXT,
input_data JSONB, output_data JSONB, is_compliant BOOLEAN DEFAULT TRUE, timestamp TIMESTAMP DEFAULT NOW())""")
conn.commit()
conn.close()
def create_session(self, name):
conn = self._get_conn()
cursor = conn.cursor()
cursor.execute("INSERT INTO sessions (name, created_at) VALUES (%s, %s) RETURNING id", (name, datetime.now()))
session_id = cursor.fetchone()[0]
conn.commit()
conn.close()
return session_id
def get_sessions(self):
conn = self._get_conn()
cursor = conn.cursor()
cursor.execute("SELECT id, name FROM sessions ORDER BY created_at DESC")
sessions = cursor.fetchall()
conn.close()
return sessions
def save_message(self, session_id, role, content):
conn = self._get_conn()
cursor = conn.cursor()
cursor.execute("INSERT INTO messages (session_id, role, content, timestamp) VALUES (%s, %s, %s, %s)",
(session_id, role, content, datetime.now()))
conn.commit()
conn.close()
def get_history(self, session_id):
if not session_id: return []
conn = self._get_conn()
cursor = conn.cursor()
cursor.execute("SELECT role, content FROM messages WHERE session_id = %s ORDER BY timestamp ASC", (session_id,))
rows = cursor.fetchall()
conn.close()
return [(r[1] if r[0] == 'user' else None, r[1] if r[0] == 'assistant' else None) for r in rows]
db = DatabaseManager()
# --- Real-time Webhook Listener ---
def listen_for_webhooks():
conn = psycopg2.connect(os.getenv("DATABASE_URL"))
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cursor = conn.cursor()
cursor.execute("LISTEN new_webhook;")
print("Agent listening for webhooks...")
while True:
if select.select([conn], [], [], 5) == ([], [], []):
continue
conn.poll()
while conn.notifies:
notify = conn.notifies.pop(0)
event_data = json.loads(notify.payload)
print(f"New Webhook Received: {event_data['event_type']}")
# Here you would route this event to your agents
# orchestrator.process_event(event_data)
# Start listener in a background thread
threading.Thread(target=listen_for_webhooks, daemon=True).start()
# Tool Implementation for Storefront
def render_storefront_component(component_type, product_handle):
store_domain = os.getenv("SHOPIFY_SHOP_URL", "")
return f"""
<script src="https://cdn.shopify.com/s/assets/storefront/load-components.js"></script>
<shopify-context shop-url="{store_domain}"></shopify-context>
<{component_type} handle="{product_handle}"></{component_type}>
"""
# Chat Logic with Dynamic Orchestration & Tool Calling
def chat_wrapper(message, history, session_id, model):
if not message or not session_id: return "", history
db.save_message(session_id, "user", message)
# 1. Orchestrate: Identify Agent and Config
agent_key = orchestrator.get_agent_for_intent(message)
sys_prompt, tools = orchestrator.get_agent_config(agent_key)
messages = [{"role": "system", "content": sys_prompt}] + [{"role": h[0] and "user" or "assistant", "content": h[0] or h[1]} for h in history if h[0] or h[1]]
messages.append({"role": "user", "content": message})
# 2. First Call to OpenAI
response = openai_client.chat.completions.create(model=model, messages=messages, tools=tools)
msg_obj = response.choices[0].message
# 3. Handle Tool Calls
if msg_obj.tool_calls:
messages.append(msg_obj)
for tool_call in msg_obj.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
# Use tool_map to find the correct function
func_res = tool_map[func_name](**func_args)
# Auto-Audit Logging
# Log the action (we assume the tool execution is compliant unless flagged)
log_audit_event(session_id, agent_key, func_name, True)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(func_res)
})
# Final call with tool results
response = openai_client.chat.completions.create(model=model, messages=messages)
assistant_reply = response.choices[0].message.content
else:
assistant_reply = msg_obj.content
db.save_message(session_id, "assistant", assistant_reply)
history.append((message, assistant_reply))
return "", history
# UI
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🚀 Optimized AI Agent Dashboard (Auditor Edition)")
chatbot = gr.Chatbot(height=400)
with gr.Tabs():
with gr.TabItem("Session Manager"):
session_name = gr.Textbox(label="New Session Name")
create_btn = gr.Button("Create Session")
session_dropdown = gr.Dropdown(label="Select Session", choices=db.get_sessions())
create_btn.click(lambda name: db.create_session(name), [session_name], [session_dropdown])
with gr.TabItem("Chat"):
msg = gr.Textbox(label="Input")
model = gr.Dropdown(choices=["gpt-3.5-turbo", "gpt-4o", "gpt-4-turbo"], value="gpt-3.5-turbo")
msg.submit(chat_wrapper, [msg, chatbot, session_dropdown, model], [msg, chatbot])
session_dropdown.change(lambda sid: db.get_history(sid), [session_dropdown], [chatbot])
with gr.TabItem("Storefront"):
comp_type = gr.Dropdown(choices=["shopify-product-card", "shopify-buy-button"], label="Component Type")
handle = gr.Textbox(label="Product Handle")
render_btn = gr.Button("Render Component")
html_out = gr.HTML()
render_btn.click(render_storefront_component, [comp_type, handle], [html_out])
if __name__ == "__main__":
demo.launch()
|