Prof-Reza commited on
Commit
05871ef
·
verified ·
1 Parent(s): 28abf63

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -28
app.py CHANGED
@@ -1,46 +1,133 @@
1
  import os
2
  import gradio as gr
3
- # Adjust imports to work when modules are in the repository root.
4
- # When deploying on Hugging Face, the helper modules live at the top level,
5
- # so import them directly instead of via a package.
6
  from planner import plan_course
7
  from generators import generate_course_zip
8
  from searcher import run_web_search
9
 
10
- # store chat messages and sources globally
11
- chat_history = []
12
- sources = []
 
 
 
 
13
 
14
- def handle_user_message(message):
15
- global chat_history
16
- chat_history.append({"role": "user", "content": message})
17
- # simple display of conversation
18
- return "\n\n".join([m["role"] + ': ' + m["content"] for m in chat_history])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
- def handle_search(query, num_results=5, domain_filter=""):
21
- global sources
 
22
  results = run_web_search(query, num_results=num_results, domain_filter=domain_filter)
 
 
23
  sources.extend(results)
24
- # return string summarizing sources
25
- return "\n".join([f"{r.get('title','')} - {r.get('url','')}" for r in results])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- def handle_generate():
28
- plan = plan_course(chat_history, sources)
 
 
 
 
 
29
  zip_path = generate_course_zip(plan, sources)
30
  return zip_path
31
 
32
  with gr.Blocks() as demo:
33
- gr.Markdown("# Course Agent\nChat about your course idea, search for sources, and generate a course package.")
34
- message = gr.Textbox(label="Your message")
35
- chat_display = gr.Textbox(label="Conversation", interactive=False)
36
- search_query = gr.Textbox(label="Search query")
37
- domain_filter = gr.Textbox(label="Domain filter (comma-separated)", placeholder=".edu,.gov,acm.org")
 
 
 
 
 
 
 
38
  search_results = gr.Textbox(label="Search results", interactive=False)
 
 
 
39
  generate_btn = gr.Button("Generate Course Package")
40
  file_output = gr.File(label="course.zip")
41
-
42
- message.submit(handle_user_message, inputs=message, outputs=chat_display)
43
- search_query.submit(handle_search, inputs=search_query, outputs=search_results)
44
- generate_btn.click(handle_generate, outputs=file_output)
45
-
46
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import gradio as gr
3
+ import openai
4
+
 
5
  from planner import plan_course
6
  from generators import generate_course_zip
7
  from searcher import run_web_search
8
 
9
+ # System prompt guiding the assistant's behaviour during brainstorming
10
+ SYSTEM_PROMPT = (
11
+ "You are a helpful course planning assistant. Conduct brainstorming with the user "
12
+ "about their course idea. Offer suggestions, ask clarifying questions, and capture their requirements. "
13
+ "When the user feels ready, they will click 'Finalize Outline' to create a course plan using all prior "
14
+ "conversation and gathered resources."
15
+ )
16
 
17
+ def chat(user_message, chat_history, chat_pairs, sources, plan):
18
+ """Handle a user chat message and return updated chat state."""
19
+ # Ensure OpenAI API key is set
20
+ openai.api_key = os.getenv("OPENAI_API_KEY")
21
+ # initialise state variables if they are None
22
+ if chat_history is None:
23
+ chat_history = []
24
+ if chat_pairs is None:
25
+ chat_pairs = []
26
+ # append the user's message to the conversation history
27
+ chat_history.append({"role": "user", "content": user_message})
28
+ # build messages including system prompt
29
+ messages = [{"role": "system", "content": SYSTEM_PROMPT}] + chat_history
30
+ # call OpenAI's ChatCompletion to get assistant's reply
31
+ response = openai.ChatCompletion.create(
32
+ model=os.getenv("OPENAI_MODEL", "gpt-5-mini"),
33
+ messages=messages,
34
+ temperature=float(os.getenv("TEMPERATURE", "0.7")),
35
+ max_tokens=int(os.getenv("MAX_OUTPUT_TOKENS", "1024")),
36
+ )
37
+ assistant_reply = response["choices"][0]["message"]["content"]
38
+ # append assistant reply to conversation history
39
+ chat_history.append({"role": "assistant", "content": assistant_reply})
40
+ # append pair to display history for Chatbot component
41
+ chat_pairs.append((user_message, assistant_reply))
42
+ return chat_pairs, chat_history, chat_pairs, sources, plan
43
 
