BtB-ExpC commited on
Commit
9d9db50
·
1 Parent(s): 72b43ce

restructured

Browse files
app.py CHANGED
@@ -1,90 +1,104 @@
 
1
  import gradio as gr
2
- import openai
3
  import os
 
 
4
 
5
- # Load secrets
6
- CORRECT_PASSWORD = os.getenv("APP_PASSWORD") # Set this in Hugging Face Spaces secrets
7
- openai.api_key = os.getenv("OPENAI_API_KEY") # Also store securely
8
 
9
- client = openai.OpenAI() # ✅ New format
10
 
11
 
12
- # -------------------------------
13
- # Define Functions for App Logic
14
- # -------------------------------
15
-
16
- def login(password):
17
  """
18
- Check the submitted password.
19
- If correct, hide the login container and show the main app.
20
- Otherwise, return an error message.
 
 
 
 
 
 
21
  """
22
- if password == CORRECT_PASSWORD:
23
- # Hide login page, show main app, and clear error message
24
- return gr.update(visible=False), gr.update(visible=True), ""
25
- else:
26
- # Remain on login page with an error message
27
- return gr.update(visible=True), gr.update(visible=False), "❌ Incorrect password. Please try again or contact Ben."
28
-
29
- def diagnoser_query(user_query):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  """
31
- Process the Diagnoser query.
32
- (For now, simply pass the query to the OpenAI API.)
33
  """
34
- response = client.chat.completions.create(
35
- model="gpt-4o-mini",
36
- timeout=10,
37
- messages=[
38
- {
39
- "role": "user",
40
- "content": (
41
- "What is wrong with this exercise? In other words, what about it should be improved? "
42
- "What stands between it and a perfect exercise that couldn't be better? Don't give solutions yet, "
43
- "only a diagnosis\n "
44
- f"{user_query}"
45
- ),
46
- }
47
- ],
48
- )
49
- return response.choices[0].message.content
50
 
51
- def distractors_query(user_query):
 
52
  """
53
- Process the Distractors brainstorm query.
54
- (For now, simply pass the query to the OpenAI API.)
55
  """
56
- response = client.chat.completions.create(
57
- model="gpt-4o-mini",
58
- timeout=10,
59
- messages=[{"role": "user", "content": user_query}]
60
- )
61
- return response.choices[0].message.content
62
 
63
  # -------------------------------
64
  # Build the Gradio Interface
65
  # -------------------------------
66
-
67
  with gr.Blocks() as demo:
68
  # --- Login Page ---
69
  with gr.Column(visible=True, elem_id="login_page") as login_container:
70
  gr.Markdown("## 🔒 Please Login")
71
- password_input = gr.Textbox(label="Enter Password", type="password", placeholder="Enter password to access the app")
 
 
 
 
72
  login_button = gr.Button("Login")
73
- login_error = gr.Markdown(value="") # To display error messages
74
 
75
  # --- Main App (initially hidden) ---
76
  with gr.Column(visible=False, elem_id="main_app") as app_container:
77
  gr.Markdown("## Core Functionalities")
78
- # Use gr.Tabs for persistent states between functionalities
79
  with gr.Tabs():
80
  with gr.TabItem("Diagnoser"):
81
  gr.Markdown("### Diagnoser")
82
- diagnoser_input = gr.Textbox(label="Enter Diagnoser Query", placeholder="Type your query here...")
 
 
 
83
  diagnoser_button = gr.Button("Submit")
84
  diagnoser_output = gr.Textbox(label="Response", interactive=False)
85
  with gr.TabItem("Distractors brainstorm"):
86
  gr.Markdown("### Distractors brainstorm")
87
- distractors_input = gr.Textbox(label="Enter Brainstorm Query", placeholder="Type your query here...")
 
 
 
88
  distractors_button = gr.Button("Submit")
89
  distractors_output = gr.Textbox(label="Response", interactive=False)
90
 
@@ -92,26 +106,26 @@ with gr.Blocks() as demo:
92
  # Set Up Interactions
93
  # -------------------------------
94
 
95
- # When the login button is clicked, check the password and update container visibility
96
  login_button.click(
97
- fn=login,
98
  inputs=[password_input],
99
  outputs=[login_container, app_container, login_error]
100
  )
101
 
102
- # Connect the Diagnoser functionality
103
  diagnoser_button.click(
104
- fn=diagnoser_query,
105
  inputs=[diagnoser_input],
106
  outputs=[diagnoser_output]
107
  )
108
 
