OzanSevindir commited on
Commit
67b02ff
·
verified ·
1 Parent(s): 6870b7f

Upload folder using huggingface_hub

Browse files
__pycache__/deep_research.cpython-312.pyc ADDED
Binary file (35.1 kB). View file
 
__pycache__/planner_agent.cpython-312.pyc CHANGED
Binary files a/__pycache__/planner_agent.cpython-312.pyc and b/__pycache__/planner_agent.cpython-312.pyc differ
 
__pycache__/research_manager.cpython-312.pyc CHANGED
Binary files a/__pycache__/research_manager.cpython-312.pyc and b/__pycache__/research_manager.cpython-312.pyc differ
 
__pycache__/simple_search_agent.cpython-312.pyc ADDED
Binary file (1.43 kB). View file
 
__pycache__/writer_agent.cpython-312.pyc CHANGED
Binary files a/__pycache__/writer_agent.cpython-312.pyc and b/__pycache__/writer_agent.cpython-312.pyc differ
 
deep_research.py CHANGED
@@ -7,7 +7,7 @@ import re
7
  load_dotenv(override=True)
8
 
9
 
10
- async def run_research(query: str, model_choice: str, progress=gr.Progress()):
11
  """Run research and yield updates for both report and references"""
12
  status_messages = []
13
  final_report_md = ""
@@ -39,7 +39,7 @@ async def run_research(query: str, model_choice: str, progress=gr.Progress()):
39
  '''
40
 
41
  # Collect all chunks and parse structured messages
42
- async for chunk in ResearchManager(model_choice).run(query):
43
  # Parse structured messages (format: TYPE|data)
44
  if "|" in chunk:
45
  msg_type, msg_data = chunk.split("|", 1)
@@ -254,6 +254,77 @@ def format_references_html(references):
254
  return html
255
 
256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  # Create custom dark theme
258
  luntre_theme = gr.themes.Base(
259
  primary_hue="green",
@@ -429,6 +500,35 @@ textarea:not(.chat-input textarea):focus {
429
  font-weight: 400;
430
  }
431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
  /* Report action buttons */
433
  .report-actions {
434
  display: flex;
@@ -895,6 +995,8 @@ button[role="tab"] {
895
  with gr.Blocks(theme=luntre_theme, css=custom_css, title="Luntre AI - Deep Research") as demo:
896
  # State to store current query for rewrite functionality
897
  current_query_state = gr.State("")
 
 
898
 
899
  # Header
900
  gr.HTML("""
@@ -933,6 +1035,7 @@ with gr.Blocks(theme=luntre_theme, css=custom_css, title="Luntre AI - Deep Resea
933
  with gr.Row(elem_classes="controls-row"):
934
  run_btn = gr.Button("▶ Run Research", variant="primary", elem_classes="run-button")
935
  search_btn = gr.Button("▶ Run Search", variant="secondary", elem_classes="search-button")
 
936
  model_selector = gr.Dropdown(
937
  choices=[
938
  "Gemini 2.5 Flash",
@@ -965,12 +1068,51 @@ with gr.Blocks(theme=luntre_theme, css=custom_css, title="Luntre AI - Deep Resea
965
  """Clear the input box"""
966
  return ""
967
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
968
  # Run research
969
  run_event = run_btn.click(
970
  fn=update_query_state,
971
  inputs=[query_input],
972
  outputs=[current_query_state],
973
  queue=False
 
 
 
 
 
974
  ).then(
975
  fn=clear_input,
976
  inputs=[],
@@ -978,7 +1120,7 @@ with gr.Blocks(theme=luntre_theme, css=custom_css, title="Luntre AI - Deep Resea
978
  queue=False
979
  ).then(
980
  fn=run_research,
981
- inputs=[current_query_state, model_selector],
982
  outputs=[report_output, references_output]
983
  )
984
 
@@ -993,16 +1135,59 @@ with gr.Blocks(theme=luntre_theme, css=custom_css, title="Luntre AI - Deep Resea
993
  # Rewrite (run again with same query)
994
  rewrite_event = rewrite_btn.click(
995
  fn=run_research,
996
- inputs=[current_query_state, model_selector],
997
  outputs=[report_output, references_output]
998
  )
999
 
1000
- # Also allow Enter key to submit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1001
  query_input.submit(
1002
  fn=update_query_state,
1003
  inputs=[query_input],
1004
  outputs=[current_query_state],
1005
  queue=False
 
 
 
 
 
1006
  ).then(
1007
  fn=clear_input,
1008
  inputs=[],
@@ -1010,7 +1195,7 @@ with gr.Blocks(theme=luntre_theme, css=custom_css, title="Luntre AI - Deep Resea
1010
  queue=False
1011
  ).then(
1012
  fn=run_research,
1013
- inputs=[current_query_state, model_selector],
1014
  outputs=[report_output, references_output]
1015
  )
1016
 
 
7
  load_dotenv(override=True)
8
 
9
 
10
+ async def run_research(query: str, model_choice: str, conversation_history: list, progress=gr.Progress()):
11
  """Run research and yield updates for both report and references"""
12
  status_messages = []
13
  final_report_md = ""
 
39
  '''
