serverdaun commited on
Commit
fb1de84
·
1 Parent(s): c049b12

add clarifier

Browse files
Files changed (3) hide show
  1. src/clarifier.py +24 -0
  2. src/main.py +61 -9
  3. src/research_manager.py +29 -5
src/clarifier.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agents import Agent
2
+ from pydantic import BaseModel, Field
3
+
4
+ INSTRUCTIONS = (
5
+ "You are a domain expert who wants to fully understand the research intent behind a user's high-level query. "
6
+ "Return a concise list (max 3) of the most important clarifying questions you would ask the user to narrow the scope "
7
+ "and make the subsequent research more targeted and useful. Output only the questions - no additional commentary."
8
+ )
9
+
10
+
11
+ class ClarifyingQuestions(BaseModel):
12
+ """A list of clarifying questions to present to the user before starting the research."""
13
+
14
+ questions: list[str] = Field(
15
+ description="The clarifying questions that should be asked of the user before planning the research."
16
+ )
17
+
18
+
19
+ clarifier_agent = Agent(
20
+ name="ClarifierAgent",
21
+ instructions=INSTRUCTIONS,
22
+ model="gpt-4o-mini",
23
+ output_type=ClarifyingQuestions,
24
+ )
src/main.py CHANGED
@@ -6,21 +6,73 @@ from research_manager import ResearchManager
6
  load_dotenv()
7
 
8
 
9
- async def run(query: str):
10
- async for chunk in ResearchManager().run(query):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  yield chunk
12
 
13
 
14
  with gr.Blocks(theme=gr.themes.Default(primary_hue="yellow")) as ui:
15
  gr.Markdown("# Deep Research")
16
- query_textbox = gr.Textbox(
17
- label="What topic would you like to research?",
18
- value="e.g. How to create a Deep Research Agent?",
 
 
 
 
 
 
 
 
 
 
 
 
19
  )
20
- run_button = gr.Button("Run", variant="primary")
 
21
  report = gr.Markdown(label="Report")
22
 
23
- run_button.click(fn=run, inputs=query_textbox, outputs=report)
24
- query_textbox.submit(fn=run, inputs=query_textbox, outputs=report)
 
 
 
 
 
 
 
 
 
25
 
26
- ui.launch()
 
 
6
  load_dotenv()
7
 
8
 
9
+ async def ask_clarifications(query: str) -> tuple[str, list[str]]:
10
+ """Generate clarifying questions for *query* and return both a nicely formatted string and the raw list."""
11
+ manager = ResearchManager()
12
+ questions = await manager.get_clarifying_questions(query)
13
+
14
+ if not questions:
15
+ return (
16
+ "No clarifying questions were generated. You can proceed to run the research.",
17
+ [],
18
+ )
19
+
20
+ formatted = "\n".join(f"{idx+1}. {q}" for idx, q in enumerate(questions))
21
+ return formatted, questions
22
+
23
+
24
+ async def run_research(query: str, answers: str, questions: list[str]):
25
+ """Run the complete research pipeline and stream the markdown report."""
26
+ clarifications_block = ""
27
+
28
+ answer_lines = [line.strip() for line in answers.split("\n")]
29
+ while len(answer_lines) < len(questions):
30
+ answer_lines.append("")
31
+
32
+ q_and_a = []
33
+ for idx, question in enumerate(questions):
34
+ answer = answer_lines[idx]
35
+ q_and_a.append(f"Q{idx+1}: {question}\nA{idx+1}: {answer}")
36
+
37
+ clarifications_block = "\n".join(q_and_a)
38
+
39
+ async for chunk in ResearchManager().run(query, clarifications_block):
40
  yield chunk
41
 
42
 
43
  with gr.Blocks(theme=gr.themes.Default(primary_hue="yellow")) as ui:
44
  gr.Markdown("# Deep Research")
45
+
46
+ with gr.Row():
47
+ query_textbox = gr.Textbox(
48
+ label="What topic would you like to research?",
49
+ placeholder="e.g. How to create a Deep Research Agent?",
50
+ )
51
+ ask_button = gr.Button("Ask clarifying questions")
52
+
53
+ clarifying_questions_state = gr.State([])
54
+ clarifications_markdown = gr.Markdown(label="Clarifying questions will appear here")
55
+
56
+ clarification_answers_box = gr.Textbox(
57
+ label="Your answers to the clarifying questions (one per line)",
58
+ placeholder="Answer 1\nAnswer 2\n...",
59
+ lines=3,
60
  )
61
+
62
+ run_button = gr.Button("Run research", variant="primary")
63
  report = gr.Markdown(label="Report")
64
 
65
+ ask_button.click(
66
+ fn=ask_clarifications,
67
+ inputs=query_textbox,
68
+ outputs=[clarifications_markdown, clarifying_questions_state],
69
+ )
70
+
71
+ run_button.click(
72
+ fn=run_research,
73
+ inputs=[query_textbox, clarification_answers_box, clarifying_questions_state],
74
+ outputs=report,
75
+ )
76
 
77
+ if __name__ == "__main__":
78
+ ui.launch()
src/research_manager.py CHANGED
@@ -2,6 +2,7 @@ import asyncio
2
 
3
  from agents import Runner, gen_trace_id, trace
4
 
 
5
  from planner import WebSearchItem, WebSearchPlan, planner_agent
6
  from report_generator import ReportData, writer_agent
7
  from web_search import search_agent
@@ -9,16 +10,29 @@ from web_search import search_agent
9
 
10
  class ResearchManager:
11
 
12
- async def run(self, query: str):
13
- """Run the deep research process, yielding the status updates and the final report"""
 
 
 
 
14
  trace_id = gen_trace_id()
15
  with trace("Research trace", trace_id=trace_id):
16
  print("Starting research...")
17
- search_plan = await self.plan_searches(query)
 
 
 
 
 
 
 
 
 
18
  yield "Searches planned, starting to search..."
19
  search_results = await self.perform_searches(search_plan)
20
  yield "Searches complete, writing report..."
21
- report = await self.write_report(query, search_results)
22
  yield report.markdown_report
23
 
24
  async def plan_searches(self, query: str) -> WebSearchPlan:
@@ -63,7 +77,7 @@ class ResearchManager:
63
  async def write_report(self, query: str, search_results: list[str]) -> ReportData:
64
  """Write the report for the query"""
65
  print("Thinking about report...")
66
- input = f"Original query: {query}\nSummarized search results: {search_results}"
67
  result = await Runner.run(
68
  writer_agent,
69
  input,
@@ -71,3 +85,13 @@ class ResearchManager:
71
 
72
  print("Finished writing report")
73
  return result.final_output_as(ReportData)
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  from agents import Runner, gen_trace_id, trace
4
 
5
+ from clarifier import ClarifyingQuestions, clarifier_agent
6
  from planner import WebSearchItem, WebSearchPlan, planner_agent
7
  from report_generator import ReportData, writer_agent
8
  from web_search import search_agent
 
10
 
11
  class ResearchManager:
12
 
13
+ async def run(self, query: str, clarifications: str | None = None):
14
+ """Run the deep research process, yielding status updates and the final report.
15
+
16
+ If *clarifications* are provided (the user's answers to the clarifying questions), we will use them to
17
+ augment the planning and reporting stages. Otherwise this behaves exactly like the previous implementation.
18
+ """
19
  trace_id = gen_trace_id()
20
  with trace("Research trace", trace_id=trace_id):
21
  print("Starting research...")
22
+
23
+ # Combine the original query with any clarification the user has supplied.
24
+ if clarifications:
25
+ combined_query = (
26
+ f"Original query: {query}\n\nUser clarifications:\n{clarifications}"
27
+ )
28
+ else:
29
+ combined_query = query
30
+
31
+ search_plan = await self.plan_searches(combined_query)
32
  yield "Searches planned, starting to search..."
33
  search_results = await self.perform_searches(search_plan)
34
  yield "Searches complete, writing report..."
35
+ report = await self.write_report(combined_query, search_results)
36
  yield report.markdown_report
37
 
38
  async def plan_searches(self, query: str) -> WebSearchPlan:
 
77
  async def write_report(self, query: str, search_results: list[str]) -> ReportData:
78
  """Write the report for the query"""
79
  print("Thinking about report...")
80
+ input = f"{query}\nSummarized search results: {search_results}"
81
  result = await Runner.run(
82
  writer_agent,
83
  input,
 
85
 
86
  print("Finished writing report")
87
  return result.final_output_as(ReportData)
88
+
89
+ async def get_clarifying_questions(self, query: str) -> list[str]:
90
+ """Generate clarifying questions for a given query."""
91
+ print("Generating clarifying questions...")
92
+ result = await Runner.run(clarifier_agent, f"Query: {query}")
93
+ questions_model: ClarifyingQuestions = result.final_output_as(
94
+ ClarifyingQuestions
95
+ )
96
+ print(f"Generated {len(questions_model.questions)} clarifying questions")
97
+ return questions_model.questions