Spaces:
Sleeping
Sleeping
jedick
commited on
Commit
·
3472410
1
Parent(s):
404f284
Use custom chat interface
Browse files- app.py +96 -69
- prompts.py +6 -9
app.py
CHANGED
|
@@ -63,6 +63,11 @@ def run_workflow(input, history, thread_id):
|
|
| 63 |
|
| 64 |
print(f"Using thread_id: {thread_id}")
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
# Asynchronously stream graph steps for a single input
|
| 67 |
# https://langchain-ai.lang.chat/langgraph/reference/graphs/#langgraph.graph.state.CompiledStateGraph
|
| 68 |
for step in graph.stream(
|
|
@@ -98,6 +103,7 @@ def run_workflow(input, history, thread_id):
|
|
| 98 |
)
|
| 99 |
)
|
| 100 |
if chunk_messages.content:
|
|
|
|
| 101 |
history.append(
|
| 102 |
gr.ChatMessage(role="assistant", content=chunk_messages.content)
|
| 103 |
)
|
|
@@ -214,6 +220,20 @@ with gr.Blocks(
|
|
| 214 |
css=css,
|
| 215 |
) as demo:
|
| 216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
# -----------------
|
| 218 |
# Define components
|
| 219 |
# -----------------
|
|
@@ -233,7 +253,7 @@ with gr.Blocks(
|
|
| 233 |
downloading = gr.Textbox(
|
| 234 |
lines=1,
|
| 235 |
label="Downloading Data, Please Wait",
|
| 236 |
-
visible=
|
| 237 |
render=False,
|
| 238 |
)
|
| 239 |
extracting = gr.Textbox(
|
|
@@ -268,6 +288,29 @@ with gr.Blocks(
|
|
| 268 |
show_copy_all_button=True,
|
| 269 |
render=False,
|
| 270 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
|
| 272 |
# ------------
|
| 273 |
# Set up state
|
|
@@ -314,7 +357,7 @@ with gr.Blocks(
|
|
| 314 |
if compute_mode.startswith("edge"):
|
| 315 |
status_text = f"""
|
| 316 |
📍 Now in **edge** mode, using ZeroGPU hardware<br>
|
| 317 |
-
⌛ Response time is
|
| 318 |
✨ Embeddings: [Nomic](https://huggingface.co/nomic-ai/nomic-embed-text-v1.5); LLM: [{model_id}](https://huggingface.co/{model_id})<br>
|
| 319 |
🏠 See the project's [GitHub repository](https://github.com/jedick/R-help-chat)
|
| 320 |
"""
|
|
@@ -339,31 +382,21 @@ with gr.Blocks(
|
|
| 339 |
return info_text
|
| 340 |
|
| 341 |
with gr.Row():
|
| 342 |
-
# Left column: Intro, Compute, Chat
|
| 343 |
with gr.Column(scale=2):
|
| 344 |
with gr.Row(elem_classes=["row-container"]):
|
| 345 |
with gr.Column(scale=2):
|
| 346 |
intro = gr.Markdown(get_intro_text())
|
| 347 |
with gr.Column(scale=1):
|
| 348 |
compute_mode.render()
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
additional_inputs=[thread_id],
|
| 354 |
-
additional_outputs=[retrieved_emails, citations_text],
|
| 355 |
-
api_name=False,
|
| 356 |
-
)
|
| 357 |
downloading.render()
|
| 358 |
extracting.render()
|
| 359 |
data_error.render()
|
| 360 |
-
|
| 361 |
-
label="Retrieved Emails",
|
| 362 |
-
lines=10,
|
| 363 |
-
visible=False,
|
| 364 |
-
info="Tip: Look for 'Tool Call' and 'Next Email' separators. Quoted lines (starting with '>') are removed before indexing.",
|
| 365 |
-
)
|
| 366 |
-
# Right column: Info, Examples, Citations
|
| 367 |
with gr.Column(scale=1):
|
| 368 |
status = gr.Markdown(get_status_text(compute_mode.value))
|
| 369 |
with gr.Accordion("ℹ️ More Info", open=False):
|
|
@@ -380,7 +413,7 @@ with gr.Blocks(
|
|
| 380 |
]
|
| 381 |
gr.Examples(
|
| 382 |
examples=[[q] for q in example_questions],
|
| 383 |
-
inputs=[
|
| 384 |
label="Click an example to fill the message box",
|
| 385 |
elem_id="example-questions",
|
| 386 |
)
|
|
@@ -390,7 +423,7 @@ with gr.Blocks(
|
|
| 390 |
]
|
| 391 |
gr.Examples(
|
| 392 |
examples=[[q] for q in multi_tool_questions],
|
| 393 |
-
inputs=[
|
| 394 |
label="Multiple retrievals (cloud mode)",
|
| 395 |
elem_id="example-questions",
|
| 396 |
)
|
|
@@ -400,11 +433,17 @@ with gr.Blocks(
|
|
| 400 |
]
|
| 401 |
gr.Examples(
|
| 402 |
examples=[[q] for q in multi_turn_questions],
|
| 403 |
-
inputs=[
|
| 404 |
label="Asking follow-up questions",
|
| 405 |
elem_id="example-questions",
|
| 406 |
)
|
| 407 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 408 |
|
| 409 |
# -------------
|
| 410 |
# App functions
|
|
@@ -434,23 +473,23 @@ with gr.Blocks(
|
|
| 434 |
"""Return updated visibility state for a component"""
|
| 435 |
return gr.update(visible=visible)
|
| 436 |
|
| 437 |
-
def
|
| 438 |
-
if
|
| 439 |
-
#
|
| 440 |
-
return
|
| 441 |
-
elif
|
| 442 |
-
#
|
| 443 |
-
return retrieved_emails, change_visibility(True)
|
| 444 |
-
else:
|
| 445 |
-
# This blanks out the textbox when a new chat is started
|
| 446 |
-
return "", change_visibility(False)
|
| 447 |
-
|
| 448 |
-
def update_citations(citations):
|
| 449 |
-
if citations == []:
|
| 450 |
-
# Blank out and hide the citations textbox when new input is submitted
|
| 451 |
return "", change_visibility(False)
|
| 452 |
else:
|
| 453 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
|
| 455 |
# --------------
|
| 456 |
# Event handlers
|
|
@@ -494,9 +533,17 @@ with gr.Blocks(
|
|
| 494 |
api_name=False,
|
| 495 |
)
|
| 496 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 497 |
retrieved_emails.change(
|
| 498 |
# Update the emails textbox
|
| 499 |
-
|
| 500 |
[retrieved_emails, emails_textbox],
|
| 501 |
[emails_textbox, emails_textbox],
|
| 502 |
api_name=False,
|
|
@@ -504,8 +551,8 @@ with gr.Blocks(
|
|
| 504 |
|
| 505 |
citations_text.change(
|
| 506 |
# Update the citations textbox
|
| 507 |
-
|
| 508 |
-
[citations_text],
|
| 509 |
[citations_textbox, citations_textbox],
|
| 510 |
api_name=False,
|
| 511 |
)
|
|
@@ -514,16 +561,6 @@ with gr.Blocks(
|
|
| 514 |
# Data loading
|
| 515 |
# ------------
|
| 516 |
|
| 517 |
-
def is_data_present():
|
| 518 |
-
"""Check if the database directory is present"""
|
| 519 |
-
|
| 520 |
-
return os.path.isdir(db_dir)
|
| 521 |
-
|
| 522 |
-
def is_data_missing():
|
| 523 |
-
"""Check if the database directory is missing"""
|
| 524 |
-
|
| 525 |
-
return not os.path.isdir(db_dir)
|
| 526 |
-
|
| 527 |
def download():
|
| 528 |
"""Download the db.zip file"""
|
| 529 |
|
|
@@ -555,30 +592,22 @@ with gr.Blocks(
|
|
| 555 |
return None
|
| 556 |
|
| 557 |
false = gr.State(False)
|
| 558 |
-
true = gr.State(True)
|
| 559 |
need_data = gr.State()
|
| 560 |
have_data = gr.State()
|
| 561 |
|
| 562 |
# When app is launched, check if data is present, download it if necessary,
|
| 563 |
-
#
|
| 564 |
-
#
|
| 565 |
-
#
|
|
|
|
| 566 |
|
| 567 |
# fmt: off
|
| 568 |
demo.load(
|
| 569 |
-
is_data_missing, None, [need_data], api_name=False
|
| 570 |
-
).then(
|
| 571 |
-
is_data_present, None, [have_data], api_name=False
|
| 572 |
-
).then(
|
| 573 |
-
change_visibility, [have_data], [chatbot], api_name=False
|
| 574 |
-
).then(
|
| 575 |
-
change_visibility, [have_data], [chat_interface.textbox], api_name=False
|
| 576 |
-
).then(
|
| 577 |
-
change_visibility, [need_data], [downloading], api_name=False
|
| 578 |
-
).then(
|
| 579 |
download, None, [downloading], api_name=False
|
| 580 |
).then(
|
| 581 |
change_visibility, [false], [downloading], api_name=False
|
|
|
|
|
|
|
| 582 |
).then(
|
| 583 |
change_visibility, [need_data], [extracting], api_name=False
|
| 584 |
).then(
|
|
@@ -586,17 +615,15 @@ with gr.Blocks(
|
|
| 586 |
).then(
|
| 587 |
change_visibility, [false], [extracting], api_name=False
|
| 588 |
).then(
|
| 589 |
-
|
| 590 |
).then(
|
| 591 |
is_data_present, None, [have_data], api_name=False
|
| 592 |
).then(
|
| 593 |
-
change_visibility, [have_data], [
|
| 594 |
).then(
|
| 595 |
-
|
| 596 |
).then(
|
| 597 |
change_visibility, [need_data], [data_error], api_name=False
|
| 598 |
-
).then(
|
| 599 |
-
get_info_text, None, [info], api_name=False
|
| 600 |
)
|
| 601 |
# fmt: on
|
| 602 |
|
|
|
|
| 63 |
|
| 64 |
print(f"Using thread_id: {thread_id}")
|
| 65 |
|
| 66 |
+
# Display the user input in the chatbot
|
| 67 |
+
history.append(gr.ChatMessage(role="user", content=input))
|
| 68 |
+
# Return the message history and empty lists for emails and citations texboxes
|
| 69 |
+
yield history, [], []
|
| 70 |
+
|
| 71 |
# Asynchronously stream graph steps for a single input
|
| 72 |
# https://langchain-ai.lang.chat/langgraph/reference/graphs/#langgraph.graph.state.CompiledStateGraph
|
| 73 |
for step in graph.stream(
|
|
|
|
| 103 |
)
|
| 104 |
)
|
| 105 |
if chunk_messages.content:
|
| 106 |
+
# Display response made instead of or in addition to a tool call
|
| 107 |
history.append(
|
| 108 |
gr.ChatMessage(role="assistant", content=chunk_messages.content)
|
| 109 |
)
|
|
|
|
| 220 |
css=css,
|
| 221 |
) as demo:
|
| 222 |
|
| 223 |
+
# -----------------
|
| 224 |
+
# Data availability
|
| 225 |
+
# -----------------
|
| 226 |
+
|
| 227 |
+
def is_data_present():
|
| 228 |
+
"""Check if the database directory is present"""
|
| 229 |
+
|
| 230 |
+
return os.path.isdir(db_dir)
|
| 231 |
+
|
| 232 |
+
def is_data_missing():
|
| 233 |
+
"""Check if the database directory is missing"""
|
| 234 |
+
|
| 235 |
+
return not os.path.isdir(db_dir)
|
| 236 |
+
|
| 237 |
# -----------------
|
| 238 |
# Define components
|
| 239 |
# -----------------
|
|
|
|
| 253 |
downloading = gr.Textbox(
|
| 254 |
lines=1,
|
| 255 |
label="Downloading Data, Please Wait",
|
| 256 |
+
visible=is_data_missing(),
|
| 257 |
render=False,
|
| 258 |
)
|
| 259 |
extracting = gr.Textbox(
|
|
|
|
| 288 |
show_copy_all_button=True,
|
| 289 |
render=False,
|
| 290 |
)
|
| 291 |
+
# Modified from gradio/chat_interface.py
|
| 292 |
+
input = gr.Textbox(
|
| 293 |
+
show_label=False,
|
| 294 |
+
label="Message",
|
| 295 |
+
placeholder="Type a message...",
|
| 296 |
+
scale=7,
|
| 297 |
+
autofocus=True,
|
| 298 |
+
submit_btn=True,
|
| 299 |
+
render=False,
|
| 300 |
+
)
|
| 301 |
+
emails_textbox = gr.Textbox(
|
| 302 |
+
label="Retrieved Emails",
|
| 303 |
+
info="Tip: Look for 'Tool Call' and 'Next Email' separators. Quoted lines (starting with '>') are removed before indexing.",
|
| 304 |
+
lines=10,
|
| 305 |
+
visible=False,
|
| 306 |
+
render=False,
|
| 307 |
+
)
|
| 308 |
+
citations_textbox = gr.Textbox(
|
| 309 |
+
label="Citations",
|
| 310 |
+
lines=2,
|
| 311 |
+
visible=False,
|
| 312 |
+
render=False,
|
| 313 |
+
)
|
| 314 |
|
| 315 |
# ------------
|
| 316 |
# Set up state
|
|
|
|
| 357 |
if compute_mode.startswith("edge"):
|
| 358 |
status_text = f"""
|
| 359 |
📍 Now in **edge** mode, using ZeroGPU hardware<br>
|
| 360 |
+
⌛ Response time is around 2 minutes<br>
|
| 361 |
✨ Embeddings: [Nomic](https://huggingface.co/nomic-ai/nomic-embed-text-v1.5); LLM: [{model_id}](https://huggingface.co/{model_id})<br>
|
| 362 |
🏠 See the project's [GitHub repository](https://github.com/jedick/R-help-chat)
|
| 363 |
"""
|
|
|
|
| 382 |
return info_text
|
| 383 |
|
| 384 |
with gr.Row():
|
| 385 |
+
# Left column: Intro, Compute, Chat
|
| 386 |
with gr.Column(scale=2):
|
| 387 |
with gr.Row(elem_classes=["row-container"]):
|
| 388 |
with gr.Column(scale=2):
|
| 389 |
intro = gr.Markdown(get_intro_text())
|
| 390 |
with gr.Column(scale=1):
|
| 391 |
compute_mode.render()
|
| 392 |
+
with gr.Group(visible=is_data_present()) as chat_interface:
|
| 393 |
+
chatbot.render()
|
| 394 |
+
input.render()
|
| 395 |
+
# Render textboxes for data loading progress
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
downloading.render()
|
| 397 |
extracting.render()
|
| 398 |
data_error.render()
|
| 399 |
+
# Right column: Info, Examples
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
with gr.Column(scale=1):
|
| 401 |
status = gr.Markdown(get_status_text(compute_mode.value))
|
| 402 |
with gr.Accordion("ℹ️ More Info", open=False):
|
|
|
|
| 413 |
]
|
| 414 |
gr.Examples(
|
| 415 |
examples=[[q] for q in example_questions],
|
| 416 |
+
inputs=[input],
|
| 417 |
label="Click an example to fill the message box",
|
| 418 |
elem_id="example-questions",
|
| 419 |
)
|
|
|
|
| 423 |
]
|
| 424 |
gr.Examples(
|
| 425 |
examples=[[q] for q in multi_tool_questions],
|
| 426 |
+
inputs=[input],
|
| 427 |
label="Multiple retrievals (cloud mode)",
|
| 428 |
elem_id="example-questions",
|
| 429 |
)
|
|
|
|
| 433 |
]
|
| 434 |
gr.Examples(
|
| 435 |
examples=[[q] for q in multi_turn_questions],
|
| 436 |
+
inputs=[input],
|
| 437 |
label="Asking follow-up questions",
|
| 438 |
elem_id="example-questions",
|
| 439 |
)
|
| 440 |
+
|
| 441 |
+
# Bottom row: retrieved emails and citations
|
| 442 |
+
with gr.Row():
|
| 443 |
+
with gr.Column(scale=2):
|
| 444 |
+
emails_textbox.render()
|
| 445 |
+
with gr.Column(scale=1):
|
| 446 |
+
citations_textbox.render()
|
| 447 |
|
| 448 |
# -------------
|
| 449 |
# App functions
|
|
|
|
| 473 |
"""Return updated visibility state for a component"""
|
| 474 |
return gr.update(visible=visible)
|
| 475 |
|
| 476 |
+
def update_textbox(content, textbox):
|
| 477 |
+
if content is None:
|
| 478 |
+
# Keep the content of the textbox unchanged
|
| 479 |
+
return textbox, change_visibility(True)
|
| 480 |
+
elif content == []:
|
| 481 |
+
# Blank out the textbox
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 482 |
return "", change_visibility(False)
|
| 483 |
else:
|
| 484 |
+
# Display the content in the textbox
|
| 485 |
+
return content, change_visibility(True)
|
| 486 |
+
|
| 487 |
+
# def update_citations(citations):
|
| 488 |
+
# if citations == []:
|
| 489 |
+
# # Blank out and hide the citations textbox when new input is submitted
|
| 490 |
+
# return "", change_visibility(False)
|
| 491 |
+
# else:
|
| 492 |
+
# return citations, change_visibility(True)
|
| 493 |
|
| 494 |
# --------------
|
| 495 |
# Event handlers
|
|
|
|
| 533 |
api_name=False,
|
| 534 |
)
|
| 535 |
|
| 536 |
+
input.submit(
|
| 537 |
+
# Submit input to the chatbot
|
| 538 |
+
to_workflow,
|
| 539 |
+
[input, chatbot, thread_id],
|
| 540 |
+
[chatbot, retrieved_emails, citations_text],
|
| 541 |
+
api_name=False,
|
| 542 |
+
)
|
| 543 |
+
|
| 544 |
retrieved_emails.change(
|
| 545 |
# Update the emails textbox
|
| 546 |
+
update_textbox,
|
| 547 |
[retrieved_emails, emails_textbox],
|
| 548 |
[emails_textbox, emails_textbox],
|
| 549 |
api_name=False,
|
|
|
|
| 551 |
|
| 552 |
citations_text.change(
|
| 553 |
# Update the citations textbox
|
| 554 |
+
update_textbox,
|
| 555 |
+
[citations_text, citations_textbox],
|
| 556 |
[citations_textbox, citations_textbox],
|
| 557 |
api_name=False,
|
| 558 |
)
|
|
|
|
| 561 |
# Data loading
|
| 562 |
# ------------
|
| 563 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 564 |
def download():
|
| 565 |
"""Download the db.zip file"""
|
| 566 |
|
|
|
|
| 592 |
return None
|
| 593 |
|
| 594 |
false = gr.State(False)
|
|
|
|
| 595 |
need_data = gr.State()
|
| 596 |
have_data = gr.State()
|
| 597 |
|
| 598 |
# When app is launched, check if data is present, download it if necessary,
|
| 599 |
+
# show extracting step as textbox, show error textbox if needed,
|
| 600 |
+
# update database info, and restore chat interface.
|
| 601 |
+
# nb. initial visibility of chat interface components and
|
| 602 |
+
# downloading textbox are set after instantiation of ChatInterface above
|
| 603 |
|
| 604 |
# fmt: off
|
| 605 |
demo.load(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 606 |
download, None, [downloading], api_name=False
|
| 607 |
).then(
|
| 608 |
change_visibility, [false], [downloading], api_name=False
|
| 609 |
+
).then(
|
| 610 |
+
is_data_missing, None, [need_data], api_name=False
|
| 611 |
).then(
|
| 612 |
change_visibility, [need_data], [extracting], api_name=False
|
| 613 |
).then(
|
|
|
|
| 615 |
).then(
|
| 616 |
change_visibility, [false], [extracting], api_name=False
|
| 617 |
).then(
|
| 618 |
+
get_info_text, None, [info], api_name=False
|
| 619 |
).then(
|
| 620 |
is_data_present, None, [have_data], api_name=False
|
| 621 |
).then(
|
| 622 |
+
change_visibility, [have_data], [chat_interface], api_name=False
|
| 623 |
).then(
|
| 624 |
+
is_data_missing, None, [need_data], api_name=False
|
| 625 |
).then(
|
| 626 |
change_visibility, [need_data], [data_error], api_name=False
|
|
|
|
|
|
|
| 627 |
)
|
| 628 |
# fmt: on
|
| 629 |
|
prompts.py
CHANGED
|
@@ -17,15 +17,14 @@ def retrieve_prompt(compute_mode):
|
|
| 17 |
f"Today Date: {date.today()}. "
|
| 18 |
"You are a helpful RAG chatbot designed to answer questions about R programming based on the R-help mailing list. "
|
| 19 |
"Do not ask the user for more information, but retrieve emails from the R-help mailing list archives. "
|
|
|
|
| 20 |
f"The emails available for retrieval are from {start} to {end}. "
|
| 21 |
-
"Write a search query based on the user'
|
| 22 |
"For questions about differences or comparison between X and Y, retrieve emails about X and Y. "
|
| 23 |
-
"
|
|
|
|
| 24 |
# This confuses gpt-4o-mini (empty search_query - token problem?)
|
| 25 |
-
|
| 26 |
-
"Example: retrieve emails about R in <month> using retrieve_emails(search_query='R', months=<month>). "
|
| 27 |
-
"Try to infer years from the user's question (last month or this month is this year). "
|
| 28 |
-
"If you can infer years, use retrieve_emails(search_query=, start_year=, end_year=), otherwise retrieve_emails(search_query=). "
|
| 29 |
"If you decide not to retrieve emails, tell the user why and suggest how to improve their question to chat with the R-help mailing list. "
|
| 30 |
)
|
| 31 |
# A sanity check that we don't have unassigned variables
|
|
@@ -52,9 +51,7 @@ def answer_prompt(with_tools=True):
|
|
| 52 |
"Respond with 300 words maximum and 30 lines of code maximum and include any relevant URLs from the retrieved emails. "
|
| 53 |
)
|
| 54 |
if with_tools:
|
| 55 |
-
answer_prompt +=
|
| 56 |
-
"Use answer_with_citations to provide the answer and all citations used. "
|
| 57 |
-
)
|
| 58 |
matches = re.findall(r"\{.*?\}", "".join(answer_prompt))
|
| 59 |
if matches:
|
| 60 |
raise ValueError(f"Unassigned variables in prompt: {' '.join(matches)}")
|
|
|
|
| 17 |
f"Today Date: {date.today()}. "
|
| 18 |
"You are a helpful RAG chatbot designed to answer questions about R programming based on the R-help mailing list. "
|
| 19 |
"Do not ask the user for more information, but retrieve emails from the R-help mailing list archives. "
|
| 20 |
+
# gpt-4o-mini says last two months aren't available with this: Emails from from {start} to {end} are available for retrieval.
|
| 21 |
f"The emails available for retrieval are from {start} to {end}. "
|
| 22 |
+
"Write a search query based on the user's question, but do not answer the question just yet. "
|
| 23 |
"For questions about differences or comparison between X and Y, retrieve emails about X and Y. "
|
| 24 |
+
"If the user's question is about years, use retrieve_emails(search_query=, start_year=, end_year=) (this month is this year). "
|
| 25 |
+
"Example: to retrieve emails about R from a month in any year use retrieve_emails(search_query='R', months=<month>). "
|
| 26 |
# This confuses gpt-4o-mini (empty search_query - token problem?)
|
| 27 |
+
"Use 3-letter month abbreviations: Jan for January, Jul for July. "
|
|
|
|
|
|
|
|
|
|
| 28 |
"If you decide not to retrieve emails, tell the user why and suggest how to improve their question to chat with the R-help mailing list. "
|
| 29 |
)
|
| 30 |
# A sanity check that we don't have unassigned variables
|
|
|
|
| 51 |
"Respond with 300 words maximum and 30 lines of code maximum and include any relevant URLs from the retrieved emails. "
|
| 52 |
)
|
| 53 |
if with_tools:
|
| 54 |
+
answer_prompt += "Use answer_with_citations to provide the complete answer and all citations used. "
|
|
|
|
|
|
|
| 55 |
matches = re.findall(r"\{.*?\}", "".join(answer_prompt))
|
| 56 |
if matches:
|
| 57 |
raise ValueError(f"Unassigned variables in prompt: {' '.join(matches)}")
|