Spaces:
Sleeping
Sleeping
Download app.py from Srinu007/Strides_pharma_chatbot: direct link, hf CLI and curl.
- Browser
- Download file 13.3 kB
-
https://huggingface.co/spaces/Srinu007/Strides_pharma_chatbot/resolve/main/app.py
- Command line
-
hf download hf://spaces/Srinu007/Strides_pharma_chatbot/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Srinu007/Strides_pharma_chatbot/resolve/main/app.py
13.3 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 = f"\n\nβοΈ **[SYSTEM UPDATE]:** Successfully appended task '{data_payload.get('task_name')}' to the internal server database master record structure." | |
| except Exception as inner_err: | |
| database_committed_alert = f"\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 --- | |
| provider_select.change( | |
| fn=update_model_dropdown, | |
| inputs=[provider_select], | |
| outputs=[model_select] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |