coco-framework 0.1.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.
- coco/__init__.py +3 -0
- coco/agents/__init__.py +9 -0
- coco/agents/_subagent_transformer.py +307 -0
- coco/agents/factory.py +2164 -0
- coco/agents/middleware/__init__.py +100 -0
- coco/agents/middleware/_execution.py +385 -0
- coco/agents/middleware/_redaction.py +454 -0
- coco/agents/middleware/_retry.py +134 -0
- coco/agents/middleware/_trace_policy.py +61 -0
- coco/agents/middleware/context_editing.py +306 -0
- coco/agents/middleware/file_search.py +433 -0
- coco/agents/middleware/human_in_the_loop.py +680 -0
- coco/agents/middleware/internal_call_transformer.py +108 -0
- coco/agents/middleware/model_call_limit.py +267 -0
- coco/agents/middleware/model_fallback.py +417 -0
- coco/agents/middleware/model_retry.py +327 -0
- coco/agents/middleware/pii.py +878 -0
- coco/agents/middleware/provider_tool_search.py +307 -0
- coco/agents/middleware/shell_tool.py +949 -0
- coco/agents/middleware/summarization.py +910 -0
- coco/agents/middleware/todo.py +357 -0
- coco/agents/middleware/tool_call_limit.py +495 -0
- coco/agents/middleware/tool_emulator.py +251 -0
- coco/agents/middleware/tool_error.py +209 -0
- coco/agents/middleware/tool_retry.py +421 -0
- coco/agents/middleware/tool_selection.py +515 -0
- coco/agents/middleware/types.py +2201 -0
- coco/agents/structured_output.py +472 -0
- coco/chat_models/__init__.py +7 -0
- coco/chat_models/base.py +1082 -0
- coco/embeddings/__init__.py +18 -0
- coco/embeddings/base.py +279 -0
- coco/mcp/__init__.py +36 -0
- coco/mcp/adapter.py +245 -0
- coco/mcp/elicitation.py +394 -0
- coco/mcp/tools.py +307 -0
- coco/messages/__init__.py +73 -0
- coco/py.typed +0 -0
- coco/rate_limiters/__init__.py +13 -0
- coco/tools/__init__.py +22 -0
- coco/tools/tool_node.py +20 -0
- coco_anthropic/__init__.py +15 -0
- coco_anthropic/_client_utils.py +81 -0
- coco_anthropic/_compat.py +228 -0
- coco_anthropic/_sdk_compat.py +124 -0
- coco_anthropic/_version.py +3 -0
- coco_anthropic/chat_models.py +3349 -0
- coco_anthropic/data/__init__.py +1 -0
- coco_anthropic/data/_profiles.py +491 -0
- coco_anthropic/data/profile_augmentations.toml +69 -0
- coco_anthropic/experimental.py +140 -0
- coco_anthropic/llms.py +428 -0
- coco_anthropic/middleware/__init__.py +25 -0
- coco_anthropic/middleware/anthropic_tools.py +1197 -0
- coco_anthropic/middleware/bash.py +84 -0
- coco_anthropic/middleware/file_search.py +360 -0
- coco_anthropic/middleware/prompt_caching.py +276 -0
- coco_anthropic/output_parsers.py +93 -0
- coco_anthropic/py.typed +0 -0
- coco_core/__init__.py +20 -0
- coco_core/_api/__init__.py +87 -0
- coco_core/_api/beta_decorator.py +266 -0
- coco_core/_api/deprecation.py +637 -0
- coco_core/_api/internal.py +23 -0
- coco_core/_api/path.py +50 -0
- coco_core/_import_utils.py +41 -0
- coco_core/_protocol.py +625 -0
- coco_core/_security/__init__.py +36 -0
- coco_core/_security/_exceptions.py +9 -0
- coco_core/_security/_policy.py +313 -0
- coco_core/_security/_ssrf_protection.py +155 -0
- coco_core/_security/_transport.py +254 -0
- coco_core/agents.py +258 -0
- coco_core/caches.py +272 -0
- coco_core/callbacks/__init__.py +132 -0
- coco_core/callbacks/base.py +1229 -0
- coco_core/callbacks/file.py +266 -0
- coco_core/callbacks/manager.py +2826 -0
- coco_core/callbacks/stdout.py +123 -0
- coco_core/callbacks/streaming_stdout.py +154 -0
- coco_core/callbacks/usage.py +124 -0
- coco_core/chat_history.py +267 -0
- coco_core/chat_loaders.py +26 -0
- coco_core/chat_sessions.py +19 -0
- coco_core/cross_encoders.py +18 -0
- coco_core/document_loaders/__init__.py +36 -0
- coco_core/document_loaders/base.py +155 -0
- coco_core/document_loaders/blob_loaders.py +38 -0
- coco_core/documents/__init__.py +55 -0
- coco_core/documents/base.py +347 -0
- coco_core/documents/compressor.py +74 -0
- coco_core/documents/transformers.py +79 -0
- coco_core/embeddings/__init__.py +31 -0
- coco_core/embeddings/embeddings.py +78 -0
- coco_core/embeddings/fake.py +129 -0
- coco_core/env.py +22 -0
- coco_core/example_selectors/__init__.py +47 -0
- coco_core/example_selectors/base.py +60 -0
- coco_core/example_selectors/length_based.py +131 -0
- coco_core/example_selectors/semantic_similarity.py +366 -0
- coco_core/exceptions.py +166 -0
- coco_core/globals.py +72 -0
- coco_core/indexing/__init__.py +53 -0
- coco_core/indexing/api.py +954 -0
- coco_core/indexing/base.py +661 -0
- coco_core/indexing/in_memory.py +104 -0
- coco_core/language_models/__init__.py +116 -0
- coco_core/language_models/_compat_bridge.py +844 -0
- coco_core/language_models/_utils.py +343 -0
- coco_core/language_models/base.py +500 -0
- coco_core/language_models/chat_model_stream.py +1525 -0
- coco_core/language_models/chat_models.py +2748 -0
- coco_core/language_models/fake.py +137 -0
- coco_core/language_models/fake_chat_models.py +396 -0
- coco_core/language_models/llms.py +1569 -0
- coco_core/language_models/model_profile.py +183 -0
- coco_core/load/__init__.py +44 -0
- coco_core/load/_validation.py +191 -0
- coco_core/load/dump.py +120 -0
- coco_core/load/load.py +828 -0
- coco_core/load/mapping.py +1097 -0
- coco_core/load/serializable.py +406 -0
- coco_core/messages/__init__.py +198 -0
- coco_core/messages/ai.py +854 -0
- coco_core/messages/base.py +518 -0
- coco_core/messages/block_translators/__init__.py +112 -0
- coco_core/messages/block_translators/anthropic.py +534 -0
- coco_core/messages/block_translators/bedrock.py +108 -0
- coco_core/messages/block_translators/bedrock_converse.py +329 -0
- coco_core/messages/block_translators/coco_v0.py +303 -0
- coco_core/messages/block_translators/google_genai.py +610 -0
- coco_core/messages/block_translators/google_vertexai.py +21 -0
- coco_core/messages/block_translators/groq.py +157 -0
- coco_core/messages/block_translators/openai.py +1089 -0
- coco_core/messages/chat.py +64 -0
- coco_core/messages/content.py +1488 -0
- coco_core/messages/function.py +62 -0
- coco_core/messages/human.py +70 -0
- coco_core/messages/modifier.py +33 -0
- coco_core/messages/system.py +70 -0
- coco_core/messages/tool.py +418 -0
- coco_core/messages/utils.py +2442 -0
- coco_core/output_parsers/__init__.py +101 -0
- coco_core/output_parsers/base.py +361 -0
- coco_core/output_parsers/format_instructions.py +16 -0
- coco_core/output_parsers/json.py +139 -0
- coco_core/output_parsers/list.py +249 -0
- coco_core/output_parsers/openai_functions.py +324 -0
- coco_core/output_parsers/openai_tools.py +383 -0
- coco_core/output_parsers/pydantic.py +141 -0
- coco_core/output_parsers/string.py +63 -0
- coco_core/output_parsers/transform.py +175 -0
- coco_core/output_parsers/xml.py +301 -0
- coco_core/outputs/__init__.py +66 -0
- coco_core/outputs/chat_generation.py +147 -0
- coco_core/outputs/chat_result.py +39 -0
- coco_core/outputs/generation.py +80 -0
- coco_core/outputs/llm_result.py +112 -0
- coco_core/outputs/run_info.py +22 -0
- coco_core/prompt_values.py +161 -0
- coco_core/prompts/__init__.py +101 -0
- coco_core/prompts/base.py +508 -0
- coco_core/prompts/chat.py +1495 -0
- coco_core/prompts/dict.py +177 -0
- coco_core/prompts/few_shot.py +483 -0
- coco_core/prompts/few_shot_with_templates.py +239 -0
- coco_core/prompts/image.py +177 -0
- coco_core/prompts/loading.py +296 -0
- coco_core/prompts/message.py +97 -0
- coco_core/prompts/prompt.py +312 -0
- coco_core/prompts/string.py +399 -0
- coco_core/prompts/structured.py +214 -0
- coco_core/py.typed +0 -0
- coco_core/rate_limiters.py +254 -0
- coco_core/retrievers.py +328 -0
- coco_core/runnables/__init__.py +136 -0
- coco_core/runnables/base.py +6725 -0
- coco_core/runnables/branch.py +457 -0
- coco_core/runnables/config.py +712 -0
- coco_core/runnables/configurable.py +710 -0
- coco_core/runnables/fallbacks.py +663 -0
- coco_core/runnables/graph.py +741 -0
- coco_core/runnables/graph_ascii.py +366 -0
- coco_core/runnables/graph_mermaid.py +503 -0
- coco_core/runnables/graph_png.py +215 -0
- coco_core/runnables/history.py +631 -0
- coco_core/runnables/passthrough.py +849 -0
- coco_core/runnables/retry.py +379 -0
- coco_core/runnables/router.py +239 -0
- coco_core/runnables/schema.py +188 -0
- coco_core/runnables/utils.py +798 -0
- coco_core/stores.py +291 -0
- coco_core/structured_query.py +203 -0
- coco_core/sys_info.py +154 -0
- coco_core/tools/__init__.py +95 -0
- coco_core/tools/base.py +1948 -0
- coco_core/tools/convert.py +497 -0
- coco_core/tools/render.py +67 -0
- coco_core/tools/retriever.py +94 -0
- coco_core/tools/simple.py +208 -0
- coco_core/tools/structured.py +322 -0
- coco_core/tracers/__init__.py +47 -0
- coco_core/tracers/_compat.py +95 -0
- coco_core/tracers/_context.py +337 -0
- coco_core/tracers/_streaming.py +53 -0
- coco_core/tracers/base.py +955 -0
- coco_core/tracers/coco.py +279 -0
- coco_core/tracers/context.py +205 -0
- coco_core/tracers/core.py +766 -0
- coco_core/tracers/event_stream.py +1101 -0
- coco_core/tracers/log_stream.py +765 -0
- coco_core/tracers/memory_stream.py +200 -0
- coco_core/tracers/root_listeners.py +130 -0
- coco_core/tracers/run_collector.py +40 -0
- coco_core/tracers/schemas.py +14 -0
- coco_core/tracers/stdout.py +205 -0
- coco_core/utils/__init__.py +111 -0
- coco_core/utils/_gateway.py +274 -0
- coco_core/utils/_merge.py +218 -0
- coco_core/utils/aiter.py +357 -0
- coco_core/utils/env.py +86 -0
- coco_core/utils/formatting.py +80 -0
- coco_core/utils/function_calling.py +869 -0
- coco_core/utils/html.py +132 -0
- coco_core/utils/image.py +15 -0
- coco_core/utils/input.py +82 -0
- coco_core/utils/interactive_env.py +12 -0
- coco_core/utils/iter.py +229 -0
- coco_core/utils/json.py +230 -0
- coco_core/utils/json_schema.py +273 -0
- coco_core/utils/mustache.py +706 -0
- coco_core/utils/pydantic.py +631 -0
- coco_core/utils/strings.py +69 -0
- coco_core/utils/usage.py +61 -0
- coco_core/utils/utils.py +528 -0
- coco_core/utils/uuid.py +57 -0
- coco_core/vectorstores/__init__.py +53 -0
- coco_core/vectorstores/base.py +1111 -0
- coco_core/vectorstores/in_memory.py +546 -0
- coco_core/vectorstores/utils.py +163 -0
- coco_core/version.py +3 -0
- coco_framework-0.1.0.dist-info/METADATA +184 -0
- coco_framework-0.1.0.dist-info/RECORD +400 -0
- coco_framework-0.1.0.dist-info/WHEEL +4 -0
- coco_framework-0.1.0.dist-info/licenses/LICENSE +24 -0
- coco_framework-0.1.0.dist-info/licenses/NOTICE +15 -0
- coco_graph/_internal/__init__.py +4 -0
- coco_graph/_internal/_cache.py +31 -0
- coco_graph/_internal/_config.py +474 -0
- coco_graph/_internal/_constants.py +140 -0
- coco_graph/_internal/_fields.py +213 -0
- coco_graph/_internal/_future.py +220 -0
- coco_graph/_internal/_pydantic.py +275 -0
- coco_graph/_internal/_queue.py +124 -0
- coco_graph/_internal/_replay.py +90 -0
- coco_graph/_internal/_retry.py +29 -0
- coco_graph/_internal/_runnable.py +969 -0
- coco_graph/_internal/_scratchpad.py +19 -0
- coco_graph/_internal/_serde.py +253 -0
- coco_graph/_internal/_timeout.py +25 -0
- coco_graph/_internal/_typing.py +54 -0
- coco_graph/cache/base/__init__.py +48 -0
- coco_graph/cache/base/py.typed +0 -0
- coco_graph/cache/memory/__init__.py +73 -0
- coco_graph/cache/redis/__init__.py +144 -0
- coco_graph/cache/sqlite/__init__.py +120 -0
- coco_graph/callbacks.py +394 -0
- coco_graph/channels/__init__.py +29 -0
- coco_graph/channels/any_value.py +72 -0
- coco_graph/channels/base.py +121 -0
- coco_graph/channels/binop.py +155 -0
- coco_graph/channels/delta.py +202 -0
- coco_graph/channels/ephemeral_value.py +79 -0
- coco_graph/channels/last_value.py +151 -0
- coco_graph/channels/named_barrier_value.py +167 -0
- coco_graph/channels/topic.py +94 -0
- coco_graph/channels/untracked_value.py +73 -0
- coco_graph/checkpoint/base/__init__.py +861 -0
- coco_graph/checkpoint/base/id.py +109 -0
- coco_graph/checkpoint/base/py.typed +0 -0
- coco_graph/checkpoint/memory/__init__.py +698 -0
- coco_graph/checkpoint/memory/py.typed +0 -0
- coco_graph/checkpoint/postgres/__init__.py +602 -0
- coco_graph/checkpoint/postgres/_ainternal.py +23 -0
- coco_graph/checkpoint/postgres/_internal.py +21 -0
- coco_graph/checkpoint/postgres/aio.py +691 -0
- coco_graph/checkpoint/postgres/base.py +666 -0
- coco_graph/checkpoint/postgres/py.typed +0 -0
- coco_graph/checkpoint/postgres/shallow.py +967 -0
- coco_graph/checkpoint/serde/__init__.py +0 -0
- coco_graph/checkpoint/serde/_msgpack.py +97 -0
- coco_graph/checkpoint/serde/base.py +64 -0
- coco_graph/checkpoint/serde/encrypted.py +80 -0
- coco_graph/checkpoint/serde/event_hooks.py +52 -0
- coco_graph/checkpoint/serde/jsonplus.py +883 -0
- coco_graph/checkpoint/serde/py.typed +0 -0
- coco_graph/checkpoint/serde/types.py +68 -0
- coco_graph/checkpoint/sqlite/__init__.py +645 -0
- coco_graph/checkpoint/sqlite/_delta.py +172 -0
- coco_graph/checkpoint/sqlite/aio.py +738 -0
- coco_graph/checkpoint/sqlite/py.typed +0 -0
- coco_graph/checkpoint/sqlite/utils.py +116 -0
- coco_graph/config.py +196 -0
- coco_graph/constants.py +64 -0
- coco_graph/errors.py +241 -0
- coco_graph/func/__init__.py +620 -0
- coco_graph/graph/__init__.py +12 -0
- coco_graph/graph/_branch.py +225 -0
- coco_graph/graph/_node.py +103 -0
- coco_graph/graph/message.py +437 -0
- coco_graph/graph/state.py +1978 -0
- coco_graph/graph/ui.py +227 -0
- coco_graph/managed/__init__.py +3 -0
- coco_graph/managed/base.py +31 -0
- coco_graph/managed/is_last_step.py +24 -0
- coco_graph/prebuilt/__init__.py +23 -0
- coco_graph/prebuilt/_tool_call_stream.py +117 -0
- coco_graph/prebuilt/_tool_call_transformer.py +165 -0
- coco_graph/prebuilt/chat_agent_executor.py +1015 -0
- coco_graph/prebuilt/interrupt.py +105 -0
- coco_graph/prebuilt/py.typed +0 -0
- coco_graph/prebuilt/tool_node.py +2030 -0
- coco_graph/prebuilt/tool_validator.py +221 -0
- coco_graph/pregel/__init__.py +3 -0
- coco_graph/pregel/_algo.py +1460 -0
- coco_graph/pregel/_call.py +298 -0
- coco_graph/pregel/_checkpoint.py +331 -0
- coco_graph/pregel/_config.py +0 -0
- coco_graph/pregel/_draw.py +294 -0
- coco_graph/pregel/_executor.py +223 -0
- coco_graph/pregel/_io.py +174 -0
- coco_graph/pregel/_log.py +3 -0
- coco_graph/pregel/_loop.py +1988 -0
- coco_graph/pregel/_messages.py +461 -0
- coco_graph/pregel/_read.py +312 -0
- coco_graph/pregel/_retry.py +854 -0
- coco_graph/pregel/_runner.py +941 -0
- coco_graph/pregel/_tools.py +268 -0
- coco_graph/pregel/_utils.py +221 -0
- coco_graph/pregel/_validate.py +120 -0
- coco_graph/pregel/_write.py +192 -0
- coco_graph/pregel/debug.py +302 -0
- coco_graph/pregel/main.py +4364 -0
- coco_graph/pregel/protocol.py +288 -0
- coco_graph/pregel/types.py +38 -0
- coco_graph/py.typed +0 -0
- coco_graph/runtime.py +350 -0
- coco_graph/store/base/__init__.py +1322 -0
- coco_graph/store/base/batch.py +371 -0
- coco_graph/store/base/embed.py +436 -0
- coco_graph/store/base/py.typed +0 -0
- coco_graph/store/memory/__init__.py +592 -0
- coco_graph/store/memory/py.typed +0 -0
- coco_graph/store/postgres/__init__.py +4 -0
- coco_graph/store/postgres/aio.py +592 -0
- coco_graph/store/postgres/base.py +1480 -0
- coco_graph/store/postgres/py.typed +0 -0
- coco_graph/store/sqlite/__init__.py +4 -0
- coco_graph/store/sqlite/aio.py +632 -0
- coco_graph/store/sqlite/base.py +1514 -0
- coco_graph/stream/__init__.py +45 -0
- coco_graph/stream/_convert.py +32 -0
- coco_graph/stream/_mux.py +523 -0
- coco_graph/stream/_types.py +330 -0
- coco_graph/stream/run_stream.py +735 -0
- coco_graph/stream/stream_channel.py +341 -0
- coco_graph/stream/transformers.py +1039 -0
- coco_graph/types.py +1079 -0
- coco_graph/typing.py +48 -0
- coco_graph/utils/__init__.py +1 -0
- coco_graph/utils/config.py +4 -0
- coco_graph/utils/runnable.py +3 -0
- coco_graph/version.py +13 -0
- coco_graph/warnings.py +69 -0
- coco_openai/__init__.py +20 -0
- coco_openai/_compat.py +45 -0
- coco_openai/_version.py +3 -0
- coco_openai/chat_models/__init__.py +6 -0
- coco_openai/chat_models/_client_utils.py +684 -0
- coco_openai/chat_models/_compat.py +525 -0
- coco_openai/chat_models/azure.py +1227 -0
- coco_openai/chat_models/base.py +5654 -0
- coco_openai/chat_models/codex.py +557 -0
- coco_openai/chatgpt_oauth.py +1063 -0
- coco_openai/data/__init__.py +1 -0
- coco_openai/data/_profiles.py +1655 -0
- coco_openai/data/profile_augmentations.toml +127 -0
- coco_openai/embeddings/__init__.py +6 -0
- coco_openai/embeddings/azure.py +240 -0
- coco_openai/embeddings/base.py +820 -0
- coco_openai/llms/__init__.py +6 -0
- coco_openai/llms/azure.py +249 -0
- coco_openai/llms/base.py +919 -0
- coco_openai/middleware/__init__.py +11 -0
- coco_openai/middleware/openai_moderation.py +484 -0
- coco_openai/output_parsers/__init__.py +9 -0
- coco_openai/output_parsers/tools.py +9 -0
- coco_openai/py.typed +0 -0
- coco_openai/tools/__init__.py +5 -0
- coco_openai/tools/custom_tool.py +111 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
"""Base class for prompt templates."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import builtins
|
|
6
|
+
import contextlib
|
|
7
|
+
import json
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
from collections.abc import Callable, Mapping
|
|
10
|
+
from functools import cached_property
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
|
|
13
|
+
|
|
14
|
+
import yaml
|
|
15
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
16
|
+
from typing_extensions import Self, override
|
|
17
|
+
|
|
18
|
+
from coco_core._api import deprecated, suppress_coco_deprecation_warning
|
|
19
|
+
from coco_core.exceptions import ErrorCode, create_message
|
|
20
|
+
from coco_core.load import dumpd
|
|
21
|
+
from coco_core.output_parsers.base import BaseOutputParser
|
|
22
|
+
from coco_core.prompt_values import (
|
|
23
|
+
ChatPromptValueConcrete,
|
|
24
|
+
PromptValue,
|
|
25
|
+
StringPromptValue,
|
|
26
|
+
)
|
|
27
|
+
from coco_core.runnables.base import RunnableSerializable
|
|
28
|
+
from coco_core.runnables.config import RunnableConfig, ensure_config
|
|
29
|
+
from coco_core.utils.pydantic import create_model_v2
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from coco_core.documents import Document
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
FormatOutputType = TypeVar("FormatOutputType")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class BasePromptTemplate(
|
|
39
|
+
RunnableSerializable[dict[str, Any], PromptValue], ABC, Generic[FormatOutputType]
|
|
40
|
+
):
|
|
41
|
+
"""Base class for all prompt templates, returning a prompt."""
|
|
42
|
+
|
|
43
|
+
input_variables: list[str]
|
|
44
|
+
"""A list of the names of the variables whose values are required as inputs to the
|
|
45
|
+
prompt.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
optional_variables: list[str] = Field(default=[])
|
|
49
|
+
"""A list of the names of the variables for placeholder or `MessagePlaceholder` that
|
|
50
|
+
are optional.
|
|
51
|
+
|
|
52
|
+
These variables are auto inferred from the prompt and user need not provide them.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
input_types: builtins.dict[str, Any] = Field(default_factory=dict, exclude=True)
|
|
56
|
+
"""A dictionary of the types of the variables the prompt template expects.
|
|
57
|
+
|
|
58
|
+
If not provided, all variables are assumed to be strings.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
# Ideally we would type output_parser as BaseOutputParser[Any]
|
|
62
|
+
# but that makes Pydantic fail (Pydantic tries to instantiate BaseOutputParser
|
|
63
|
+
# instead of using the provided output_parser...)
|
|
64
|
+
output_parser: BaseOutputParser | None = None # type: ignore[type-arg]
|
|
65
|
+
"""How to parse the output of calling an LLM on this formatted prompt."""
|
|
66
|
+
|
|
67
|
+
partial_variables: Mapping[str, Any] = Field(default_factory=dict)
|
|
68
|
+
"""A dictionary of the partial variables the prompt template carries.
|
|
69
|
+
|
|
70
|
+
Partial variables populate the template so that you don't need to pass them in every
|
|
71
|
+
time you call the prompt.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
metadata: builtins.dict[str, Any] | None = None
|
|
75
|
+
"""Metadata to be used for tracing."""
|
|
76
|
+
|
|
77
|
+
tags: list[str] | None = None
|
|
78
|
+
"""Tags to be used for tracing."""
|
|
79
|
+
|
|
80
|
+
@model_validator(mode="after")
|
|
81
|
+
def validate_variable_names(self) -> Self:
|
|
82
|
+
"""Validate variable names do not include restricted names."""
|
|
83
|
+
if "stop" in self.input_variables:
|
|
84
|
+
msg = (
|
|
85
|
+
"Cannot have an input variable named 'stop', as it is used internally,"
|
|
86
|
+
" please rename."
|
|
87
|
+
)
|
|
88
|
+
raise ValueError(
|
|
89
|
+
create_message(message=msg, error_code=ErrorCode.INVALID_PROMPT_INPUT)
|
|
90
|
+
)
|
|
91
|
+
if "stop" in self.partial_variables:
|
|
92
|
+
msg = (
|
|
93
|
+
"Cannot have an partial variable named 'stop', as it is used "
|
|
94
|
+
"internally, please rename."
|
|
95
|
+
)
|
|
96
|
+
raise ValueError(
|
|
97
|
+
create_message(message=msg, error_code=ErrorCode.INVALID_PROMPT_INPUT)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
overall = set(self.input_variables).intersection(self.partial_variables)
|
|
101
|
+
if overall:
|
|
102
|
+
msg = f"Found overlapping input and partial variables: {overall}"
|
|
103
|
+
raise ValueError(
|
|
104
|
+
create_message(message=msg, error_code=ErrorCode.INVALID_PROMPT_INPUT)
|
|
105
|
+
)
|
|
106
|
+
return self
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def get_lc_namespace(cls) -> list[str]:
|
|
110
|
+
"""Get the namespace of the Coco object.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
`["coco", "schema", "prompt_template"]`
|
|
114
|
+
"""
|
|
115
|
+
return ["coco", "schema", "prompt_template"]
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def is_lc_serializable(cls) -> bool:
|
|
119
|
+
"""Return `True` as this class is serializable."""
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
model_config = ConfigDict(
|
|
123
|
+
arbitrary_types_allowed=True,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
@cached_property
|
|
127
|
+
def _serialized(self) -> builtins.dict[str, Any]:
|
|
128
|
+
# self is always a Serializable object in this case, thus the result is
|
|
129
|
+
# guaranteed to be a dict since dumpd uses the default callback, which uses
|
|
130
|
+
# obj.to_json which always returns TypedDict subclasses
|
|
131
|
+
return cast("builtins.dict[str, Any]", dumpd(self))
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
@override
|
|
135
|
+
def OutputType(self) -> Any:
|
|
136
|
+
"""Return the output type of the prompt."""
|
|
137
|
+
return StringPromptValue | ChatPromptValueConcrete
|
|
138
|
+
|
|
139
|
+
@override
|
|
140
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
141
|
+
"""Get the input schema for the prompt.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
config: Configuration for the prompt.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
The input schema for the prompt.
|
|
148
|
+
"""
|
|
149
|
+
# This is correct, but pydantic typings/mypy don't think so.
|
|
150
|
+
required_input_variables = {
|
|
151
|
+
k: (self.input_types.get(k, str), ...) for k in self.input_variables
|
|
152
|
+
}
|
|
153
|
+
optional_input_variables = {
|
|
154
|
+
k: (self.input_types.get(k, str), None) for k in self.optional_variables
|
|
155
|
+
}
|
|
156
|
+
return create_model_v2(
|
|
157
|
+
"PromptInput",
|
|
158
|
+
field_definitions={**required_input_variables, **optional_input_variables},
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def _validate_input(self, inner_input: Any) -> builtins.dict[str, Any]:
|
|
162
|
+
if not isinstance(inner_input, dict):
|
|
163
|
+
if len(self.input_variables) == 1:
|
|
164
|
+
var_name = self.input_variables[0]
|
|
165
|
+
inner_input_ = {var_name: inner_input}
|
|
166
|
+
|
|
167
|
+
else:
|
|
168
|
+
msg = (
|
|
169
|
+
f"Expected mapping type as input to {self.__class__.__name__}. "
|
|
170
|
+
f"Received {type(inner_input)}."
|
|
171
|
+
)
|
|
172
|
+
raise TypeError(
|
|
173
|
+
create_message(
|
|
174
|
+
message=msg, error_code=ErrorCode.INVALID_PROMPT_INPUT
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
else:
|
|
178
|
+
inner_input_ = inner_input
|
|
179
|
+
missing = set(self.input_variables).difference(inner_input_)
|
|
180
|
+
if missing:
|
|
181
|
+
msg = (
|
|
182
|
+
f"Input to {self.__class__.__name__} is missing variables {missing}. "
|
|
183
|
+
f" Expected: {self.input_variables}"
|
|
184
|
+
f" Received: {list(inner_input_.keys())}"
|
|
185
|
+
)
|
|
186
|
+
example_key = missing.pop()
|
|
187
|
+
msg += (
|
|
188
|
+
f"\nNote: if you intended {{{example_key}}} to be part of the string"
|
|
189
|
+
" and not a variable, please escape it with double curly braces like: "
|
|
190
|
+
f"'{{{{{example_key}}}}}'."
|
|
191
|
+
)
|
|
192
|
+
raise KeyError(
|
|
193
|
+
create_message(message=msg, error_code=ErrorCode.INVALID_PROMPT_INPUT)
|
|
194
|
+
)
|
|
195
|
+
return inner_input_
|
|
196
|
+
|
|
197
|
+
def _format_prompt_with_error_handling(
|
|
198
|
+
self, inner_input: builtins.dict[str, Any]
|
|
199
|
+
) -> PromptValue:
|
|
200
|
+
inner_input_ = self._validate_input(inner_input)
|
|
201
|
+
return self.format_prompt(**inner_input_)
|
|
202
|
+
|
|
203
|
+
async def _aformat_prompt_with_error_handling(
|
|
204
|
+
self, inner_input: builtins.dict[str, Any]
|
|
205
|
+
) -> PromptValue:
|
|
206
|
+
inner_input_ = self._validate_input(inner_input)
|
|
207
|
+
return await self.aformat_prompt(**inner_input_)
|
|
208
|
+
|
|
209
|
+
@override
|
|
210
|
+
def invoke(
|
|
211
|
+
self,
|
|
212
|
+
input: builtins.dict[str, Any],
|
|
213
|
+
config: RunnableConfig | None = None,
|
|
214
|
+
**kwargs: Any,
|
|
215
|
+
) -> PromptValue:
|
|
216
|
+
"""Invoke the prompt.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
input: Input to the prompt.
|
|
220
|
+
config: Configuration for the prompt.
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
The output of the prompt.
|
|
224
|
+
"""
|
|
225
|
+
config = ensure_config(config)
|
|
226
|
+
if self.metadata:
|
|
227
|
+
config["metadata"] = {**config["metadata"], **self.metadata}
|
|
228
|
+
if self.tags:
|
|
229
|
+
config["tags"] += self.tags
|
|
230
|
+
return self._call_with_config(
|
|
231
|
+
self._format_prompt_with_error_handling,
|
|
232
|
+
input,
|
|
233
|
+
config,
|
|
234
|
+
run_type="prompt",
|
|
235
|
+
serialized=self._serialized,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
@override
|
|
239
|
+
async def ainvoke(
|
|
240
|
+
self,
|
|
241
|
+
input: builtins.dict[str, Any],
|
|
242
|
+
config: RunnableConfig | None = None,
|
|
243
|
+
**kwargs: Any,
|
|
244
|
+
) -> PromptValue:
|
|
245
|
+
"""Async invoke the prompt.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
input: Input to the prompt.
|
|
249
|
+
config: Configuration for the prompt.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
The output of the prompt.
|
|
253
|
+
"""
|
|
254
|
+
config = ensure_config(config)
|
|
255
|
+
if self.metadata:
|
|
256
|
+
config["metadata"].update(self.metadata)
|
|
257
|
+
if self.tags:
|
|
258
|
+
config["tags"].extend(self.tags)
|
|
259
|
+
return await self._acall_with_config(
|
|
260
|
+
self._aformat_prompt_with_error_handling,
|
|
261
|
+
input,
|
|
262
|
+
config,
|
|
263
|
+
run_type="prompt",
|
|
264
|
+
serialized=self._serialized,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
@abstractmethod
|
|
268
|
+
def format_prompt(self, **kwargs: Any) -> PromptValue:
|
|
269
|
+
"""Create `PromptValue`.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
**kwargs: Any arguments to be passed to the prompt template.
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
The output of the prompt.
|
|
276
|
+
"""
|
|
277
|
+
|
|
278
|
+
async def aformat_prompt(self, **kwargs: Any) -> PromptValue:
|
|
279
|
+
"""Async create `PromptValue`.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
**kwargs: Any arguments to be passed to the prompt template.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
The output of the prompt.
|
|
286
|
+
"""
|
|
287
|
+
return self.format_prompt(**kwargs)
|
|
288
|
+
|
|
289
|
+
def partial(
|
|
290
|
+
self, **kwargs: str | Callable[[], str]
|
|
291
|
+
) -> BasePromptTemplate[FormatOutputType]:
|
|
292
|
+
"""Return a partial of the prompt template.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
**kwargs: Partial variables to set.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
A partial of the prompt template.
|
|
299
|
+
"""
|
|
300
|
+
prompt_dict = self.__dict__.copy()
|
|
301
|
+
prompt_dict["input_variables"] = list(
|
|
302
|
+
set(self.input_variables).difference(kwargs)
|
|
303
|
+
)
|
|
304
|
+
prompt_dict["partial_variables"] = {**self.partial_variables, **kwargs}
|
|
305
|
+
return type(self)(**prompt_dict)
|
|
306
|
+
|
|
307
|
+
def _merge_partial_and_user_variables(
|
|
308
|
+
self, **kwargs: Any
|
|
309
|
+
) -> builtins.dict[str, Any]:
|
|
310
|
+
# Get partial params:
|
|
311
|
+
partial_kwargs = {
|
|
312
|
+
k: v if not callable(v) else v() for k, v in self.partial_variables.items()
|
|
313
|
+
}
|
|
314
|
+
return {**partial_kwargs, **kwargs}
|
|
315
|
+
|
|
316
|
+
@abstractmethod
|
|
317
|
+
def format(self, **kwargs: Any) -> FormatOutputType:
|
|
318
|
+
"""Format the prompt with the inputs.
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
**kwargs: Any arguments to be passed to the prompt template.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
A formatted string.
|
|
325
|
+
|
|
326
|
+
Example:
|
|
327
|
+
```python
|
|
328
|
+
prompt.format(variable1="foo")
|
|
329
|
+
```
|
|
330
|
+
"""
|
|
331
|
+
|
|
332
|
+
async def aformat(self, **kwargs: Any) -> FormatOutputType:
|
|
333
|
+
"""Async format the prompt with the inputs.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
**kwargs: Any arguments to be passed to the prompt template.
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
A formatted string.
|
|
340
|
+
|
|
341
|
+
Example:
|
|
342
|
+
```python
|
|
343
|
+
await prompt.aformat(variable1="foo")
|
|
344
|
+
```
|
|
345
|
+
"""
|
|
346
|
+
return self.format(**kwargs)
|
|
347
|
+
|
|
348
|
+
@property
|
|
349
|
+
def _prompt_type(self) -> str:
|
|
350
|
+
"""Return the prompt type key."""
|
|
351
|
+
raise NotImplementedError
|
|
352
|
+
|
|
353
|
+
@deprecated("1.4.2", alternative="asdict", removal="2.0.0")
|
|
354
|
+
@override
|
|
355
|
+
def dict(self, **kwargs: Any) -> builtins.dict[str, Any]:
|
|
356
|
+
"""DEPRECATED - use `asdict()` instead.
|
|
357
|
+
|
|
358
|
+
Return a dictionary representation of the prompt.
|
|
359
|
+
"""
|
|
360
|
+
return self.asdict(**kwargs)
|
|
361
|
+
|
|
362
|
+
def asdict(self, **kwargs: Any) -> builtins.dict[str, Any]:
|
|
363
|
+
"""Return a dictionary representation of the prompt.
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
**kwargs: Any additional arguments to pass to the dictionary.
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Dictionary representation of the prompt.
|
|
370
|
+
"""
|
|
371
|
+
prompt_dict = super().model_dump(**kwargs)
|
|
372
|
+
with contextlib.suppress(NotImplementedError):
|
|
373
|
+
prompt_dict["_type"] = self._prompt_type
|
|
374
|
+
return prompt_dict
|
|
375
|
+
|
|
376
|
+
def _dict_for_compat(self) -> builtins.dict[str, Any]:
|
|
377
|
+
"""Return the prompt dictionary while preserving deprecated overrides."""
|
|
378
|
+
with suppress_coco_deprecation_warning():
|
|
379
|
+
return self.dict()
|
|
380
|
+
|
|
381
|
+
@deprecated(
|
|
382
|
+
since="1.2.21",
|
|
383
|
+
removal="2.0.0",
|
|
384
|
+
alternative="Use `dumpd`/`dumps` from `coco_core.load` to serialize "
|
|
385
|
+
"prompts and `load`/`loads` to deserialize them.",
|
|
386
|
+
)
|
|
387
|
+
def save(self, file_path: Path | str) -> None:
|
|
388
|
+
"""Save the prompt.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
file_path: Path to directory to save prompt to.
|
|
392
|
+
|
|
393
|
+
Raises:
|
|
394
|
+
ValueError: If the prompt has partial variables.
|
|
395
|
+
ValueError: If the file path is not json or yaml.
|
|
396
|
+
NotImplementedError: If the prompt type is not implemented.
|
|
397
|
+
|
|
398
|
+
Example:
|
|
399
|
+
```python
|
|
400
|
+
prompt.save(file_path="path/prompt.yaml")
|
|
401
|
+
```
|
|
402
|
+
"""
|
|
403
|
+
if self.partial_variables:
|
|
404
|
+
msg = "Cannot save prompt with partial variables."
|
|
405
|
+
raise ValueError(msg)
|
|
406
|
+
|
|
407
|
+
# Fetch dictionary to save. Preserve deprecated `dict()` overrides until
|
|
408
|
+
# `dict()` is removed.
|
|
409
|
+
prompt_dict = self._dict_for_compat()
|
|
410
|
+
if "_type" not in prompt_dict:
|
|
411
|
+
msg = f"Prompt {self} does not support saving."
|
|
412
|
+
raise NotImplementedError(msg)
|
|
413
|
+
|
|
414
|
+
# Convert file to Path object.
|
|
415
|
+
save_path = Path(file_path)
|
|
416
|
+
|
|
417
|
+
directory_path = save_path.parent
|
|
418
|
+
directory_path.mkdir(parents=True, exist_ok=True)
|
|
419
|
+
|
|
420
|
+
resolved_path = save_path.resolve()
|
|
421
|
+
if resolved_path.suffix == ".json":
|
|
422
|
+
with resolved_path.open("w", encoding="utf-8") as f:
|
|
423
|
+
json.dump(prompt_dict, f, indent=4)
|
|
424
|
+
elif resolved_path.suffix.endswith((".yaml", ".yml")):
|
|
425
|
+
with resolved_path.open("w", encoding="utf-8") as f:
|
|
426
|
+
yaml.dump(prompt_dict, f, default_flow_style=False)
|
|
427
|
+
else:
|
|
428
|
+
msg = f"{save_path} must be json or yaml"
|
|
429
|
+
raise ValueError(msg)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def _get_document_info(
|
|
433
|
+
doc: Document, prompt: BasePromptTemplate[str]
|
|
434
|
+
) -> dict[str, Any]:
|
|
435
|
+
base_info = {"page_content": doc.page_content, **doc.metadata}
|
|
436
|
+
missing_metadata = set(prompt.input_variables).difference(base_info)
|
|
437
|
+
if len(missing_metadata) > 0:
|
|
438
|
+
required_metadata = [
|
|
439
|
+
iv for iv in prompt.input_variables if iv != "page_content"
|
|
440
|
+
]
|
|
441
|
+
msg = (
|
|
442
|
+
f"Document prompt requires documents to have metadata variables: "
|
|
443
|
+
f"{required_metadata}. Received document with missing metadata: "
|
|
444
|
+
f"{list(missing_metadata)}."
|
|
445
|
+
)
|
|
446
|
+
raise ValueError(
|
|
447
|
+
create_message(message=msg, error_code=ErrorCode.INVALID_PROMPT_INPUT)
|
|
448
|
+
)
|
|
449
|
+
return {k: base_info[k] for k in prompt.input_variables}
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def format_document(doc: Document, prompt: BasePromptTemplate[str]) -> str:
|
|
453
|
+
"""Format a document into a string based on a prompt template.
|
|
454
|
+
|
|
455
|
+
First, this pulls information from the document from two sources:
|
|
456
|
+
|
|
457
|
+
1. `page_content`: This takes the information from the `document.page_content` and
|
|
458
|
+
assigns it to a variable named `page_content`.
|
|
459
|
+
2. `metadata`: This takes information from `document.metadata` and assigns it to
|
|
460
|
+
variables of the same name.
|
|
461
|
+
|
|
462
|
+
Those variables are then passed into the `prompt` to produce a formatted string.
|
|
463
|
+
|
|
464
|
+
Args:
|
|
465
|
+
doc: `Document`, the `page_content` and `metadata` will be used to create the
|
|
466
|
+
final string.
|
|
467
|
+
prompt: `BasePromptTemplate`, will be used to format the `page_content` and
|
|
468
|
+
`metadata` into the final string.
|
|
469
|
+
|
|
470
|
+
Returns:
|
|
471
|
+
String of the document formatted.
|
|
472
|
+
|
|
473
|
+
Example:
|
|
474
|
+
```python
|
|
475
|
+
from coco_core.documents import Document
|
|
476
|
+
from coco_core.prompts import PromptTemplate
|
|
477
|
+
|
|
478
|
+
doc = Document(page_content="This is a joke", metadata={"page": "1"})
|
|
479
|
+
prompt = PromptTemplate.from_template("Page {page}: {page_content}")
|
|
480
|
+
format_document(doc, prompt)
|
|
481
|
+
# -> "Page 1: This is a joke"
|
|
482
|
+
```
|
|
483
|
+
"""
|
|
484
|
+
return prompt.format(**_get_document_info(doc, prompt))
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
async def aformat_document(doc: Document, prompt: BasePromptTemplate[str]) -> str:
|
|
488
|
+
"""Async format a document into a string based on a prompt template.
|
|
489
|
+
|
|
490
|
+
First, this pulls information from the document from two sources:
|
|
491
|
+
|
|
492
|
+
1. `page_content`: This takes the information from the `document.page_content` and
|
|
493
|
+
assigns it to a variable named `page_content`.
|
|
494
|
+
2. `metadata`: This takes information from `document.metadata` and assigns it to
|
|
495
|
+
variables of the same name.
|
|
496
|
+
|
|
497
|
+
Those variables are then passed into the `prompt` to produce a formatted string.
|
|
498
|
+
|
|
499
|
+
Args:
|
|
500
|
+
doc: `Document`, the `page_content` and `metadata` will be used to create the
|
|
501
|
+
final string.
|
|
502
|
+
prompt: `BasePromptTemplate`, will be used to format the `page_content` and
|
|
503
|
+
`metadata` into the final string.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
String of the document formatted.
|
|
507
|
+
"""
|
|
508
|
+
return await prompt.aformat(**_get_document_info(doc, prompt))
|