40
 
41
  # Collect all chunks and parse structured messages
42
+ async for chunk in ResearchManager(model_choice).run(query, conversation_history):
43
  # Parse structured messages (format: TYPE|data)
44
  if "|" in chunk:
45
  msg_type, msg_data = chunk.split("|", 1)
 
254
  return html
255
 
256
 
257
+ async def run_simple_search(query: str, model_choice: str, conversation_history: list, progress=gr.Progress()):
258
+ """Run a quick follow-up search without full research workflow"""
259
+ progress(0, desc="🔍 Quick search starting...")
260
+
261
+ # Escape single quotes for JavaScript
262
+ query_escaped = query.replace("'", "'")
263
+
264
+ query_display = f'''
265
+ <div class="user-query simple-search">
266
+ <div class="query-header">
267
+ <div class="query-label">Your Follow-up Question:</div>
268
+ <div class="query-actions">
269
+ <button class="icon-btn" onclick="navigator.clipboard.writeText('{query_escaped}'); this.innerHTML='✓ Copied'; setTimeout(() => this.innerHTML='📋 Copy', 2000);" title="Copy query">
270
+ 📋 Copy
271
+ </button>
272
+ </div>
273
+ </div>
274
+ <div class="query-text">{query}</div>
275
+ </div>
276
+ '''
277
+
278
+ answer_text = ""
279
+
280
+ async for chunk in ResearchManager(model_choice).run_simple_search(query, conversation_history):
281
+ # Parse structured messages
282
+ if "|" in chunk:
283
+ msg_type, msg_data = chunk.split("|", 1)
284
+
285
+ if msg_type == "SIMPLE_SEARCH_START":
286
+ progress(0.3, desc="🔍 Searching...")
287
+ yield query_display + '<div class="status-message">• Searching...</div>', ""
288
+
289
+ elif msg_type == "SIMPLE_SEARCH_COMPLETE":
290
+ answer_text = msg_data
291
+ progress(1.0, desc="✅ Complete!")
292
+
293
+ # Convert markdown to HTML
294
+ answer_html = markdown.markdown(
295
+ answer_text,
296
+ extensions=['extra', 'codehilite', 'tables', 'fenced_code']
297
+ )
298
+
299
+ # Add answer actions
300
+ answer_actions = '''
301
+ <div class="answer-actions">
302
+ <button class="icon-btn" onclick="
303
+ const answerText = document.querySelector('.simple-answer').innerText;
304
+ navigator.clipboard.writeText(answerText);
305
+ this.innerHTML='✓ Copied';
306
+ setTimeout(() => this.innerHTML='📋 Copy Answer', 2000);
307
+ " title="Copy answer">
308
+ 📋 Copy Answer
309
+ </button>
310
+ </div>
311
+ '''
312
+
313
+ final_html = query_display + '<div class="simple-answer">' + answer_html + '</div>' + answer_actions
314
+ yield final_html, ""
315
+ return
316
+
317
+ elif msg_type == "SIMPLE_SEARCH_ERROR":
318
+ error_html = query_display + f'<div class="error-message">Error: {msg_data}</div>'
319
+ yield error_html, ""
320
+ return
321
+
322
+ # Fallback if no complete message
323
+ if answer_text:
324
+ answer_html = markdown.markdown(answer_text, extensions=['extra', 'codehilite', 'tables', 'fenced_code'])
325
+ yield query_display + '<div class="simple-answer">' + answer_html + '</div>', ""
326
+
327
+
328
  # Create custom dark theme
