ai / app.py
hidaug10's picture
Upload 3 files
27b4f6f verified
Raw
History Blame Contribute Delete
13.4 kB
# --- PYTHON 3.13 COMPATIBILITY MONKEY-PATCH ---
import sys
import types
if 'audioop' not in sys.modules:
mock_audioop = types.ModuleType('audioop')
mock_audioop.error = Exception
mock_audioop.getsample = lambda data, width, index: 0
sys.modules['audioop'] = mock_audioop
# ----------------------------------------------
import os
import sqlite3
import pandas as pd
import json
import gradio as gr
from groq import Groq
import requests
# --- Database Initialization ---
DB_NAME = "strides_production.db"
def init_db():
conn = sqlite3.connect(DB_NAME)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS project_tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
phase TEXT,
task_name TEXT,
owner TEXT,
timeline TEXT,
priority TEXT
)
''')
cursor.execute("SELECT COUNT(*) FROM project_tasks")
if cursor.fetchone()[0] == 0:
dummy_data = [
('Discovery', 'Identify Deviation Root Cause', 'A. Sharma', 'Week 1', 'High'),
('Data Prep', 'Clean LIMS Batch Records', 'R. Verma', 'Week 2-3', 'Medium'),
('Modeling', 'Train Predictive Quality AI', 'S. Iyer', 'Week 4-5', 'High'),
('Validation', 'Draft GxP Validation Protocol', 'M. Reddy', 'Week 6', 'High'),
('Discovery', 'Audit Existing Logbook Manuals', 'P. Gupta', 'Week 1', 'Low'),
('Data Prep', 'Standardize Sensor Timestamp Data', 'R. Verma', 'Week 2-3', 'Medium'),
('Validation', 'Perform IQ/OQ/PQ for AI Model', 'M. Reddy', 'Week 6', 'High')
]
cursor.executemany(
'INSERT INTO project_tasks (phase, task_name, owner, timeline, priority) VALUES (?,?,?,?,?)',
dummy_data
)
conn.commit()
conn.close()
init_db()
# --- Dynamic Model Dropdown Refresher Logic ---
GROQ_MODELS = [
"llama-3.1-8b-instant",
"llama-3.1-70b-versatile",
"openai/gpt-oss-20b",
"whisper-large-v3-turbo"
]
OPENROUTER_MODELS = [
"nvidia/nemotron-3.5-content-safety:free",
"qwen/qwen3.7-plus",
"microsoft/mai-transcribe-1.5",
"google/gemini-embedding-2"
]
def update_model_dropdown(provider):
if provider == "Groq":
return gr.Dropdown(choices=GROQ_MODELS, value=GROQ_MODELS[0], label="Target Engine Architecture")
elif provider == "OpenRouter":
return gr.Dropdown(choices=OPENROUTER_MODELS, value=OPENROUTER_MODELS[0], label="Target Engine Architecture")
# --- Common LLM API Request Orchestrator ---
def call_llm(provider, api_key, model_choice, system_prompt, user_message, chat_history_format=None):
messages = [{"role": "system", "content": system_prompt}]
if chat_history_format:
messages.extend(chat_history_format)
else:
messages.append({"role": "user", "content": user_message})
if provider == "Groq":
client = Groq(api_key=api_key)
groq_model_map = {
"llama-3.1-8b-instant": "llama-3.1-8b-instant",
"llama-3.1-70b-versatile": "llama-3.1-70b-versatile",
"openai/gpt-oss-20b": "llama-3.1-8b-instant",
"whisper-large-v3-turbo": "whisper-large-v3-turbo"
}
target_model = groq_model_map.get(model_choice, "llama-3.1-8b-instant")
response = client.chat.completions.create(
model=target_model, messages=messages, temperature=0.0
)
return response.choices[0].message.content.strip()
elif provider == "OpenRouter":
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
# Maps user-facing selection directly to their OpenRouter global endpoints
openrouter_model_map = {
"nvidia/nemotron-3.5-content-safety:free": "nvidia/nemotron-3.5-content-safety:free",
"qwen/qwen3.7-plus": "qwen/qwen3.7-plus",
"microsoft/mai-transcribe-1.5": "microsoft/mai-transcribe-1.5",
"google/gemini-embedding-2": "google/gemini-embedding-2"
}
target_model = openrouter_model_map.get(model_choice, "nvidia/nemotron-3.5-content-safety:free")
payload = {
"model": target_model,
"messages": messages,
"temperature": 0.0
}
response = requests.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, json=payload)
if response.status_code == 200:
return response.json()['choices'][0]['message']['content'].strip()
else:
raise Exception(f"OpenRouter Gateway Alert ({response.status_code}): {response.text}")
# --- Tab 1: Text-to-SQL Reader Desk Core Logic ---
def execute_ai_query(provider, api_key, model_choice, user_question):
if not api_key.strip():
return None, "⚠️ Please enter a valid API Key to proceed."
if not user_question.strip():
return None, "⚠️ Please type a question or scenario."
system_prompt = (
"You are an expert SQL assistant. The database table is called 'project_tasks' with columns: "
"[id, timestamp, phase, task_name, owner, timeline, priority]. "
"Return ONLY a valid, executable raw SQLite query based on the user's question. "
"Do not include any explanation, introductory markdown, markdown code block wrappers, or trailing text. "
"Output raw text only."
)
try:
sql_query = call_llm(provider, api_key, model_choice, system_prompt, user_question)
sql_query = sql_query.replace("```sql", "").replace("```", "").replace("`", "").strip()
conn = sqlite3.connect(DB_NAME)
df = pd.read_sql_query(sql_query, conn)
conn.close()
return df, f"⚑ **Generated SQL Query:** `{sql_query}`"
except Exception as e:
return None, f"❌ Execution Failed: {str(e)}"
# --- Tab 2: Conversation & Data Append Agent Core Logic ---
def conversation_and_commit_agent(chat_history, provider, api_key, model_choice, user_msg):
if not api_key.strip():
chat_history.append({"role": "assistant", "content": "⚠️ Authentication missing. Please input your API Key on the left menu pane."})
return chat_history, ""
if not user_msg.strip():
return chat_history, ""
system_prompt = (
"You are a helpful conversational assistant and workflow coordinator for the Strides Pharma AI operational framework.\n"
"Your goal is twofold:\n"
"1. Respond to general conversational statements normally and professionally.\n"
"2. If the user expresses intent to log, add, or append a task milestone to the schedule, guide them or process it. "
"The required metrics are: Phase, Task_Name, Owner, Timeline, and Priority.\n\n"
"CRITICAL MECHANISM FOR DATA INSERTION:\n"
"If you have gathered or been explicitly provided structural task properties to log, you MUST append a raw JSON block at the very end of your final response text. "
"The format must exactly be: ||JSON_DATA: {\"phase\": \"...\", \"task_name\": \"...\", \"owner\": \"...\", \"timeline\": \"...\", \"priority\": \"...\"}||\n"
"If some schema details are completely absent, converse politely with the client to verify those remaining parameters before adding the string tag marker."
)
formatted_history = []
for turn in chat_history:
formatted_history.append({"role": turn["role"], "content": turn["content"]})
formatted_history.append({"role": "user", "content": user_msg})
try:
raw_response = call_llm(provider, api_key, model_choice, system_prompt, "", chat_history_format=formatted_history)
cleaned_response = raw_response
database_committed_alert = ""
if "||JSON_DATA:" in raw_response:
try:
parts = raw_response.split("||JSON_DATA:")
cleaned_response = parts[0].strip()
json_string = parts[1].replace("||", "").strip()
data_payload = json.loads(json_string)
conn = sqlite3.connect(DB_NAME)
cursor = conn.cursor()
cursor.execute(
"INSERT INTO project_tasks (phase, task_name, owner, timeline, priority) VALUES (?, ?, ?, ?, ?)",
(data_payload.get('phase'), data_payload.get('task_name'), data_payload.get('owner'), data_payload.get('timeline'), data_payload.get('priority'))
)
conn.commit()
conn.close()
database_committed_alert = "\n\nβš™οΈ **[SYSTEM UPDATE]:** Successfully appended task '" + str(data_payload.get('task_name')) + "' to the internal server database master record structure."
except Exception as inner_err:
database_committed_alert = "\n\n⚠️ **[SYSTEM NOTICE]:** Captured structure request token, but insertion execution aborted due to tracking parsing discrepancies: " + str(inner_err)
final_display_text = cleaned_response + database_committed_alert
chat_history.append({"role": "user", "content": user_msg})
chat_history.append({"role": "assistant", "content": final_display_text})
return chat_history, ""
except Exception as e:
chat_history.append({"role": "user", "content": user_msg})
chat_history.append({"role": "assistant", "content": f"❌ API Connection Failure: {str(e)}"})
return chat_history, ""
# --- Interface Layout Configuration ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# πŸ’Š Strides Pharma AI Production & Data Portal")
gr.Markdown("Orchestrate production tasks, converse with core system workflows, and modify infrastructure records securely.")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### πŸ”‘ Global Control Tower")
provider_select = gr.Dropdown(choices=["Groq", "OpenRouter"], value="Groq", label="API Gateway Provider")
token_input = gr.Textbox(label="User API Secret Key", type="password", placeholder="gsk_... or sk-or-...")
# This component gets updated dynamically by the event handler below
model_select = gr.Dropdown(
choices=GROQ_MODELS,
value=GROQ_MODELS[0],
label="Target Engine Architecture"
)
gr.Markdown("✨ **Global Platform Database State Schema:**\n- `phase` (Discovery, Data Prep, Modeling, Validation)\n- `task_name` (Structural workflow description string)\n- `owner` (Assigned personnel scientist name)\n- `timeline` (Expected operational delivery time frames)\n- `priority` (High, Medium, Low)")
with gr.Column(scale=2):
with gr.Tabs():
with gr.TabItem("πŸ€– Interactive Data Contributor Chatbot"):
gr.Markdown("### Conversational Contributor Agent")
gr.Markdown("Chat with this engine normally, or tell it to log a brand-new task assignment milestone directly into the active SQLite infrastructure.")
chatbot_viewport = gr.Chatbot(type="messages", label="Operational History Workspace")
chat_input = gr.Textbox(placeholder="Say hello, or submit task details to log...", label="Your Message")
send_btn = gr.Button("Submit Message", variant="primary")
send_btn.click(
fn=conversation_and_commit_agent,
inputs=[chatbot_viewport, provider_select, token_input, model_select, chat_input],
outputs=[chatbot_viewport, chat_input]
)
chat_input.submit(
fn=conversation_and_commit_agent,
inputs=[chatbot_viewport, provider_select, token_input, model_select, chat_input],
outputs=[chatbot_viewport, chat_input]
)
with gr.TabItem("πŸ”Ž SQL Inquisitor Desk"):
gr.Markdown("### Natural Language SQL Query Engine")
query_input = gr.Textbox(label="Query the current database contents using conversational English:", placeholder="e.g., Show me all records sorted by priority status")
query_btn = gr.Button("Evaluate Infrastructure", variant="secondary")
sql_status_display = gr.Markdown()
output_data_table = gr.DataFrame(label="Queried Records Dataframe Live Output")
query_btn.click(
fn=execute_ai_query,
inputs=[provider_select, token_input, model_select, query_input],
outputs=[output_data_table, sql_status_display]
)
# --- REACTIVE EVENT LISTENER ---
# Whenever the provider dropdown changes, change the choices of the model select dropdown
provider_select.change(
fn=update_model_dropdown,
inputs=[provider_select],
outputs=[model_select]
)
if __name__ == "__main__":
demo.launch()