109
- # Connect the Distractors brainstorm functionality
110
  distractors_button.click(
111
- fn=distractors_query,
112
  inputs=[distractors_input],
113
  outputs=[distractors_output]
114
  )
115
 
116
- # Launch the app
117
- demo.launch()
 
1
+ # app.py
2
  import gradio as gr
 
3
  import os
4
+ import asyncio
5
+ import logging
6
 
7
+ from utils.auth import login as auth_login # simple login function
8
+ from config.chain_configs import chain_configs # chain configurations dictionary
 
9
 
10
+ logger = logging.getLogger(__name__)
11
 
12
 
13
+ async def run_chain(chain_name: str, input_variables: dict):
 
 
 
 
14
  """
15
+ A generic async function to run a given structured chain.
16
+ Handles prompt formatting, invoking the LLM asynchronously, and returning results.
17
+
18
+ Args:
19
+ chain_name (str): The key for the desired chain in the chain_configs.
20
+ input_variables (dict): A dictionary of variables to format the chain's prompt.
21
+
22
+ Returns:
23
+ The result of invoking the chain's LLM with the formatted prompt.
24
  """
25
+ try:
26
+ # Resolve the chain configuration by its name.
27
+ chain_config = chain_configs.get(chain_name)
28
+ if not chain_config:
29
+ raise KeyError(f"Chain '{chain_name}' not found in the chain configuration.")
30
+
31
+ # Generate the prompt using the chain's template.
32
+ prompt_value = chain_config["template"].format_prompt(**input_variables)
33
+
34
+ # Invoke the chain's LLM asynchronously.
35
+ result = await chain_config["chain"].ainvoke(prompt_value.to_messages())
36
+
37
+ logger.info(f"Chain '{chain_name}' executed successfully.")
38
+ return result
39
+
40
+ except KeyError as e:
41
+ logger.error(f"Chain configuration error: {e}")
42
+ raise ValueError(f"Invalid chain structure: missing {e}")
43
+
44
+ except Exception as e:
45
+ logger.error(f"Error running chain '{chain_name}': {e}")
46
+ raise RuntimeError(f"Failed to execute chain: {e}")
47
+
48
+
49
+ async def run_diagnoser(user_query: str) -> str:
50
  """
51
+ Async function to run the diagnoser chain.
52
+ Prepares the input variables and awaits the chain's result.
53
  """
54
+ input_vars = {"user_query": user_query}
55
+ result = await run_chain("diagnoser", input_vars)
56
+ return result
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
+
59
+ async def run_distractors(user_query: str) -> str:
60
  """
61
+ Async function to run the distractors brainstorm chain.
62
+ Prepares the input variables and awaits the chain's result.
63
  """
64
+ input_vars = {"user_query": user_query}
65
+ result = await run_chain("distractors", input_vars)
66
+ return result
67
+
 
 
68
 
69
  # -------------------------------
70
  # Build the Gradio Interface
71
  # -------------------------------
 
72
  with gr.Blocks() as demo:
73
  # --- Login Page ---
74
  with gr.Column(visible=True, elem_id="login_page") as login_container:
75
  gr.Markdown("## 🔒 Please Login")
76
+ password_input = gr.Textbox(
77
+ label="Enter Password",
78
+ type="password",
79
+ placeholder="Enter password to access the app"
80
+ )
81
  login_button = gr.Button("Login")
82
+ login_error = gr.Markdown(value="") # For error messages
83
 
84
  # --- Main App (initially hidden) ---
85
  with gr.Column(visible=False, elem_id="main_app") as app_container:
86
  gr.Markdown("## Core Functionalities")
 
87
  with gr.Tabs():
88
  with gr.TabItem("Diagnoser"):
89
  gr.Markdown("### Diagnoser")
90
+ diagnoser_input = gr.Textbox(
91
+ label="Enter Diagnoser Query",
92
+ placeholder="Type your query here..."
93
+ )
94
  diagnoser_button = gr.Button("Submit")
95
  diagnoser_output = gr.Textbox(label="Response", interactive=False)
96
  with gr.TabItem("Distractors brainstorm"):
97
  gr.Markdown("### Distractors brainstorm")
98
+ distractors_input = gr.Textbox(
99
+ label="Enter Brainstorm Query",
100
+ placeholder="Type your query here..."
101
+ )
102
  distractors_button = gr.Button("Submit")
103
  distractors_output = gr.Textbox(label="Response", interactive=False)
104
 
 
106
  # Set Up Interactions
107
  # -------------------------------
108
 
