Skip to content

Commit 4fcd842

Browse files
committed
Standardized prompt templates and system prompt across the repo
1 parent bf98fb1 commit 4fcd842

File tree

9 files changed

+71
-38
lines changed

9 files changed

+71
-38
lines changed

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -927,15 +927,14 @@ will return much faster than the first query and we'll be certain the authors ma
927927
| `parsing.chunking_algorithm` | `ChunkingOptions.SIMPLE_OVERLAP` | Algorithm for chunking. |
928928
| `parsing.doc_filters` | `None` | Optional filters for allowed documents. |
929929
| `parsing.use_human_readable_clinical_trials` | `False` | Parse clinical trial JSONs into readable text. |
930-
| `prompt.summary` | `summary_prompt` | Template for summarizing text, must contain variables matching `summary_prompt`. |
930+
| `prompt.summary` | `summary_prompt` | User prompt template(s) to use when generating contextual summaries. |
931931
| `prompt.qa` | `qa_prompt` | Template for QA, must contain variables matching `qa_prompt`. |
932932
| `prompt.select` | `select_paper_prompt` | Template for selecting papers, must contain variables matching `select_paper_prompt`. |
933933
| `prompt.pre` | `None` | Optional pre-prompt templated with just the original question to append information before a qa prompt. |
934934
| `prompt.post` | `None` | Optional post-processing prompt that can access PQASession fields. |
935-
| `prompt.system` | `default_system_prompt` | System prompt for the model. |
935+
| `prompt.system` | `default_system_prompt` | System prompt to use when generating contextual summaries and answers. |
936936
| `prompt.use_json` | `True` | Whether to use JSON formatting. |
937-
| `prompt.summary_json` | `summary_json_prompt` | JSON-specific summary prompt. |
938-
| `prompt.summary_json_system` | `summary_json_system_prompt` | System prompt for JSON summaries. |
937+
| `prompt.summary_json` | `summary_json_prompt` | JSON-specific user prompt template(s) to use when generating contextual summaries. |
939938
| `prompt.context_outer` | `CONTEXT_OUTER_PROMPT` | Prompt for how to format all contexts in generate answer. |
940939
| `prompt.context_inner` | `CONTEXT_INNER_PROMPT` | Prompt for how to format a single context in generate answer. Must contain 'name' and 'text' variables. |
941940
| `agent.agent_llm` | `"gpt-4o-2024-11-20"` | Model to use for agent making tool selections. |

docs/tutorials/settings_tutorial.ipynb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@
129129
" default_system_prompt,\n",
130130
" env_reset_prompt,\n",
131131
" env_system_prompt,\n",
132+
" include_text_prompt_template,\n",
132133
" qa_prompt,\n",
133134
" select_paper_prompt,\n",
134135
" structured_citation_prompt,\n",
135-
" summary_json_prompt,\n",
136136
" summary_json_system_prompt,\n",
137137
" summary_prompt,\n",
138138
")\n",
@@ -201,8 +201,9 @@
201201
" post=None,\n",
202202
" system=default_system_prompt,\n",
203203
" use_json=True,\n",
204-
" summary_json=summary_json_prompt,\n",
205-
" summary_json_system=summary_json_system_prompt,\n",
204+
" summary_json=[\n",
205+
" summary_json_system_prompt, include_text_prompt_template\n",
206+
" ],\n",
206207
" context_outer=CONTEXT_OUTER_PROMPT,\n",
207208
" context_inner=CONTEXT_INNER_PROMPT,\n",
208209
" ),\n",

docs/tutorials/settings_tutorial.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ from paperqa.prompts import (
102102
default_system_prompt,
103103
env_reset_prompt,
104104
env_system_prompt,
105+
include_text_prompt_template,
105106
qa_prompt,
106107
select_paper_prompt,
107108
structured_citation_prompt,
108-
summary_json_prompt,
109109
summary_json_system_prompt,
110110
summary_prompt,
111111
)
@@ -174,8 +174,7 @@ settings = Settings(
174174
post=None,
175175
system=default_system_prompt,
176176
use_json=True,
177-
summary_json=summary_json_prompt,
178-
summary_json_system=summary_json_system_prompt,
177+
summary_json=[summary_json_system_prompt, include_text_prompt_template],
179178
context_outer=CONTEXT_OUTER_PROMPT,
180179
context_inner=CONTEXT_INNER_PROMPT,
181180
),

src/paperqa/configs/contracrow.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@
3636
"post": null,
3737
"system": "Answer in a direct and concise tone. Your audience is an expert, so be highly specific. If there are ambiguous terms or acronyms, first define them.",
3838
"use_json": true,
39-
"summary_json": "Excerpt from {citation}\n\n----\n\n{text}\n\n----\n\nQuestion: {question}\n\n",
40-
"summary_json_system": "Provide a summary of the relevant information that could help determine if a claim is contradicted or supported by this excerpt. The excerpt may be irrelevant. Do not directly answer if it is contradicted - only summarize relevant information. Respond with the following JSON format:\n\n{{\n \"summary\": \"...\",\n \"relevance_score\": \"...\"\n}}\n\nwhere `summary` is relevant information from excerpt ({summary_length}) and `relevance_score` is the relevance of `summary` to support or contradict the claim (integer out of 10). If any string entry in the JSON has newlines, be sure to escape them. "
39+
"summary_json": [
40+
"Provide a summary of the relevant information that could help determine if a claim is contradicted or supported by this excerpt. The excerpt may be irrelevant. Do not directly answer if it is contradicted - only summarize relevant information. Respond with the following JSON format:\n\n{{\n \"summary\": \"...\",\n \"relevance_score\": \"...\"\n}}\n\nwhere `summary` is relevant information from excerpt ({summary_length}) and `relevance_score` is the relevance of `summary` to support or contradict the claim (integer out of 10). If any string entry in the JSON has newlines, be sure to escape them.",
41+
"Excerpt from {citation}\n\n----\n\n{text}\n\n----\n\nQuestion: {question}"
42+
]
4143
},
4244
"agent": {
4345
"agent_llm": "gpt-4o-2024-08-06",

src/paperqa/configs/wikicrow.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@
3636
"post": null,
3737
"system": "Answer in a direct and concise tone.",
3838
"use_json": true,
39-
"summary_json": "Excerpt from {citation}\n\n----\n\n{text}\n\n----\n\nQuestion: {question}\n\n",
40-
"summary_json_system": "Provide a summary of the relevant information that could help answer the question based on the excerpt. The excerpt may be irrelevant. Do not directly answer the question - only summarize relevant information. \n\nRespond with the following JSON format:\n\n{{\n \"summary\": \"...\",\n \"relevance_score\": \"...\",\n \"gene_name: \"...\"\n}}\n\nwhere `summary` is relevant information from text - {summary_length}, \n`gene_name` is the gene discussed in the excerpt (may be different than query), and `relevance_score` is the relevance of `summary` to answer the question (integer out of 10)"
39+
"summary_json": [
40+
"Provide a summary of the relevant information that could help answer the question based on the excerpt. The excerpt may be irrelevant. Do not directly answer the question - only summarize relevant information. \n\nRespond with the following JSON format:\n\n{{\n \"summary\": \"...\",\n \"relevance_score\": \"...\",\n \"gene_name: \"...\"\n}}\n\nwhere `summary` is relevant information from text - {summary_length}, \n`gene_name` is the gene discussed in the excerpt (may be different than query), and `relevance_score` is the relevance of `summary` to answer the question (integer out of 10)",
41+
"Excerpt from {citation}\n\n----\n\n{text}\n\n----\n\nQuestion: {question}"
42+
]
4143
},
4244
"agent": {
4345
"agent_llm": "gpt-4-turbo-2024-04-09",

src/paperqa/core.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ async def _map_fxn_summary( # noqa: PLR0912
136136
text: Text,
137137
question: str,
138138
summary_llm_model: LLMModel | None,
139-
prompt_templates: tuple[str, str] | None,
139+
prompt_templates: tuple[str | list[str], str] | None,
140140
extra_prompt_data: dict[str, str] | None = None,
141141
parser: Callable[[str], dict[str, Any]] | None = None,
142142
callbacks: Sequence[Callable[[str], None]] | None = None,
@@ -154,8 +154,9 @@ async def _map_fxn_summary( # noqa: PLR0912
154154
text: The text to parse.
155155
question: The question to use for summarization.
156156
summary_llm_model: The LLM model to use for generating summaries.
157-
prompt_templates: Optional two-elements tuple containing templates for the user and system prompts.
158-
prompt_templates = (user_prompt_template, system_prompt_template)
157+
prompt_templates: Optional two-tuple containing
158+
the user prompt template(s) and a system prompt.
159+
prompt_templates = (user_prompt_template(s), system_prompt_template)
159160
extra_prompt_data: Optional extra data to pass to the prompt template.
160161
parser: Optional parser function to parse LLM output into structured data.
161162
Should return dict with at least 'summary' field.
@@ -202,13 +203,27 @@ async def _map_fxn_summary( # noqa: PLR0912
202203
else cleaned_text
203204
),
204205
} | (extra_prompt_data or {})
205-
message_prompt, system_prompt = (pt.format(**data) for pt in prompt_templates)
206+
user_msg_prompts: list[str] = (
207+
[prompt_templates[0].format(**data)]
208+
if isinstance(prompt_templates[0], str)
209+
else [pt.format(**data) for pt in prompt_templates[0]]
210+
)
211+
system_msg = Message(role="system", content=prompt_templates[1])
212+
prepend_msgs = (
213+
[
214+
system_msg,
215+
*(Message(content=m) for m in user_msg_prompts[:-1]),
216+
]
217+
if len(user_msg_prompts) > 1
218+
else [system_msg]
219+
)
220+
msg_with_media_prompt = user_msg_prompts[-1]
206221
try:
207222
llm_result = await summary_llm_model.call_single(
208223
messages=[
209-
Message(role="system", content=system_prompt),
224+
*prepend_msgs,
210225
Message.create_message(
211-
text=message_prompt,
226+
text=msg_with_media_prompt,
212227
images=(
213228
[i.to_image_url() for i in text.media]
214229
if text.media
@@ -231,8 +246,8 @@ async def _map_fxn_summary( # noqa: PLR0912
231246
)
232247
llm_result = await summary_llm_model.call_single(
233248
messages=[
234-
Message(role="system", content=system_prompt),
235-
Message(content=message_prompt),
249+
*prepend_msgs,
250+
Message(content=msg_with_media_prompt),
236251
*append_msgs,
237252
],
238253
callbacks=callbacks,

src/paperqa/docs.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -643,18 +643,14 @@ async def aget_evidence(
643643
else matches
644644
)
645645

646-
prompt_templates = None
647646
if not answer_config.evidence_skip_summary:
648-
if prompt_config.use_json:
649-
prompt_templates = (
650-
prompt_config.summary_json,
651-
prompt_config.summary_json_system,
652-
)
653-
else:
654-
prompt_templates = (
655-
prompt_config.summary,
656-
prompt_config.system,
657-
)
647+
prompt_templates: tuple[str | list[str], str] | None = (
648+
prompt_config.summary_json
649+
if prompt_config.use_json
650+
else prompt_config.summary
651+
), prompt_config.system
652+
else:
653+
prompt_templates = None
658654

659655
with set_llm_session_ids(session.id):
660656
results = await gather_with_concurrency(

src/paperqa/settings.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,13 @@ class PromptSettings(BaseModel):
371371
# SEE: https://nwtc.libguides.com/citations/MLA#s-lg-box-707489
372372
EXAMPLE_CITATION: ClassVar[str] = "(pqac-0f650d59)"
373373

374-
summary: str = summary_prompt
374+
summary: str | list[str] = Field(
375+
default=summary_prompt,
376+
description=(
377+
"User prompt template(s) to use when generating contextual summaries."
378+
" Must contain variables matching the default argument `summary_prompt`."
379+
),
380+
)
375381
qa: str = qa_prompt
376382
answer_iteration_prompt: str | None = Field(
377383
default=answer_iteration_prompt_template,
@@ -392,13 +398,25 @@ class PromptSettings(BaseModel):
392398
),
393399
)
394400
post: str | None = None
395-
system: str = default_system_prompt
401+
system: str = Field(
402+
default=default_system_prompt,
403+
description="System prompt to use when generating contextual summaries and answers.",
404+
)
396405
use_json: bool = True
397406
# Not thrilled about this model,
398407
# but need to split out the system/summary
399408
# to get JSON
400-
summary_json: str = include_text_prompt_template
401-
summary_json_system: str = summary_json_system_prompt
409+
summary_json: str | list[str] = Field(
410+
default_factory=lambda: [
411+
summary_json_system_prompt,
412+
include_text_prompt_template,
413+
],
414+
description=(
415+
"JSON-specific user prompt template(s) to use"
416+
" when generating contextual summaries."
417+
" Must contain variables matching the default argument `summary_prompt`."
418+
),
419+
)
402420
context_outer: str = Field(
403421
default=CONTEXT_OUTER_PROMPT,
404422
description="Prompt for how to format all contexts in generate answer.",

tests/test_paperqa.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,8 @@ async def acompletion_that_breaks_first_context(*args, **kwargs):
528528
async def test_json_evidence(docs_fixture: Docs) -> None:
529529
settings = Settings.from_name("fast")
530530
settings.prompts.use_json = True
531-
settings.prompts.summary_json_system = (
531+
assert isinstance(settings.prompts.summary_json, list)
532+
settings.prompts.summary_json[0] = (
532533
"Provide a summary of the excerpt that could help answer the question based on"
533534
" the excerpt. The excerpt may be irrelevant. Do not directly answer the"
534535
" question - only summarize relevant information. Respond with the following"

0 commit comments

Comments
 (0)