44
+ def run_search(query, chat_history, chat_pairs, sources, plan, num_results=5, domain_filter=""):
45
+ """Execute a web search and update sources list."""
46
+ # perform search using provided searcher
47
  results = run_web_search(query, num_results=num_results, domain_filter=domain_filter)
48
+ if sources is None:
49
+ sources = []
50
  sources.extend(results)
51
+ # summarise results into a string for display
52
+ summary_lines = []
53
+ for r in results:
54
+ title = r.get("title", "")
55
+ url = r.get("url", "")
56
+ summary_lines.append(f"{title} - {url}")
57
+ summary = "\n".join(summary_lines)
58
+ return summary, chat_history, chat_pairs, sources, plan
59
+
60
+ def finalize_outline(chat_history, chat_pairs, sources, plan):
61
+ """Generate a course outline based on the conversation and collected sources."""
62
+ if chat_history is None:
63
+ chat_history = []
64
+ if sources is None:
65
+ sources = []
66
+ # use the planner to create the plan
67
+ plan_text = plan_course(chat_history, sources)
68
+ plan = plan_text
69
+ return plan_text, chat_history, chat_pairs, sources, plan
70
 
71
+ def generate_package(plan, sources):
72
+ """Generate the final course package zip file."""
73
+ if plan is None or plan == "":
74
+ # fallback: create a minimal plan if none exists
75
+ plan = "Course plan is empty."
76
+ if sources is None:
77
+ sources = []
78
  zip_path = generate_course_zip(plan, sources)
79
  return zip_path
80
 
81
  with gr.Blocks() as demo:
82
+ gr.Markdown(
83
+ """# Course Creator Agent
84
+ Chat with the assistant to brainstorm your course idea. Use web search to collect resources. When you're ready, click **Finalize Outline** to generate a course plan. Then generate the final course package (ZIP)."""
85
+ )
86
+ # Chat interface components
87
+ chatbot = gr.Chatbot(label="Conversation")
88
+ msg_input = gr.Textbox(label="Your message", placeholder="Type your message and press Enter", lines=1)
89
+ # Search controls
90
+ search_query = gr.Textbox(label="Search query", placeholder="Enter search keywords")
91
+ domain_filter = gr.Textbox(
92
+ label="Domain filter (comma-separated)", placeholder=".edu,.gov,acm.org", value=""
93
+ )
94
  search_results = gr.Textbox(label="Search results", interactive=False)
95
+ # Buttons and outputs
96
+ finalize_btn = gr.Button("Finalize Outline")
97
+ plan_output = gr.Textbox(label="Course outline", interactive=False)
98
  generate_btn = gr.Button("Generate Course Package")
99
  file_output = gr.File(label="course.zip")
100
+ # State variables to keep track of conversation, display pairs, sources and plan
101
+ state_chat_history = gr.State([])
102
+ state_chat_pairs = gr.State([])
103
+ state_sources = gr.State([])
104
+ state_plan = gr.State("")
105
+ # Handle chat submission: update chatbot display and states
106
+ msg_input.submit(
107
+ chat,
108
+ inputs=[msg_input, state_chat_history, state_chat_pairs, state_sources, state_plan],
109
+ outputs=[chatbot, state_chat_history, state_chat_pairs, state_sources, state_plan],
110
+ ).then(
111
+ lambda: "", None, None, [], [msg_input]
112
+ )
113
+ # Handle search submission: update search results and sources; maintain other states unchanged
114
+ search_query.submit(
115
+ lambda q, domain, chat_hist, chat_pairs, srcs, pl: run_search(
116
+ q, chat_hist, chat_pairs, srcs, pl, num_results=5, domain_filter=domain
117
+ ),
118
+ inputs=[search_query, domain_filter, state_chat_history, state_chat_pairs, state_sources, state_plan],
119
+ outputs=[search_results, state_chat_history, state_chat_pairs, state_sources, state_plan],
120
+ )
121
+ # Finalize outline button: generate course plan and store it
122
+ finalize_btn.click(
123
+ finalize_outline,
124
+ inputs=[state_chat_history, state_chat_pairs, state_sources, state_plan],
125
+ outputs=[plan_output, state_chat_history, state_chat_pairs, state_sources, state_plan],
126
+ )
127
+ # Generate course package button
128
+ generate_btn.click(
129
+ generate_package,
130
+ inputs=[state_plan, state_sources],
131
+ outputs=file_output,
132
+ )
133
+ demo.launch()