graphiti/graphiti_core/prompts/summarize_nodes.py
Daniel Chalef 896cb4e990
Refactor summary prompts to use character limit and prevent meta-commentary (#979)
* Refactor summary prompts to use character limit and prevent meta-commentary

- Changed summary length constraint from "8 sentences" to "250 characters" for more predictable output
- Created reusable summary_instructions snippet in snippets.py with clear BAD/GOOD examples
- Added explicit instruction to output only factual content without meta-commentary
- Applied consistent formatting across extract_nodes.py and summarize_nodes.py
- Bumped version to 0.22.0pre2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add copyright header to snippets.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-04 15:44:00 -07:00

131 lines
4 KiB
Python

"""
Copyright 2024, Zep Software, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from typing import Any, Protocol, TypedDict
from pydantic import BaseModel, Field
from .models import Message, PromptFunction, PromptVersion
from .prompt_helpers import to_prompt_json
from .snippets import summary_instructions
class Summary(BaseModel):
summary: str = Field(
...,
description='Summary containing the important information about the entity. Under 250 characters',
)
class SummaryDescription(BaseModel):
description: str = Field(..., description='One sentence description of the provided summary')
class Prompt(Protocol):
summarize_pair: PromptVersion
summarize_context: PromptVersion
summary_description: PromptVersion
class Versions(TypedDict):
summarize_pair: PromptFunction
summarize_context: PromptFunction
summary_description: PromptFunction
def summarize_pair(context: dict[str, Any]) -> list[Message]:
return [
Message(
role='system',
content='You are a helpful assistant that combines summaries.',
),
Message(
role='user',
content=f"""
Synthesize the information from the following two summaries into a single succinct summary.
IMPORTANT: Keep the summary concise and to the point. SUMMARIES MUST BE LESS THAN 250 CHARACTERS.
Summaries:
{to_prompt_json(context['node_summaries'], indent=2)}
""",
),
]
def summarize_context(context: dict[str, Any]) -> list[Message]:
return [
Message(
role='system',
content='You are a helpful assistant that generates a summary and attributes from provided text.',
),
Message(
role='user',
content=f"""
Given the MESSAGES and the ENTITY name, create a summary for the ENTITY. Your summary must only use
information from the provided MESSAGES. Your summary should also only contain information relevant to the
provided ENTITY.
In addition, extract any values for the provided entity properties based on their descriptions.
If the value of the entity property cannot be found in the current context, set the value of the property to the Python value None.
{summary_instructions}
<MESSAGES>
{to_prompt_json(context['previous_episodes'], indent=2)}
{to_prompt_json(context['episode_content'], indent=2)}
</MESSAGES>
<ENTITY>
{context['node_name']}
</ENTITY>
<ENTITY CONTEXT>
{context['node_summary']}
</ENTITY CONTEXT>
<ATTRIBUTES>
{to_prompt_json(context['attributes'], indent=2)}
</ATTRIBUTES>
""",
),
]
def summary_description(context: dict[str, Any]) -> list[Message]:
return [
Message(
role='system',
content='You are a helpful assistant that describes provided contents in a single sentence.',
),
Message(
role='user',
content=f"""
Create a short one sentence description of the summary that explains what kind of information is summarized.
Summaries must be under 250 characters.
Summary:
{to_prompt_json(context['summary'], indent=2)}
""",
),
]
versions: Versions = {
'summarize_pair': summarize_pair,
'summarize_context': summarize_context,
'summary_description': summary_description,
}