Compare commits
2 commits
main
...
danielchal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9aee5c5e1f | ||
|
|
c83de3c451 |
6 changed files with 106 additions and 73 deletions
|
|
@ -20,47 +20,44 @@ from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from .models import Message, PromptFunction, PromptVersion
|
from .models import Message, PromptFunction, PromptVersion
|
||||||
from .prompt_helpers import to_prompt_json
|
from .prompt_helpers import to_prompt_json
|
||||||
|
from .snippets import summary_instructions
|
||||||
|
|
||||||
|
|
||||||
class ExtractedEntity(BaseModel):
|
class ExtractedEntity(BaseModel):
|
||||||
name: str = Field(..., description="Name of the extracted entity")
|
name: str = Field(..., description='Name of the extracted entity')
|
||||||
entity_type_id: int = Field(
|
entity_type_id: int = Field(
|
||||||
description="ID of the classified entity type. "
|
description='ID of the classified entity type. '
|
||||||
"Must be one of the provided entity_type_id integers.",
|
'Must be one of the provided entity_type_id integers.',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExtractedEntities(BaseModel):
|
class ExtractedEntities(BaseModel):
|
||||||
extracted_entities: list[ExtractedEntity] = Field(
|
extracted_entities: list[ExtractedEntity] = Field(..., description='List of extracted entities')
|
||||||
..., description="List of extracted entities"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class MissedEntities(BaseModel):
|
class MissedEntities(BaseModel):
|
||||||
missed_entities: list[str] = Field(
|
missed_entities: list[str] = Field(..., description="Names of entities that weren't extracted")
|
||||||
..., description="Names of entities that weren't extracted"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class EntityClassificationTriple(BaseModel):
|
class EntityClassificationTriple(BaseModel):
|
||||||
uuid: str = Field(description="UUID of the entity")
|
uuid: str = Field(description='UUID of the entity')
|
||||||
name: str = Field(description="Name of the entity")
|
name: str = Field(description='Name of the entity')
|
||||||
entity_type: str | None = Field(
|
entity_type: str | None = Field(
|
||||||
default=None,
|
default=None,
|
||||||
description="Type of the entity. Must be one of the provided types or None",
|
description='Type of the entity. Must be one of the provided types or None',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class EntityClassification(BaseModel):
|
class EntityClassification(BaseModel):
|
||||||
entity_classifications: list[EntityClassificationTriple] = Field(
|
entity_classifications: list[EntityClassificationTriple] = Field(
|
||||||
..., description="List of entities classification triples."
|
..., description='List of entities classification triples.'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class EntitySummary(BaseModel):
|
class EntitySummary(BaseModel):
|
||||||
summary: str = Field(
|
summary: str = Field(
|
||||||
...,
|
...,
|
||||||
description="Summary containing the important information about the entity. Under 8 sentences.",
|
description='Summary containing the important information about the entity. Under 250 characters.',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -128,8 +125,8 @@ reference entities. Only extract distinct entities from the CURRENT MESSAGE. Don
|
||||||
{context['custom_prompt']}
|
{context['custom_prompt']}
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
Message(role="system", content=sys_prompt),
|
Message(role='system', content=sys_prompt),
|
||||||
Message(role="user", content=user_prompt),
|
Message(role='user', content=user_prompt),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -161,8 +158,8 @@ Guidelines:
|
||||||
3. Do NOT extract any properties that contain dates
|
3. Do NOT extract any properties that contain dates
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
Message(role="system", content=sys_prompt),
|
Message(role='system', content=sys_prompt),
|
||||||
Message(role="user", content=user_prompt),
|
Message(role='user', content=user_prompt),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -192,8 +189,8 @@ Guidelines:
|
||||||
4. Be as explicit as possible in your node names, using full names and avoiding abbreviations.
|
4. Be as explicit as possible in your node names, using full names and avoiding abbreviations.
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
Message(role="system", content=sys_prompt),
|
Message(role='system', content=sys_prompt),
|
||||||
Message(role="user", content=user_prompt),
|
Message(role='user', content=user_prompt),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -216,8 +213,8 @@ Given the above previous messages, current message, and list of extracted entiti
|
||||||
extracted.
|
extracted.
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
Message(role="system", content=sys_prompt),
|
Message(role='system', content=sys_prompt),
|
||||||
Message(role="user", content=user_prompt),
|
Message(role='user', content=user_prompt),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -248,19 +245,19 @@ def classify_nodes(context: dict[str, Any]) -> list[Message]:
|
||||||
3. If none of the provided entity types accurately classify an extracted node, the type should be set to None
|
3. If none of the provided entity types accurately classify an extracted node, the type should be set to None
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
Message(role="system", content=sys_prompt),
|
Message(role='system', content=sys_prompt),
|
||||||
Message(role="user", content=user_prompt),
|
Message(role='user', content=user_prompt),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def extract_attributes(context: dict[str, Any]) -> list[Message]:
|
def extract_attributes(context: dict[str, Any]) -> list[Message]:
|
||||||
return [
|
return [
|
||||||
Message(
|
Message(
|
||||||
role="system",
|
role='system',
|
||||||
content="You are a helpful assistant that extracts entity properties from the provided text.",
|
content='You are a helpful assistant that extracts entity properties from the provided text.',
|
||||||
),
|
),
|
||||||
Message(
|
Message(
|
||||||
role="user",
|
role='user',
|
||||||
content=f"""
|
content=f"""
|
||||||
|
|
||||||
<MESSAGES>
|
<MESSAGES>
|
||||||
|
|
@ -286,11 +283,11 @@ def extract_attributes(context: dict[str, Any]) -> list[Message]:
|
||||||
def extract_summary(context: dict[str, Any]) -> list[Message]:
|
def extract_summary(context: dict[str, Any]) -> list[Message]:
|
||||||
return [
|
return [
|
||||||
Message(
|
Message(
|
||||||
role="system",
|
role='system',
|
||||||
content="You are a helpful assistant that extracts entity summaries from the provided text.",
|
content='You are a helpful assistant that extracts entity summaries from the provided text.',
|
||||||
),
|
),
|
||||||
Message(
|
Message(
|
||||||
role="user",
|
role='user',
|
||||||
content=f"""
|
content=f"""
|
||||||
|
|
||||||
<MESSAGES>
|
<MESSAGES>
|
||||||
|
|
@ -301,11 +298,7 @@ def extract_summary(context: dict[str, Any]) -> list[Message]:
|
||||||
Given the above MESSAGES and the following ENTITY, update the summary that combines relevant information about the entity
|
Given the above MESSAGES and the following ENTITY, update the summary that combines relevant information about the entity
|
||||||
from the messages and relevant information from the existing summary.
|
from the messages and relevant information from the existing summary.
|
||||||
|
|
||||||
Guidelines:
|
{summary_instructions}
|
||||||
1. Do not hallucinate entity summary information if they cannot be found in the current context.
|
|
||||||
2. Only use the provided MESSAGES and ENTITY to set attribute values.
|
|
||||||
3. The summary attribute represents a summary of the ENTITY, and should be updated with new information about the Entity from the MESSAGES.
|
|
||||||
4. Keep the summary concise and to the point. SUMMARIES MUST BE LESS THAN 8 SENTENCES.
|
|
||||||
|
|
||||||
<ENTITY>
|
<ENTITY>
|
||||||
{context['node']}
|
{context['node']}
|
||||||
|
|
@ -316,11 +309,11 @@ def extract_summary(context: dict[str, Any]) -> list[Message]:
|
||||||
|
|
||||||
|
|
||||||
versions: Versions = {
|
versions: Versions = {
|
||||||
"extract_message": extract_message,
|
'extract_message': extract_message,
|
||||||
"extract_json": extract_json,
|
'extract_json': extract_json,
|
||||||
"extract_text": extract_text,
|
'extract_text': extract_text,
|
||||||
"reflexion": reflexion,
|
'reflexion': reflexion,
|
||||||
"extract_summary": extract_summary,
|
'extract_summary': extract_summary,
|
||||||
"classify_nodes": classify_nodes,
|
'classify_nodes': classify_nodes,
|
||||||
"extract_attributes": extract_attributes,
|
'extract_attributes': extract_attributes,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
|
||||||
29
graphiti_core/prompts/snippets.py
Normal file
29
graphiti_core/prompts/snippets.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
summary_instructions = """Guidelines:
|
||||||
|
1. Output only factual content. Never explain what you're doing, why, or mention limitations/constraints.
|
||||||
|
2. Only use the provided messages, entity, and entity context to set attribute values.
|
||||||
|
3. Keep the summary concise and to the point. STATE FACTS DIRECTLY IN UNDER 250 CHARACTERS.
|
||||||
|
|
||||||
|
Example summaries:
|
||||||
|
BAD: "This is the only activity in the context. The user listened to this song. No other details were provided to include in this summary."
|
||||||
|
GOOD: "User played 'Blue Monday' by New Order (electronic genre) on 2024-12-03 at 14:22 UTC."
|
||||||
|
BAD: "Based on the messages provided, the user attended a meeting. This summary focuses on that event as it was the main topic discussed."
|
||||||
|
GOOD: "User attended Q3 planning meeting with sales team on March 15."
|
||||||
|
BAD: "The context shows John ordered pizza. Due to length constraints, other details are omitted from this summary."
|
||||||
|
GOOD: "John ordered pepperoni pizza from Mario's at 7:30 PM, delivered to office."
|
||||||
|
"""
|
||||||
|
|
@ -20,19 +20,18 @@ from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from .models import Message, PromptFunction, PromptVersion
|
from .models import Message, PromptFunction, PromptVersion
|
||||||
from .prompt_helpers import to_prompt_json
|
from .prompt_helpers import to_prompt_json
|
||||||
|
from .snippets import summary_instructions
|
||||||
|
|
||||||
|
|
||||||
class Summary(BaseModel):
|
class Summary(BaseModel):
|
||||||
summary: str = Field(
|
summary: str = Field(
|
||||||
...,
|
...,
|
||||||
description="Summary containing the important information about the entity. Under 8 sentences",
|
description='Summary containing the important information about the entity. Under 250 characters',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SummaryDescription(BaseModel):
|
class SummaryDescription(BaseModel):
|
||||||
description: str = Field(
|
description: str = Field(..., description='One sentence description of the provided summary')
|
||||||
..., description="One sentence description of the provided summary"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Prompt(Protocol):
|
class Prompt(Protocol):
|
||||||
|
|
@ -50,15 +49,15 @@ class Versions(TypedDict):
|
||||||
def summarize_pair(context: dict[str, Any]) -> list[Message]:
|
def summarize_pair(context: dict[str, Any]) -> list[Message]:
|
||||||
return [
|
return [
|
||||||
Message(
|
Message(
|
||||||
role="system",
|
role='system',
|
||||||
content="You are a helpful assistant that combines summaries.",
|
content='You are a helpful assistant that combines summaries.',
|
||||||
),
|
),
|
||||||
Message(
|
Message(
|
||||||
role="user",
|
role='user',
|
||||||
content=f"""
|
content=f"""
|
||||||
Synthesize the information from the following two summaries into a single succinct summary.
|
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 8 SENTENCES.
|
IMPORTANT: Keep the summary concise and to the point. SUMMARIES MUST BE LESS THAN 250 CHARACTERS.
|
||||||
|
|
||||||
Summaries:
|
Summaries:
|
||||||
{to_prompt_json(context['node_summaries'], indent=2)}
|
{to_prompt_json(context['node_summaries'], indent=2)}
|
||||||
|
|
@ -70,29 +69,25 @@ def summarize_pair(context: dict[str, Any]) -> list[Message]:
|
||||||
def summarize_context(context: dict[str, Any]) -> list[Message]:
|
def summarize_context(context: dict[str, Any]) -> list[Message]:
|
||||||
return [
|
return [
|
||||||
Message(
|
Message(
|
||||||
role="system",
|
role='system',
|
||||||
content="You are a helpful assistant that generates a summary and attributes from provided text.",
|
content='You are a helpful assistant that generates a summary and attributes from provided text.',
|
||||||
),
|
),
|
||||||
Message(
|
Message(
|
||||||
role="user",
|
role='user',
|
||||||
content=f"""
|
content=f"""
|
||||||
|
Given the MESSAGES and the ENTITY name, create a summary for the ENTITY. Your summary must only use
|
||||||
<MESSAGES>
|
|
||||||
{to_prompt_json(context['previous_episodes'], indent=2)}
|
|
||||||
{to_prompt_json(context['episode_content'], indent=2)}
|
|
||||||
</MESSAGES>
|
|
||||||
|
|
||||||
Given the above MESSAGES and the following 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
|
information from the provided MESSAGES. Your summary should also only contain information relevant to the
|
||||||
provided ENTITY.
|
provided ENTITY.
|
||||||
|
|
||||||
In addition, extract any values for the provided entity properties based on their descriptions.
|
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.
|
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.
|
||||||
|
|
||||||
Guidelines:
|
{summary_instructions}
|
||||||
1. Do not hallucinate entity property values if they cannot be found in the current context.
|
|
||||||
2. Only use the provided messages, entity, and entity context to set attribute values.
|
<MESSAGES>
|
||||||
3. Keep the summary concise and to the point. SUMMARIES MUST BE LESS THAN 8 SENTENCES.
|
{to_prompt_json(context['previous_episodes'], indent=2)}
|
||||||
|
{to_prompt_json(context['episode_content'], indent=2)}
|
||||||
|
</MESSAGES>
|
||||||
|
|
||||||
<ENTITY>
|
<ENTITY>
|
||||||
{context['node_name']}
|
{context['node_name']}
|
||||||
|
|
@ -113,14 +108,14 @@ def summarize_context(context: dict[str, Any]) -> list[Message]:
|
||||||
def summary_description(context: dict[str, Any]) -> list[Message]:
|
def summary_description(context: dict[str, Any]) -> list[Message]:
|
||||||
return [
|
return [
|
||||||
Message(
|
Message(
|
||||||
role="system",
|
role='system',
|
||||||
content="You are a helpful assistant that describes provided contents in a single sentence.",
|
content='You are a helpful assistant that describes provided contents in a single sentence.',
|
||||||
),
|
),
|
||||||
Message(
|
Message(
|
||||||
role="user",
|
role='user',
|
||||||
content=f"""
|
content=f"""
|
||||||
Create a short one sentence description of the summary that explains what kind of information is summarized.
|
Create a short one sentence description of the summary that explains what kind of information is summarized.
|
||||||
Summaries must be under 8 sentences.
|
Summaries must be under 250 characters.
|
||||||
|
|
||||||
Summary:
|
Summary:
|
||||||
{to_prompt_json(context['summary'], indent=2)}
|
{to_prompt_json(context['summary'], indent=2)}
|
||||||
|
|
@ -130,7 +125,7 @@ def summary_description(context: dict[str, Any]) -> list[Message]:
|
||||||
|
|
||||||
|
|
||||||
versions: Versions = {
|
versions: Versions = {
|
||||||
"summarize_pair": summarize_pair,
|
'summarize_pair': summarize_pair,
|
||||||
"summarize_context": summarize_context,
|
'summarize_context': summarize_context,
|
||||||
"summary_description": summary_description,
|
'summary_description': summary_description,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[project]
|
[project]
|
||||||
name = "graphiti-core"
|
name = "graphiti-core"
|
||||||
description = "A temporal graph building library"
|
description = "A temporal graph building library"
|
||||||
version = "0.22.0pre1"
|
version = "0.22.0pre2"
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "Paul Paliychuk", email = "paul@getzep.com" },
|
{ name = "Paul Paliychuk", email = "paul@getzep.com" },
|
||||||
{ name = "Preston Rasmussen", email = "preston@getzep.com" },
|
{ name = "Preston Rasmussen", email = "preston@getzep.com" },
|
||||||
|
|
|
||||||
2
uv.lock
generated
2
uv.lock
generated
|
|
@ -783,7 +783,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "graphiti-core"
|
name = "graphiti-core"
|
||||||
version = "0.22.0rc0"
|
version = "0.22.0rc2"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "diskcache" },
|
{ name = "diskcache" },
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue