fast-agent-mcp 0.1.12__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/METADATA +3 -4
- fast_agent_mcp-0.2.0.dist-info/RECORD +123 -0
- mcp_agent/__init__.py +75 -0
- mcp_agent/agents/agent.py +61 -415
- mcp_agent/agents/base_agent.py +522 -0
- mcp_agent/agents/workflow/__init__.py +1 -0
- mcp_agent/agents/workflow/chain_agent.py +173 -0
- mcp_agent/agents/workflow/evaluator_optimizer.py +362 -0
- mcp_agent/agents/workflow/orchestrator_agent.py +591 -0
- mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_models.py +11 -21
- mcp_agent/agents/workflow/parallel_agent.py +182 -0
- mcp_agent/agents/workflow/router_agent.py +307 -0
- mcp_agent/app.py +15 -19
- mcp_agent/cli/commands/bootstrap.py +19 -38
- mcp_agent/cli/commands/config.py +4 -4
- mcp_agent/cli/commands/setup.py +7 -14
- mcp_agent/cli/main.py +7 -10
- mcp_agent/cli/terminal.py +3 -3
- mcp_agent/config.py +25 -40
- mcp_agent/context.py +12 -21
- mcp_agent/context_dependent.py +3 -5
- mcp_agent/core/agent_types.py +10 -7
- mcp_agent/core/direct_agent_app.py +179 -0
- mcp_agent/core/direct_decorators.py +443 -0
- mcp_agent/core/direct_factory.py +476 -0
- mcp_agent/core/enhanced_prompt.py +23 -55
- mcp_agent/core/exceptions.py +8 -8
- mcp_agent/core/fastagent.py +145 -371
- mcp_agent/core/interactive_prompt.py +424 -0
- mcp_agent/core/mcp_content.py +17 -17
- mcp_agent/core/prompt.py +6 -9
- mcp_agent/core/request_params.py +6 -3
- mcp_agent/core/validation.py +92 -18
- mcp_agent/executor/decorator_registry.py +9 -17
- mcp_agent/executor/executor.py +8 -17
- mcp_agent/executor/task_registry.py +2 -4
- mcp_agent/executor/temporal.py +19 -41
- mcp_agent/executor/workflow.py +3 -5
- mcp_agent/executor/workflow_signal.py +15 -21
- mcp_agent/human_input/handler.py +4 -7
- mcp_agent/human_input/types.py +2 -3
- mcp_agent/llm/__init__.py +2 -0
- mcp_agent/llm/augmented_llm.py +450 -0
- mcp_agent/llm/augmented_llm_passthrough.py +162 -0
- mcp_agent/llm/augmented_llm_playback.py +83 -0
- mcp_agent/llm/memory.py +103 -0
- mcp_agent/{workflows/llm → llm}/model_factory.py +22 -16
- mcp_agent/{workflows/llm → llm}/prompt_utils.py +1 -3
- mcp_agent/llm/providers/__init__.py +8 -0
- mcp_agent/{workflows/llm → llm/providers}/anthropic_utils.py +8 -25
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_anthropic.py +56 -194
- mcp_agent/llm/providers/augmented_llm_deepseek.py +53 -0
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_openai.py +99 -190
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_anthropic.py +72 -71
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_openai.py +65 -71
- mcp_agent/{workflows/llm → llm}/providers/openai_multipart.py +16 -44
- mcp_agent/{workflows/llm → llm/providers}/openai_utils.py +4 -4
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_anthropic.py +9 -11
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_openai.py +8 -12
- mcp_agent/{workflows/llm → llm}/sampling_converter.py +3 -31
- mcp_agent/llm/sampling_format_converter.py +37 -0
- mcp_agent/logging/events.py +1 -5
- mcp_agent/logging/json_serializer.py +7 -6
- mcp_agent/logging/listeners.py +20 -23
- mcp_agent/logging/logger.py +17 -19
- mcp_agent/logging/rich_progress.py +10 -8
- mcp_agent/logging/tracing.py +4 -6
- mcp_agent/logging/transport.py +22 -22
- mcp_agent/mcp/gen_client.py +1 -3
- mcp_agent/mcp/interfaces.py +117 -110
- mcp_agent/mcp/logger_textio.py +97 -0
- mcp_agent/mcp/mcp_agent_client_session.py +7 -7
- mcp_agent/mcp/mcp_agent_server.py +8 -8
- mcp_agent/mcp/mcp_aggregator.py +102 -143
- mcp_agent/mcp/mcp_connection_manager.py +20 -27
- mcp_agent/mcp/prompt_message_multipart.py +68 -16
- mcp_agent/mcp/prompt_render.py +77 -0
- mcp_agent/mcp/prompt_serialization.py +30 -48
- mcp_agent/mcp/prompts/prompt_constants.py +18 -0
- mcp_agent/mcp/prompts/prompt_helpers.py +327 -0
- mcp_agent/mcp/prompts/prompt_load.py +109 -0
- mcp_agent/mcp/prompts/prompt_server.py +155 -195
- mcp_agent/mcp/prompts/prompt_template.py +35 -66
- mcp_agent/mcp/resource_utils.py +7 -14
- mcp_agent/mcp/sampling.py +17 -17
- mcp_agent/mcp_server/agent_server.py +13 -17
- mcp_agent/mcp_server_registry.py +13 -22
- mcp_agent/resources/examples/{workflows → in_dev}/agent_build.py +3 -2
- mcp_agent/resources/examples/in_dev/slides.py +110 -0
- mcp_agent/resources/examples/internal/agent.py +6 -3
- mcp_agent/resources/examples/internal/fastagent.config.yaml +8 -2
- mcp_agent/resources/examples/internal/job.py +2 -1
- mcp_agent/resources/examples/internal/prompt_category.py +1 -1
- mcp_agent/resources/examples/internal/prompt_sizing.py +3 -5
- mcp_agent/resources/examples/internal/sizer.py +2 -1
- mcp_agent/resources/examples/internal/social.py +2 -1
- mcp_agent/resources/examples/prompting/agent.py +2 -1
- mcp_agent/resources/examples/prompting/image_server.py +4 -8
- mcp_agent/resources/examples/prompting/work_with_image.py +19 -0
- mcp_agent/ui/console_display.py +16 -20
- fast_agent_mcp-0.1.12.dist-info/RECORD +0 -161
- mcp_agent/core/agent_app.py +0 -646
- mcp_agent/core/agent_utils.py +0 -71
- mcp_agent/core/decorators.py +0 -455
- mcp_agent/core/factory.py +0 -463
- mcp_agent/core/proxies.py +0 -269
- mcp_agent/core/types.py +0 -24
- mcp_agent/eval/__init__.py +0 -0
- mcp_agent/mcp/stdio.py +0 -111
- mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -188
- mcp_agent/resources/examples/data-analysis/analysis.py +0 -65
- mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -41
- mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -1471
- mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -66
- mcp_agent/resources/examples/researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/researcher-imp.py +0 -190
- mcp_agent/resources/examples/researcher/researcher.py +0 -38
- mcp_agent/resources/examples/workflows/chaining.py +0 -44
- mcp_agent/resources/examples/workflows/evaluator.py +0 -78
- mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -24
- mcp_agent/resources/examples/workflows/human_input.py +0 -25
- mcp_agent/resources/examples/workflows/orchestrator.py +0 -73
- mcp_agent/resources/examples/workflows/parallel.py +0 -78
- mcp_agent/resources/examples/workflows/router.py +0 -53
- mcp_agent/resources/examples/workflows/sse.py +0 -23
- mcp_agent/telemetry/__init__.py +0 -0
- mcp_agent/telemetry/usage_tracking.py +0 -18
- mcp_agent/workflows/__init__.py +0 -0
- mcp_agent/workflows/embedding/__init__.py +0 -0
- mcp_agent/workflows/embedding/embedding_base.py +0 -61
- mcp_agent/workflows/embedding/embedding_cohere.py +0 -49
- mcp_agent/workflows/embedding/embedding_openai.py +0 -46
- mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +0 -481
- mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -120
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -134
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -45
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -45
- mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -161
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -60
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -60
- mcp_agent/workflows/llm/__init__.py +0 -0
- mcp_agent/workflows/llm/augmented_llm.py +0 -753
- mcp_agent/workflows/llm/augmented_llm_passthrough.py +0 -241
- mcp_agent/workflows/llm/augmented_llm_playback.py +0 -109
- mcp_agent/workflows/llm/providers/__init__.py +0 -8
- mcp_agent/workflows/llm/sampling_format_converter.py +0 -22
- mcp_agent/workflows/orchestrator/__init__.py +0 -0
- mcp_agent/workflows/orchestrator/orchestrator.py +0 -578
- mcp_agent/workflows/parallel/__init__.py +0 -0
- mcp_agent/workflows/parallel/fan_in.py +0 -350
- mcp_agent/workflows/parallel/fan_out.py +0 -187
- mcp_agent/workflows/parallel/parallel_llm.py +0 -166
- mcp_agent/workflows/router/__init__.py +0 -0
- mcp_agent/workflows/router/router_base.py +0 -368
- mcp_agent/workflows/router/router_embedding.py +0 -240
- mcp_agent/workflows/router/router_embedding_cohere.py +0 -59
- mcp_agent/workflows/router/router_embedding_openai.py +0 -59
- mcp_agent/workflows/router/router_llm.py +0 -320
- mcp_agent/workflows/swarm/__init__.py +0 -0
- mcp_agent/workflows/swarm/swarm.py +0 -320
- mcp_agent/workflows/swarm/swarm_anthropic.py +0 -42
- mcp_agent/workflows/swarm/swarm_openai.py +0 -41
- {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
- /mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_prompts.py +0 -0
@@ -1,14 +1,35 @@
|
|
1
1
|
from typing import List, Union
|
2
|
-
from pydantic import BaseModel
|
3
2
|
|
4
3
|
from mcp.types import (
|
5
|
-
PromptMessage,
|
6
|
-
TextContent,
|
7
|
-
ImageContent,
|
8
4
|
EmbeddedResource,
|
9
|
-
Role,
|
10
5
|
GetPromptResult,
|
6
|
+
ImageContent,
|
7
|
+
PromptMessage,
|
8
|
+
Role,
|
9
|
+
TextContent,
|
10
|
+
TextResourceContents,
|
11
11
|
)
|
12
|
+
from pydantic import BaseModel
|
13
|
+
|
14
|
+
|
15
|
+
def get_text(content: Union[TextContent, ImageContent, EmbeddedResource]) -> str | None:
|
16
|
+
"""
|
17
|
+
Extract text content from a content object if available.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
content: A content object (TextContent, ImageContent, or EmbeddedResource)
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
The text content as a string or None if not a text content
|
24
|
+
"""
|
25
|
+
if isinstance(content, TextContent):
|
26
|
+
return content.text
|
27
|
+
|
28
|
+
if isinstance(content, EmbeddedResource):
|
29
|
+
if isinstance(content.resource, TextResourceContents):
|
30
|
+
return content.resource.text
|
31
|
+
|
32
|
+
return None
|
12
33
|
|
13
34
|
|
14
35
|
class PromptMessageMultipart(BaseModel):
|
@@ -21,9 +42,7 @@ class PromptMessageMultipart(BaseModel):
|
|
21
42
|
content: List[Union[TextContent, ImageContent, EmbeddedResource]]
|
22
43
|
|
23
44
|
@classmethod
|
24
|
-
def
|
25
|
-
cls, messages: List[PromptMessage]
|
26
|
-
) -> List["PromptMessageMultipart"]:
|
45
|
+
def to_multipart(cls, messages: List[PromptMessage]) -> List["PromptMessageMultipart"]:
|
27
46
|
"""Convert a sequence of PromptMessages into PromptMessageMultipart objects."""
|
28
47
|
if not messages:
|
29
48
|
return []
|
@@ -41,7 +60,8 @@ class PromptMessageMultipart(BaseModel):
|
|
41
60
|
current_group = cls(role=msg.role, content=[msg.content])
|
42
61
|
else:
|
43
62
|
# Same role, add to current message
|
44
|
-
current_group
|
63
|
+
if current_group is not None:
|
64
|
+
current_group.content.append(msg.content)
|
45
65
|
|
46
66
|
# Add the last group
|
47
67
|
if current_group is not None:
|
@@ -49,16 +69,48 @@ class PromptMessageMultipart(BaseModel):
|
|
49
69
|
|
50
70
|
return result
|
51
71
|
|
52
|
-
def
|
72
|
+
def from_multipart(self) -> List[PromptMessage]:
|
53
73
|
"""Convert this PromptMessageMultipart to a sequence of standard PromptMessages."""
|
54
74
|
return [
|
55
|
-
PromptMessage(role=self.role, content=content_part)
|
56
|
-
for content_part in self.content
|
75
|
+
PromptMessage(role=self.role, content=content_part) for content_part in self.content
|
57
76
|
]
|
58
77
|
|
78
|
+
def first_text(self) -> str:
|
79
|
+
"""
|
80
|
+
Get the first available text content from a message.
|
81
|
+
|
82
|
+
Args:
|
83
|
+
message: A PromptMessage or PromptMessageMultipart
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
First text content or None if no text content exists
|
87
|
+
"""
|
88
|
+
for content in self.content:
|
89
|
+
text = get_text(content)
|
90
|
+
if text is not None:
|
91
|
+
return text
|
92
|
+
|
93
|
+
return "<no text>"
|
94
|
+
|
95
|
+
def all_text(self) -> str:
|
96
|
+
"""
|
97
|
+
Get all the text available.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
message: A PromptMessage or PromptMessageMultipart
|
101
|
+
|
102
|
+
Returns:
|
103
|
+
First text content or None if no text content exists
|
104
|
+
"""
|
105
|
+
result = []
|
106
|
+
for content in self.content:
|
107
|
+
text = get_text(content)
|
108
|
+
if text is not None:
|
109
|
+
result.append(text)
|
110
|
+
|
111
|
+
return "\n".join(result)
|
112
|
+
|
59
113
|
@classmethod
|
60
|
-
def parse_get_prompt_result(
|
61
|
-
cls, result: GetPromptResult
|
62
|
-
) -> List["PromptMessageMultipart"]:
|
114
|
+
def parse_get_prompt_result(cls, result: GetPromptResult) -> List["PromptMessageMultipart"]:
|
63
115
|
"""Parse a GetPromptResult into PromptMessageMultipart objects."""
|
64
|
-
return cls.
|
116
|
+
return cls.to_multipart(result.messages)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
"""
|
2
|
+
Utilities for rendering PromptMessageMultipart objects for display.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List
|
6
|
+
|
7
|
+
from mcp.types import BlobResourceContents, TextResourceContents
|
8
|
+
|
9
|
+
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
10
|
+
from mcp_agent.mcp.prompts.prompt_helpers import (
|
11
|
+
get_resource_uri,
|
12
|
+
get_text,
|
13
|
+
is_image_content,
|
14
|
+
is_resource_content,
|
15
|
+
is_text_content,
|
16
|
+
)
|
17
|
+
|
18
|
+
|
19
|
+
def render_multipart_message(message: PromptMessageMultipart) -> str:
|
20
|
+
"""
|
21
|
+
Render a multipart message for display purposes.
|
22
|
+
|
23
|
+
This function formats the message content for user-friendly display,
|
24
|
+
handling different content types appropriately.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
message: A PromptMessageMultipart object to render
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
A string representation of the message's content
|
31
|
+
"""
|
32
|
+
rendered_parts: List[str] = []
|
33
|
+
|
34
|
+
for content in message.content:
|
35
|
+
if is_text_content(content):
|
36
|
+
# Handle text content
|
37
|
+
text_content = content # type: TextContent
|
38
|
+
rendered_parts.append(text_content.text)
|
39
|
+
|
40
|
+
elif is_image_content(content):
|
41
|
+
# Format details about the image
|
42
|
+
image_content = content # type: ImageContent
|
43
|
+
data_size = len(image_content.data) if image_content.data else 0
|
44
|
+
image_info = f"[IMAGE: {image_content.mimeType}, {data_size} bytes]"
|
45
|
+
rendered_parts.append(image_info)
|
46
|
+
|
47
|
+
elif is_resource_content(content):
|
48
|
+
# Handle embedded resources
|
49
|
+
resource = content # type: EmbeddedResource
|
50
|
+
uri = get_resource_uri(resource)
|
51
|
+
|
52
|
+
if isinstance(resource.resource, TextResourceContents):
|
53
|
+
# Handle text resources
|
54
|
+
text = resource.resource.text
|
55
|
+
text_length = len(text)
|
56
|
+
mime_type = resource.resource.mimeType
|
57
|
+
|
58
|
+
# Preview with truncation for long content
|
59
|
+
preview = text[:300] + ("..." if text_length > 300 else "")
|
60
|
+
resource_info = f"[EMBEDDED TEXT RESOURCE: {mime_type}, {uri}, {text_length} chars]\n{preview}"
|
61
|
+
rendered_parts.append(resource_info)
|
62
|
+
|
63
|
+
elif isinstance(resource.resource, BlobResourceContents):
|
64
|
+
# Handle blob resources (binary data)
|
65
|
+
blob_length = len(resource.resource.blob) if resource.resource.blob else 0
|
66
|
+
mime_type = resource.resource.mimeType
|
67
|
+
|
68
|
+
resource_info = f"[EMBEDDED BLOB RESOURCE: {mime_type}, {uri}, {blob_length} bytes]"
|
69
|
+
rendered_parts.append(resource_info)
|
70
|
+
|
71
|
+
else:
|
72
|
+
# Fallback for other content types
|
73
|
+
text = get_text(content)
|
74
|
+
if text is not None:
|
75
|
+
rendered_parts.append(text)
|
76
|
+
|
77
|
+
return "\n".join(rendered_parts)
|
@@ -19,9 +19,14 @@ and PromptMessageMultipart objects. It includes functionality for:
|
|
19
19
|
import json
|
20
20
|
from typing import List
|
21
21
|
|
22
|
-
from mcp.types import
|
23
|
-
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
22
|
+
from mcp.types import EmbeddedResource, ImageContent, TextContent, TextResourceContents
|
24
23
|
|
24
|
+
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
25
|
+
from mcp_agent.mcp.prompts.prompt_constants import (
|
26
|
+
ASSISTANT_DELIMITER,
|
27
|
+
RESOURCE_DELIMITER,
|
28
|
+
USER_DELIMITER,
|
29
|
+
)
|
25
30
|
|
26
31
|
# -------------------------------------------------------------------------
|
27
32
|
# JSON Serialization Functions
|
@@ -44,8 +49,7 @@ def multipart_messages_to_json(messages: List[PromptMessageMultipart]) -> str:
|
|
44
49
|
# Convert to dictionaries using model_dump with proper JSON mode
|
45
50
|
# The mode="json" parameter ensures proper handling of AnyUrl objects
|
46
51
|
message_dicts = [
|
47
|
-
message.model_dump(by_alias=True, mode="json", exclude_none=True)
|
48
|
-
for message in messages
|
52
|
+
message.model_dump(by_alias=True, mode="json", exclude_none=True) for message in messages
|
49
53
|
]
|
50
54
|
|
51
55
|
# Convert to JSON string
|
@@ -76,9 +80,7 @@ def json_to_multipart_messages(json_str: str) -> List[PromptMessageMultipart]:
|
|
76
80
|
return messages
|
77
81
|
|
78
82
|
|
79
|
-
def save_messages_to_json_file(
|
80
|
-
messages: List[PromptMessageMultipart], file_path: str
|
81
|
-
) -> None:
|
83
|
+
def save_messages_to_json_file(messages: List[PromptMessageMultipart], file_path: str) -> None:
|
82
84
|
"""
|
83
85
|
Save PromptMessageMultipart objects to a JSON file.
|
84
86
|
|
@@ -115,9 +117,9 @@ def load_messages_from_json_file(file_path: str) -> List[PromptMessageMultipart]
|
|
115
117
|
|
116
118
|
def multipart_messages_to_delimited_format(
|
117
119
|
messages: List[PromptMessageMultipart],
|
118
|
-
user_delimiter: str =
|
119
|
-
assistant_delimiter: str =
|
120
|
-
resource_delimiter: str =
|
120
|
+
user_delimiter: str = USER_DELIMITER,
|
121
|
+
assistant_delimiter: str = ASSISTANT_DELIMITER,
|
122
|
+
resource_delimiter: str = RESOURCE_DELIMITER,
|
121
123
|
combine_text: bool = True, # Set to False to maintain backward compatibility
|
122
124
|
) -> List[str]:
|
123
125
|
"""
|
@@ -169,9 +171,7 @@ def multipart_messages_to_delimited_format(
|
|
169
171
|
delimited_content.append(resource_delimiter)
|
170
172
|
|
171
173
|
# Convert to dictionary using proper JSON mode
|
172
|
-
content_dict = content.model_dump(
|
173
|
-
by_alias=True, mode="json", exclude_none=True
|
174
|
-
)
|
174
|
+
content_dict = content.model_dump(by_alias=True, mode="json", exclude_none=True)
|
175
175
|
|
176
176
|
# Add to delimited content as JSON
|
177
177
|
delimited_content.append(json.dumps(content_dict, indent=2))
|
@@ -186,9 +186,7 @@ def multipart_messages_to_delimited_format(
|
|
186
186
|
delimited_content.append(resource_delimiter)
|
187
187
|
|
188
188
|
# Convert to dictionary using proper JSON mode
|
189
|
-
content_dict = content.model_dump(
|
190
|
-
by_alias=True, mode="json", exclude_none=True
|
191
|
-
)
|
189
|
+
content_dict = content.model_dump(by_alias=True, mode="json", exclude_none=True)
|
192
190
|
|
193
191
|
# Add to delimited content as JSON
|
194
192
|
delimited_content.append(json.dumps(content_dict, indent=2))
|
@@ -198,9 +196,9 @@ def multipart_messages_to_delimited_format(
|
|
198
196
|
|
199
197
|
def delimited_format_to_multipart_messages(
|
200
198
|
content: str,
|
201
|
-
user_delimiter: str =
|
202
|
-
assistant_delimiter: str =
|
203
|
-
resource_delimiter: str =
|
199
|
+
user_delimiter: str = USER_DELIMITER,
|
200
|
+
assistant_delimiter: str = ASSISTANT_DELIMITER,
|
201
|
+
resource_delimiter: str = RESOURCE_DELIMITER,
|
204
202
|
) -> List[PromptMessageMultipart]:
|
205
203
|
"""
|
206
204
|
Parse hybrid delimited format into PromptMessageMultipart objects:
|
@@ -237,31 +235,23 @@ def delimited_format_to_multipart_messages(
|
|
237
235
|
collecting_text = True
|
238
236
|
|
239
237
|
# Process each line
|
240
|
-
for line in
|
241
|
-
lines[1:] if lines else []
|
242
|
-
): # Skip the first line if already processed above
|
238
|
+
for line in lines[1:] if lines else []: # Skip the first line if already processed above
|
243
239
|
line_stripped = line.strip()
|
244
240
|
|
245
241
|
# Handle role delimiters
|
246
242
|
if line_stripped == user_delimiter or line_stripped == assistant_delimiter:
|
247
243
|
# Save previous message if it exists
|
248
|
-
if current_role is not None and (
|
249
|
-
text_contents or resource_contents or text_lines
|
250
|
-
):
|
244
|
+
if current_role is not None and (text_contents or resource_contents or text_lines):
|
251
245
|
# If we were collecting text, add it to the text contents
|
252
246
|
if collecting_text and text_lines:
|
253
|
-
text_contents.append(
|
254
|
-
TextContent(type="text", text="\n".join(text_lines))
|
255
|
-
)
|
247
|
+
text_contents.append(TextContent(type="text", text="\n".join(text_lines)))
|
256
248
|
text_lines = []
|
257
249
|
|
258
250
|
# Create content list with text parts first, then resource parts
|
259
251
|
combined_content = []
|
260
252
|
|
261
253
|
# Filter out any empty text content items
|
262
|
-
filtered_text_contents = [
|
263
|
-
tc for tc in text_contents if tc.text.strip() != ""
|
264
|
-
]
|
254
|
+
filtered_text_contents = [tc for tc in text_contents if tc.text.strip() != ""]
|
265
255
|
|
266
256
|
combined_content.extend(filtered_text_contents)
|
267
257
|
combined_content.extend(resource_contents)
|
@@ -286,9 +276,7 @@ def delimited_format_to_multipart_messages(
|
|
286
276
|
elif line_stripped == resource_delimiter:
|
287
277
|
# If we were collecting text, add it to text contents
|
288
278
|
if collecting_text and text_lines:
|
289
|
-
text_contents.append(
|
290
|
-
TextContent(type="text", text="\n".join(text_lines))
|
291
|
-
)
|
279
|
+
text_contents.append(TextContent(type="text", text="\n".join(text_lines)))
|
292
280
|
text_lines = []
|
293
281
|
|
294
282
|
# Switch to collecting JSON or legacy format
|
@@ -303,11 +291,7 @@ def delimited_format_to_multipart_messages(
|
|
303
291
|
json_lines.append(line)
|
304
292
|
|
305
293
|
# For legacy format or files where resources are just plain text
|
306
|
-
if (
|
307
|
-
legacy_format
|
308
|
-
and line_stripped
|
309
|
-
and not line_stripped.startswith("{")
|
310
|
-
):
|
294
|
+
if legacy_format and line_stripped and not line_stripped.startswith("{"):
|
311
295
|
# This is probably a legacy resource reference like a filename
|
312
296
|
resource_uri = line_stripped
|
313
297
|
if not resource_uri.startswith("resource://"):
|
@@ -370,9 +354,7 @@ def delimited_format_to_multipart_messages(
|
|
370
354
|
combined_content = []
|
371
355
|
|
372
356
|
# Filter out any empty text content items
|
373
|
-
filtered_text_contents = [
|
374
|
-
tc for tc in text_contents if tc.text.strip() != ""
|
375
|
-
]
|
357
|
+
filtered_text_contents = [tc for tc in text_contents if tc.text.strip() != ""]
|
376
358
|
|
377
359
|
combined_content.extend(filtered_text_contents)
|
378
360
|
combined_content.extend(resource_contents)
|
@@ -390,9 +372,9 @@ def delimited_format_to_multipart_messages(
|
|
390
372
|
def save_messages_to_delimited_file(
|
391
373
|
messages: List[PromptMessageMultipart],
|
392
374
|
file_path: str,
|
393
|
-
user_delimiter: str =
|
394
|
-
assistant_delimiter: str =
|
395
|
-
resource_delimiter: str =
|
375
|
+
user_delimiter: str = USER_DELIMITER,
|
376
|
+
assistant_delimiter: str = ASSISTANT_DELIMITER,
|
377
|
+
resource_delimiter: str = RESOURCE_DELIMITER,
|
396
378
|
combine_text: bool = True,
|
397
379
|
) -> None:
|
398
380
|
"""
|
@@ -420,9 +402,9 @@ def save_messages_to_delimited_file(
|
|
420
402
|
|
421
403
|
def load_messages_from_delimited_file(
|
422
404
|
file_path: str,
|
423
|
-
user_delimiter: str =
|
424
|
-
assistant_delimiter: str =
|
425
|
-
resource_delimiter: str =
|
405
|
+
user_delimiter: str = USER_DELIMITER,
|
406
|
+
assistant_delimiter: str = ASSISTANT_DELIMITER,
|
407
|
+
resource_delimiter: str = RESOURCE_DELIMITER,
|
426
408
|
) -> List[PromptMessageMultipart]:
|
427
409
|
"""
|
428
410
|
Load PromptMessageMultipart objects from a file in hybrid delimited format.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"""
|
2
|
+
Constants for the prompt system.
|
3
|
+
|
4
|
+
This module defines constants used throughout the prompt system, including
|
5
|
+
delimiters for parsing prompt files and serializing prompt messages.
|
6
|
+
"""
|
7
|
+
|
8
|
+
# Standard delimiters used for prompt template parsing and serialization
|
9
|
+
USER_DELIMITER = "---USER"
|
10
|
+
ASSISTANT_DELIMITER = "---ASSISTANT"
|
11
|
+
RESOURCE_DELIMITER = "---RESOURCE"
|
12
|
+
|
13
|
+
# Default delimiter mapping used by PromptTemplate and PromptTemplateLoader
|
14
|
+
DEFAULT_DELIMITER_MAP = {
|
15
|
+
USER_DELIMITER: "user",
|
16
|
+
ASSISTANT_DELIMITER: "assistant",
|
17
|
+
RESOURCE_DELIMITER: "resource",
|
18
|
+
}
|