329
  luntre_theme = gr.themes.Base(
330
  primary_hue="green",
 
500
  font-weight: 400;
501
  }
502
 
503
+ /* Simple answer styling */
504
+ .simple-answer {
505
+ background: rgba(45, 45, 45, 0.3);
506
+ border: 1px solid rgba(55, 65, 81, 0.3);
507
+ border-radius: 12px;
508
+ padding: 1.5rem;
509
+ margin-top: 1rem;
510
+ color: #E5E7EB;
511
+ line-height: 1.7;
512
+ }
513
+
514
+ .answer-actions {
515
+ display: flex;
516
+ justify-content: flex-start;
517
+ align-items: center;
518
+ margin-top: 1rem;
519
+ padding-top: 1rem;
520
+ border-top: 1px solid #374151;
521
+ }
522
+
523
+ .error-message {
524
+ background: rgba(239, 68, 68, 0.1);
525
+ border: 1px solid rgba(239, 68, 68, 0.3);
526
+ border-radius: 8px;
527
+ padding: 1rem;
528
+ margin-top: 1rem;
529
+ color: #FCA5A5;
530
+ }
531
+
532
  /* Report action buttons */
533
  .report-actions {
534
  display: flex;
 
995
  with gr.Blocks(theme=luntre_theme, css=custom_css, title="Luntre AI - Deep Research") as demo:
996
  # State to store current query for rewrite functionality
997
  current_query_state = gr.State("")
998
+ # State to store conversation history
999
+ conversation_history_state = gr.State([])
1000
 
1001
  # Header
1002
  gr.HTML("""
 
1035
  with gr.Row(elem_classes="controls-row"):
1036
  run_btn = gr.Button("▶ Run Research", variant="primary", elem_classes="run-button")
1037
  search_btn = gr.Button("▶ Run Search", variant="secondary", elem_classes="search-button")
1038
+ clear_conv_btn = gr.Button("🗑️ Clear", variant="secondary", elem_classes="search-button")
1039
  model_selector = gr.Dropdown(
1040
  choices=[
1041
  "Gemini 2.5 Flash",
 
1068
  """Clear the input box"""
1069
  return ""
1070
 
1071
+ def add_query_to_history(query, conversation_history):
1072
+ """Add user query to conversation history"""
1073
+ import datetime
1074
+ conversation_history.append({
1075
+ "type": "query",
1076
+ "content": query,
1077
+ "timestamp": datetime.datetime.now().isoformat()
1078
+ })
1079
+ return conversation_history
1080
+
1081
+ def add_report_to_history(report_html, conversation_history):
1082
+ """Add report to conversation history"""
1083
+ import datetime
1084
+ conversation_history.append({
1085
+ "type": "report",
1086
+ "content": report_html,
1087
+ "timestamp": datetime.datetime.now().isoformat()
1088
+ })
1089
+ return conversation_history
1090
+
1091
+ def add_simple_search_to_history(answer_html, conversation_history):
1092
+ """Add simple search answer to conversation history"""
1093
+ import datetime
1094
+ conversation_history.append({
1095
+ "type": "simple_search",
1096
+ "content": answer_html,
1097
+ "timestamp": datetime.datetime.now().isoformat()
1098
+ })
1099
+ return conversation_history
1100
+
1101
+ def clear_conversation():
1102
+ """Clear conversation history"""
1103
+ return []
1104
+
1105
  # Run research
1106
  run_event = run_btn.click(
1107
  fn=update_query_state,
1108
  inputs=[query_input],
1109
  outputs=[current_query_state],
1110
  queue=False
1111
+ ).then(
1112
+ fn=add_query_to_history,
1113
+ inputs=[current_query_state, conversation_history_state],
1114
+ outputs=[conversation_history_state],
1115
+ queue=False
1116
  ).then(
1117
  fn=clear_input,
1118
  inputs=[],
 
1120
  queue=False
1121
  ).then(
1122
  fn=run_research,
1123
+ inputs=[current_query_state, model_selector, conversation_history_state],
1124
  outputs=[report_output, references_output]
1125
  )
1126
 
 
1135
  # Rewrite (run again with same query)
1136
  rewrite_event = rewrite_btn.click(
1137
  fn=run_research,
1138
+ inputs=[current_query_state, model_selector, conversation_history_state],
1139
  outputs=[report_output, references_output]
1140
  )
1141
 
1142
+ # Run simple search
1143
+ search_event = search_btn.click(
1144
+ fn=update_query_state,
1145
+ inputs=[query_input],
1146
+ outputs=[current_query_state],
1147
+ queue=False
1148
+ ).then(
1149
+ fn=add_query_to_history,
1150
+ inputs=[current_query_state, conversation_history_state],
1151
+ outputs=[conversation_history_state],
1152
+ queue=False
1153
+ ).then(
1154
+ fn=clear_input,
1155
+ inputs=[],
1156
+ outputs=[query_input],
1157
+ queue=False
1158
+ ).then(
1159
+ fn=run_simple_search,
1160
+ inputs=[current_query_state, model_selector, conversation_history_state],
1161
+ outputs=[report_output, references_output]
1162
+ )
1163
+
1164
+ # Clear conversation
1165
+ def reset_conversation():
1166
+ """Reset conversation and display welcome message"""
1167
+ return (
1168
+ [],
1169
+ "<div class='welcome-message'>Welcome! Enter your research query below to get started.</div>",
1170
+ "<div class='no-references'>No references yet. Run a research query to see sources.</div>"
1171
+ )
1172
+
1173
+ clear_conv_event = clear_conv_btn.click(
1174
+ fn=reset_conversation,
1175
+ inputs=[],
1176
+ outputs=[conversation_history_state, report_output, references_output],
1177
+ queue=False
1178
+ )
1179
+
1180
+ # Also allow Enter key to submit (default to Run Research)
1181
  query_input.submit(
1182
  fn=update_query_state,
1183
  inputs=[query_input],
1184
  outputs=[current_query_state],
1185
  queue=False
1186
+ ).then(
1187
+ fn=add_query_to_history,
1188
+ inputs=[current_query_state, conversation_history_state],
1189
+ outputs=[conversation_history_state],
1190
+ queue=False
1191
  ).then(
1192
  fn=clear_input,
1193
  inputs=[],
 
1195
  queue=False
1196
  ).then(
1197
  fn=run_research,
1198
+ inputs=[current_query_state, model_selector, conversation_history_state],
1199
  outputs=[report_output, references_output]
1200
  )
1201
 
planner_agent.py CHANGED
@@ -4,9 +4,16 @@ from gemini_model import gemini_model
4
 
5
  HOW_MANY_SEARCHES = 10
6
 
7
- INSTRUCTIONS = f"You are a helpful research assistant. Given a query, come up with a set of web searches \
8
- to perform to best answer the query. Output {HOW_MANY_SEARCHES} diverse and comprehensive terms to query for, \
9
- covering different aspects and perspectives of the topic."
 
 
 
 
 
 
 
10
 
11
 
12
  class WebSearchItem(BaseModel):
 
4
 
5
  HOW_MANY_SEARCHES = 10
6
 
7
+ INSTRUCTIONS = f"You are a helpful research assistant. Given a query (and potentially previous conversation history), \
8
+ come up with a set of web searches to perform to best answer the query.\n\n\
9
+ IMPORTANT CONTEXT AWARENESS:\n\
10
+ - If previous research is provided in the context, review it carefully\n\
11
+ - Plan searches that BUILD UPON previous findings rather than repeating them\n\
12
+ - Avoid redundant searches for topics already thoroughly covered\n\
13
+ - Focus on NEW aspects, follow-up questions, or gaps in previous research\n\
14
+ - If this is a follow-up question, tailor searches to specifically address the new angle\n\n\
15
+ Output {HOW_MANY_SEARCHES} diverse and comprehensive search terms that cover different aspects and perspectives, \
16
+ while avoiding redundancy with any previous research already conducted."
17
 
18
 
19
  class WebSearchItem(BaseModel):
research_manager.py CHANGED
@@ -42,8 +42,30 @@ class ResearchManager:
42
  # Record this request
43
  self.request_times.append(current_time)
44
 
45
- async def run(self, query: str):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  """ Run the deep research process, yielding the status updates and the final report"""
 
 
 
47
  trace_id = gen_trace_id()
48
  model_display = get_model_display_name(self.model_choice)
49
 
@@ -52,7 +74,7 @@ class ResearchManager:
52
  yield f"INIT|Using Brave Search API and {model_display}"
53
  print("Starting research...")
54
 
55
- search_plan = await self.plan_searches(query)
56
  num_searches = len(search_plan.searches)
57
  yield f"PLANNING_COMPLETE|{num_searches}"
58
 
@@ -68,7 +90,7 @@ class ResearchManager:
68
  yield "SEARCH_COMPLETE|All searches finished"
69
 
70
  yield "WRITING_START|Starting to write report..."
71
- report = await self.write_report(query, results)
72
  print(f"DEBUG: Report object created, markdown_report length: {len(report.markdown_report)}")
73
 
74
  # Yield the report BEFORE sending email
@@ -79,8 +101,11 @@ class ResearchManager:
79
  yield "COMPLETE|Research complete"
80
 
81
 
82
- async def plan_searches(self, query: str) -> WebSearchPlan:
83
  """ Plan the searches to perform for the query """
 
 
 
84
  print("Planning searches...")
85
  await self.wait_for_rate_limit()
86
 
@@ -93,9 +118,13 @@ class ResearchManager:
93
  output_type=WebSearchPlan,
94
  )
95
 
 
 
 
 
96
  result = await Runner.run(
97
  dynamic_planner,
98
- f"Query: {query}",
99
  )
100
  print(f"Will perform {len(result.final_output.searches)} searches")
101
  return result.final_output_as(WebSearchPlan)
@@ -150,10 +179,16 @@ class ResearchManager:
150
  return None
151
  return None
152
 
153
- async def write_report(self, query: str, search_results: list[str]) -> ReportData:
154
  """ Write the report for the query with retry logic """
 
 
 
155
  print("Thinking about report...")
156
- input = f"Original query: {query}\nSummarized search results: {search_results}"
 
 
 
157
 
158
  # Create writer with selected model
159
  dynamic_writer = Agent(
@@ -226,4 +261,38 @@ class ResearchManager:
226
  return report # Return without sending email
227
  else:
228
  print(f"Email sending failed: {str(e)}")
229
- return report
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  # Record this request
43
  self.request_times.append(current_time)
44
 
45
+ def format_conversation_history(self, conversation_history: list) -> str:
46
+ """Format conversation history for context injection into agent prompts"""
47
+ if not conversation_history:
48
+ return ""
49
+
50
+ formatted = "\n\n=== PREVIOUS CONVERSATION HISTORY ===\n\n"
51
+ for idx, turn in enumerate(conversation_history, 1):
52
+ if turn.get("type") == "query":
53
+ formatted += f"--- Previous Query {idx} ---\n{turn['content']}\n\n"
54
+ elif turn.get("type") in ["report", "simple_search"]:
55
+ # Truncate long reports to first 1000 chars to save context
56
+ content = turn['content']
57
+ if len(content) > 2000:
58
+ content = content[:2000] + "\n... [Report truncated for context] ..."
59
+ formatted += f"--- Previous {'Report' if turn['type'] == 'report' else 'Answer'} {idx} ---\n{content}\n\n"
60
+
61
+ formatted += "=== END OF PREVIOUS CONVERSATION ===\n\n"
62
+ return formatted
63
+
64
+ async def run(self, query: str, conversation_history: list = None):
65
  """ Run the deep research process, yielding the status updates and the final report"""
66
+ if conversation_history is None:
67
+ conversation_history = []
68
+
69
  trace_id = gen_trace_id()
70
  model_display = get_model_display_name(self.model_choice)
71
 
 
74
  yield f"INIT|Using Brave Search API and {model_display}"
75
  print("Starting research...")
76
 
77
+ search_plan = await self.plan_searches(query, conversation_history)
78
  num_searches = len(search_plan.searches)
79
  yield f"PLANNING_COMPLETE|{num_searches}"
80
 
 
90
  yield "SEARCH_COMPLETE|All searches finished"
91
 
92
  yield "WRITING_START|Starting to write report..."
93
+ report = await self.write_report(query, results, conversation_history)
94
  print(f"DEBUG: Report object created, markdown_report length: {len(report.markdown_report)}")
95
 
96
  # Yield the report BEFORE sending email
 
101
  yield "COMPLETE|Research complete"
102
 
103
 
104
+ async def plan_searches(self, query: str, conversation_history: list = None) -> WebSearchPlan:
105
  """ Plan the searches to perform for the query """
106
+ if conversation_history is None:
107
+ conversation_history = []
108
+
109
  print("Planning searches...")
110
  await self.wait_for_rate_limit()
111
 
 
118
  output_type=WebSearchPlan,
119
  )
120
 
121
+ # Format the input with conversation history if available
122
+ context = self.format_conversation_history(conversation_history)
123
+ input_text = f"{context}Current Query: {query}"
124
+
125
  result = await Runner.run(
126
  dynamic_planner,
127
+ input_text,
128
  )
129
  print(f"Will perform {len(result.final_output.searches)} searches")
130
  return result.final_output_as(WebSearchPlan)
 
179
  return None
180
  return None
181
 
182
+ async def write_report(self, query: str, search_results: list[str], conversation_history: list = None) -> ReportData:
183
  """ Write the report for the query with retry logic """
184
+ if conversation_history is None:
185
+ conversation_history = []
186
+
187
  print("Thinking about report...")
188
+
189
+ # Format the input with conversation history if available
190
+ context = self.format_conversation_history(conversation_history)
191
+ input = f"{context}Current Query: {query}\n\nNew Search Results: {search_results}"
192
 
193
  # Create writer with selected model
194
  dynamic_writer = Agent(
 
261
  return report # Return without sending email
262
  else:
263
  print(f"Email sending failed: {str(e)}")
264
+ return report
265
+
266
+ async def run_simple_search(self, query: str, conversation_history: list = None):
267
+ """Run a quick follow-up search without full research workflow"""
268
+ if conversation_history is None:
269
+ conversation_history = []
270
+
271
+ print("Running simple search...")
272
+ yield "SIMPLE_SEARCH_START|Starting quick search..."
273
+
274
+ # Import simple search agent
275
+ from simple_search_agent import simple_search_agent
276
+
277
+ # Format conversation history for context
278
+ context = self.format_conversation_history(conversation_history)
279
+ input_text = f"{context}Current Question: {query}"
280
+
281
+ try:
282
+ await self.wait_for_rate_limit()
283
+
284
+ # Run the simple search agent
285
+ result = await Runner.run(
286
+ simple_search_agent,
287
+ input_text,
288
+ )
289
+
290
+ answer = str(result.final_output)
291
+ print("Simple search complete")
292
+
293
+ yield f"SIMPLE_SEARCH_COMPLETE|{answer}"
294
+
295
+ except Exception as e:
296
+ error_message = f"Simple search failed: {str(e)}"
297
+ print(error_message)
298
+ yield f"SIMPLE_SEARCH_ERROR|{error_message}"
simple_search_agent.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agents import Agent, ModelSettings
2
+ from brave_search_tool import brave_web_search
3
+ from gemini_model import gemini_model
4
+
5
+ INSTRUCTIONS = (
6
+ "You are a research assistant providing quick follow-up answers to user questions. "
7
+ "You will be given:\n"
8
+ "1. The user's current question\n"
9
+ "2. Previous conversation history (prior questions and research reports)\n\n"
10
+
11
+ "Your task:\n"
12
+ "- Answer the user's question concisely (300-500 words)\n"
13
+ "- First check if previous reports already contain the answer\n"
14
+ "- If you need NEW information, use the search tool for 1-2 targeted searches (NOT 10 searches)\n"
15
+ "- Reference previous reports when relevant using 'As mentioned in the previous report...'\n"
16
+ "- Build upon and connect to previous research findings\n"
17
+ "- Cite sources using [Source Title](URL) format\n"
18
+ "- Be direct and efficient - this is a quick follow-up, not a comprehensive report\n\n"
19
+
20
+ "Output format:\n"
21
+ "Write a clear, concise answer in markdown format. Include inline citations when making claims. "
22
+ "If you performed searches, add a brief '## Sources' section at the end with links."
23
+ )
24
+
25
+ simple_search_agent = Agent(
26
+ name="Simple Search Agent",
27
+ instructions=INSTRUCTIONS,
28
+ tools=[brave_web_search],
29
+ model=gemini_model,
30
+ model_settings=ModelSettings(
31
+ max_tokens=2000, # Shorter responses
32
+ temperature=0.7,
33
+ ),
34
+ )
writer_agent.py CHANGED
@@ -6,7 +6,10 @@ from gemini_model import gemini_model
6
  # structured output truncation (see: https://discuss.ai.google.dev/t/107176)
7
  INSTRUCTIONS = (
8
  "You are a senior researcher tasked with writing a comprehensive, well-structured report for a research query. "
9
- "You will be provided with the original query and initial research done by a research assistant.\n\n"
 
 
 
10
 
11
  "REQUIREMENTS:\n"
12
  "- Write a COMPLETE report that thoroughly addresses the query (typically 1500-2500 words)\n"
@@ -16,6 +19,14 @@ INSTRUCTIONS = (
16
  "- Each section should be substantive and well-developed\n"
17
  "- Use markdown format with proper headings, subheadings, lists, and formatting\n\n"
18
 
 
 
 
 
 
 
 
 
19
  "CITATIONS AND REFERENCES:\n"
20
  "- When making specific claims or citing facts, use NUMBERED citations like [1], [2], [3] etc.\n"
21
  "- Extract URLs from the research summaries provided to you\n"
 
6
  # structured output truncation (see: https://discuss.ai.google.dev/t/107176)
7
  INSTRUCTIONS = (
8
  "You are a senior researcher tasked with writing a comprehensive, well-structured report for a research query. "
9
+ "You will be provided with:\n"
10
+ "1. The current query\n"
11
+ "2. New research findings from your research assistant\n"
12
+ "3. PREVIOUS CONVERSATION HISTORY (if any) - including prior queries and reports\n\n"
13
 
14
  "REQUIREMENTS:\n"
15
  "- Write a COMPLETE report that thoroughly addresses the query (typically 1500-2500 words)\n"
 
19
  "- Each section should be substantive and well-developed\n"
20
  "- Use markdown format with proper headings, subheadings, lists, and formatting\n\n"
21
 
22
+ "CONTEXT AWARENESS:\n"
23
+ "- If previous conversation history is provided, carefully review it\n"
24
+ "- Reference and BUILD UPON previous reports when relevant (e.g., 'As discussed in the previous report...')\n"
25
+ "- Show connections between current and previous research findings\n"
26
+ "- Avoid repeating information already covered in detail - instead reference it and add new insights\n"
27
+ "- If this is a follow-up question, directly address how it relates to previous research\n"
28
+ "- Maintain continuity in the conversation flow\n\n"
29
+
30
  "CITATIONS AND REFERENCES:\n"
31
  "- When making specific claims or citing facts, use NUMBERED citations like [1], [2], [3] etc.\n"
32
  "- Extract URLs from the research summaries provided to you\n"