109
+ # Login button: if the password is correct, hide the login container and reveal the main app.
110
  login_button.click(
111
+ fn=auth_login,
112
  inputs=[password_input],
113
  outputs=[login_container, app_container, login_error]
114
  )
115
 
116
+ # Run the Diagnoser chain asynchronously.
117
  diagnoser_button.click(
118
+ fn=run_diagnoser,
119
  inputs=[diagnoser_input],
120
  outputs=[diagnoser_output]
121
  )
122
 
123
+ # Run the Distractors brainstorm chain asynchronously.
124
  distractors_button.click(
125
+ fn=run_distractors,
126
  inputs=[distractors_input],
127
  outputs=[distractors_output]
128
  )
129
 
130
+ # Launch the Gradio app.
131
+ demo.launch()
chains/diagnoser_chain.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class DiagnoserChain(BaseModel):
5
+ template: str # In practice, you might accept a ChatPromptTemplate
6
+ llm: any # Type the LLM appropriately (or use typing.Any for now)
7
+
8
+ def run(self, user_query: str) -> str:
9
+ # Here you would plug in your LangChain logic.
10
+ # For demonstration, we mimic a call to an LLM:
11
+ # In production, you could use an LLMChain or a sequence of chains.
12
+ prompt = f"What is wrong with this exercise?\n{user_query}"
13
+ response = self.llm.call(prompt)
14
+ return response
chains/distractors_chain.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class DistractorsChain(BaseModel):
5
+ template: str
6
+ llm: any
7
+
8
+ def run(self, user_query: str) -> str:
9
+ prompt = f"Brainstorm some distractors for:\n{user_query}"
10
+ response = self.llm.call(prompt)
11
+ return response
config/chain_configs.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from config.llm_config import llms
2
+ from config.templates import dummy_template, initial_classification_template
3
+ from chains.diagnoser_chain import DiagnoserChain
4
+ from chains.distractors_chain import DistractorsChain
5
+
6
+ chain_configs = {
7
+ "diagnoser": {
8
+ "template": dummy_template,
9
+ "class": DiagnoserChain,
10
+ "llm": llms["mini"],
11
+ },
12
+ "distractors": {
13
+ "template": dummy_template, # Replace with a specific template if needed.
14
+ "class": DistractorsChain,
15
+ "llm": llms["mini"],
16
+ },
17
+ # More chains can be added here.
18
+ }
config/llm_config.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_openai import ChatOpenAI
2
+
3
+ ZERO = 0
4
+ LOW = 0.2
5
+ MID = 0.7
6
+ HIGH = 1.2
7
+
8
+ llms = {
9
+ "gpt4o": ChatOpenAI(model_name="gpt-4o", temperature=LOW),
10
+ "mini": ChatOpenAI(model_name="gpt-4o-mini", temperature=LOW),
11
+ "gpt4o_high_temp": ChatOpenAI(model_name="gpt-4o", temperature=HIGH),
12
+ "mini_high_temp": ChatOpenAI(model_name="gpt-4o-mini", temperature=HIGH),
13
+ "o1": ChatOpenAI(model_name="o1"),
14
+ }
config/templates.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.prompts import ChatPromptTemplate
2
+
3
+ dummy_template = ChatPromptTemplate([
4
+ ("system", """
5
+ SYSTEM MESSAGE
6
+ {bot_name} {weekday} {now}
7
+ """),
8
+ ("human", """
9
+ USER MESSAGE
10
+ {user_message}
11
+ """),
12
+ ])
13
+
14
+ initial_classification_template = ChatPromptTemplate([
15
+ ("system", """
16
+ # Answer structure
17
+ 1. First pick the user_message_language: choose from Literal['English', 'German', 'Dutch', 'other'].
18
+ Look only at the user message. When multiple languages are present, pick the dominant one.
19
+ 2. Then, state your classification: 'Goals', 'Reminders', 'Meta', or 'Other'.
20
+ """),
21
+ ("human", """
22
+ USER MESSAGE
23
+ {user_message}
24
+ """),
25
+ ])
utils/auth.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+
4
+ CORRECT_PASSWORD = os.getenv("APP_PASSWORD") # Ensure this is set in your environment
5
+
6
+ def login(password: str):
7
+ """
8
+ Verify the password. Returns a tuple to update the Gradio UI.
9
+ """
10
+ if password == CORRECT_PASSWORD:
11
+ return gr.update(visible=False), gr.update(visible=True), ""
12
+ else:
13
+ return gr.update(visible=True), gr.update(visible=False), "❌ Incorrect password. Please try again or contact Ben."