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,74 @@
|
|
|
1
|
+
"""Document compressor."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
from coco_core.runnables import run_in_executor
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
|
|
15
|
+
from coco_core.callbacks import Callbacks
|
|
16
|
+
from coco_core.documents import Document
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseDocumentCompressor(BaseModel, ABC):
|
|
20
|
+
"""Base class for document compressors.
|
|
21
|
+
|
|
22
|
+
This abstraction is primarily used for post-processing of retrieved documents.
|
|
23
|
+
|
|
24
|
+
`Document` objects matching a given query are first retrieved.
|
|
25
|
+
|
|
26
|
+
Then the list of documents can be further processed.
|
|
27
|
+
|
|
28
|
+
For example, one could re-rank the retrieved documents using an LLM.
|
|
29
|
+
|
|
30
|
+
!!! note
|
|
31
|
+
Users should favor using a `RunnableLambda` instead of sub-classing from this
|
|
32
|
+
interface.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def compress_documents(
|
|
38
|
+
self,
|
|
39
|
+
documents: Sequence[Document],
|
|
40
|
+
query: str,
|
|
41
|
+
callbacks: Callbacks | None = None,
|
|
42
|
+
) -> Sequence[Document]:
|
|
43
|
+
"""Compress retrieved documents given the query context.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
documents: The retrieved `Document` objects.
|
|
47
|
+
query: The query context.
|
|
48
|
+
callbacks: Optional `Callbacks` to run during compression.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
The compressed documents.
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
async def acompress_documents(
|
|
56
|
+
self,
|
|
57
|
+
documents: Sequence[Document],
|
|
58
|
+
query: str,
|
|
59
|
+
callbacks: Callbacks | None = None,
|
|
60
|
+
) -> Sequence[Document]:
|
|
61
|
+
"""Async compress retrieved documents given the query context.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
documents: The retrieved `Document` objects.
|
|
65
|
+
query: The query context.
|
|
66
|
+
callbacks: Optional `Callbacks` to run during compression.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The compressed documents.
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
return await run_in_executor(
|
|
73
|
+
None, self.compress_documents, documents, query, callbacks
|
|
74
|
+
)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Document transformers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from coco_core.runnables.config import run_in_executor
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import Sequence
|
|
12
|
+
|
|
13
|
+
from coco_core.documents import Document
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseDocumentTransformer(ABC):
|
|
17
|
+
"""Abstract base class for document transformation.
|
|
18
|
+
|
|
19
|
+
A document transformation takes a sequence of `Document` objects and returns a
|
|
20
|
+
sequence of transformed `Document` objects.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
```python
|
|
24
|
+
class EmbeddingsRedundantFilter(BaseDocumentTransformer, BaseModel):
|
|
25
|
+
embeddings: Embeddings
|
|
26
|
+
similarity_fn: Callable = cosine_similarity
|
|
27
|
+
similarity_threshold: float = 0.95
|
|
28
|
+
|
|
29
|
+
class Config:
|
|
30
|
+
arbitrary_types_allowed = True
|
|
31
|
+
|
|
32
|
+
def transform_documents(
|
|
33
|
+
self, documents: Sequence[Document], **kwargs: Any
|
|
34
|
+
) -> Sequence[Document]:
|
|
35
|
+
stateful_documents = get_stateful_documents(documents)
|
|
36
|
+
embedded_documents = _get_embeddings_from_stateful_docs(
|
|
37
|
+
self.embeddings, stateful_documents
|
|
38
|
+
)
|
|
39
|
+
included_idxs = _filter_similar_embeddings(
|
|
40
|
+
embedded_documents,
|
|
41
|
+
self.similarity_fn,
|
|
42
|
+
self.similarity_threshold,
|
|
43
|
+
)
|
|
44
|
+
return [stateful_documents[i] for i in sorted(included_idxs)]
|
|
45
|
+
|
|
46
|
+
async def atransform_documents(
|
|
47
|
+
self, documents: Sequence[Document], **kwargs: Any
|
|
48
|
+
) -> Sequence[Document]:
|
|
49
|
+
raise NotImplementedError
|
|
50
|
+
```
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def transform_documents(
|
|
55
|
+
self, documents: Sequence[Document], **kwargs: Any
|
|
56
|
+
) -> Sequence[Document]:
|
|
57
|
+
"""Transform a list of documents.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
documents: A sequence of `Document` objects to be transformed.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
A sequence of transformed `Document` objects.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
async def atransform_documents(
|
|
67
|
+
self, documents: Sequence[Document], **kwargs: Any
|
|
68
|
+
) -> Sequence[Document]:
|
|
69
|
+
"""Asynchronously transform a list of documents.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
documents: A sequence of `Document` objects to be transformed.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
A sequence of transformed `Document` objects.
|
|
76
|
+
"""
|
|
77
|
+
return await run_in_executor(
|
|
78
|
+
None, self.transform_documents, documents, **kwargs
|
|
79
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Embeddings."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from coco_core._import_utils import import_attr
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from coco_core.embeddings.embeddings import Embeddings
|
|
9
|
+
from coco_core.embeddings.fake import (
|
|
10
|
+
DeterministicFakeEmbedding,
|
|
11
|
+
FakeEmbeddings,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = ("DeterministicFakeEmbedding", "Embeddings", "FakeEmbeddings")
|
|
15
|
+
|
|
16
|
+
_dynamic_imports = {
|
|
17
|
+
"Embeddings": "embeddings",
|
|
18
|
+
"DeterministicFakeEmbedding": "fake",
|
|
19
|
+
"FakeEmbeddings": "fake",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def __getattr__(attr_name: str) -> object:
|
|
24
|
+
module_name = _dynamic_imports.get(attr_name)
|
|
25
|
+
result = import_attr(attr_name, module_name, __spec__.parent)
|
|
26
|
+
globals()[attr_name] = result
|
|
27
|
+
return result
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def __dir__() -> list[str]:
|
|
31
|
+
return list(__all__)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""**Embeddings** interface."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
from coco_core.runnables.config import run_in_executor
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Embeddings(ABC):
|
|
9
|
+
"""Interface for embedding models.
|
|
10
|
+
|
|
11
|
+
This is an interface meant for implementing text embedding models.
|
|
12
|
+
|
|
13
|
+
Text embedding models are used to map text to a vector (a point in n-dimensional
|
|
14
|
+
space).
|
|
15
|
+
|
|
16
|
+
Texts that are similar will usually be mapped to points that are close to each
|
|
17
|
+
other in this space. The exact details of what's considered "similar" and how
|
|
18
|
+
"distance" is measured in this space are dependent on the specific embedding model.
|
|
19
|
+
|
|
20
|
+
This abstraction contains a method for embedding a list of documents and a method
|
|
21
|
+
for embedding a query text. The embedding of a query text is expected to be a single
|
|
22
|
+
vector, while the embedding of a list of documents is expected to be a list of
|
|
23
|
+
vectors.
|
|
24
|
+
|
|
25
|
+
Usually the query embedding is identical to the document embedding, but the
|
|
26
|
+
abstraction allows treating them independently.
|
|
27
|
+
|
|
28
|
+
In addition to the synchronous methods, this interface also provides asynchronous
|
|
29
|
+
versions of the methods.
|
|
30
|
+
|
|
31
|
+
By default, the asynchronous methods are implemented using the synchronous methods;
|
|
32
|
+
however, implementations may choose to override the asynchronous methods with
|
|
33
|
+
an async native implementation for performance reasons.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def embed_documents(self, texts: list[str]) -> list[list[float]]:
|
|
38
|
+
"""Embed search docs.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
texts: List of text to embed.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
List of embeddings.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
@abstractmethod
|
|
48
|
+
def embed_query(self, text: str) -> list[float]:
|
|
49
|
+
"""Embed query text.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
text: Text to embed.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Embedding.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
async def aembed_documents(self, texts: list[str]) -> list[list[float]]:
|
|
59
|
+
"""Asynchronous Embed search docs.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
texts: List of text to embed.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
List of embeddings.
|
|
66
|
+
"""
|
|
67
|
+
return await run_in_executor(None, self.embed_documents, texts)
|
|
68
|
+
|
|
69
|
+
async def aembed_query(self, text: str) -> list[float]:
|
|
70
|
+
"""Asynchronous Embed query text.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
text: Text to embed.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Embedding.
|
|
77
|
+
"""
|
|
78
|
+
return await run_in_executor(None, self.embed_query, text)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Module contains a few fake embedding models for testing purposes."""
|
|
2
|
+
|
|
3
|
+
# Please do not add additional fake embedding model implementations here.
|
|
4
|
+
import contextlib
|
|
5
|
+
import hashlib
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from typing_extensions import override
|
|
9
|
+
|
|
10
|
+
from coco_core.embeddings import Embeddings
|
|
11
|
+
|
|
12
|
+
with contextlib.suppress(ImportError):
|
|
13
|
+
import numpy as np
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FakeEmbeddings(Embeddings, BaseModel):
|
|
17
|
+
"""Fake embedding model for unit testing purposes.
|
|
18
|
+
|
|
19
|
+
This embedding model creates embeddings by sampling from a normal distribution.
|
|
20
|
+
|
|
21
|
+
!!! danger "Toy model"
|
|
22
|
+
Do not use this outside of testing, as it is not a real embedding model.
|
|
23
|
+
|
|
24
|
+
Instantiate:
|
|
25
|
+
```python
|
|
26
|
+
from coco_core.embeddings import FakeEmbeddings
|
|
27
|
+
|
|
28
|
+
embed = FakeEmbeddings(size=100)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Embed single text:
|
|
32
|
+
```python
|
|
33
|
+
input_text = "The meaning of life is 42"
|
|
34
|
+
vector = embed.embed_query(input_text)
|
|
35
|
+
print(vector[:3])
|
|
36
|
+
```
|
|
37
|
+
```python
|
|
38
|
+
[-0.700234640213188, -0.581266257710429, -1.1328482266445354]
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Embed multiple texts:
|
|
42
|
+
```python
|
|
43
|
+
input_texts = ["Document 1...", "Document 2..."]
|
|
44
|
+
vectors = embed.embed_documents(input_texts)
|
|
45
|
+
print(len(vectors))
|
|
46
|
+
# The first 3 coordinates for the first vector
|
|
47
|
+
print(vectors[0][:3])
|
|
48
|
+
```
|
|
49
|
+
```python
|
|
50
|
+
2
|
|
51
|
+
[-0.5670477847544458, -0.31403828652395727, -0.5840547508955257]
|
|
52
|
+
```
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
size: int
|
|
56
|
+
"""The size of the embedding vector."""
|
|
57
|
+
|
|
58
|
+
def _get_embedding(self) -> list[float]:
|
|
59
|
+
return list(np.random.default_rng().normal(size=self.size))
|
|
60
|
+
|
|
61
|
+
@override
|
|
62
|
+
def embed_documents(self, texts: list[str]) -> list[list[float]]:
|
|
63
|
+
return [self._get_embedding() for _ in texts]
|
|
64
|
+
|
|
65
|
+
@override
|
|
66
|
+
def embed_query(self, text: str) -> list[float]:
|
|
67
|
+
return self._get_embedding()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class DeterministicFakeEmbedding(Embeddings, BaseModel):
|
|
71
|
+
"""Deterministic fake embedding model for unit testing purposes.
|
|
72
|
+
|
|
73
|
+
This embedding model creates embeddings by sampling from a normal distribution
|
|
74
|
+
with a seed based on the hash of the text.
|
|
75
|
+
|
|
76
|
+
!!! danger "Toy model"
|
|
77
|
+
Do not use this outside of testing, as it is not a real embedding model.
|
|
78
|
+
|
|
79
|
+
Instantiate:
|
|
80
|
+
```python
|
|
81
|
+
from coco_core.embeddings import DeterministicFakeEmbedding
|
|
82
|
+
|
|
83
|
+
embed = DeterministicFakeEmbedding(size=100)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Embed single text:
|
|
87
|
+
```python
|
|
88
|
+
input_text = "The meaning of life is 42"
|
|
89
|
+
vector = embed.embed_query(input_text)
|
|
90
|
+
print(vector[:3])
|
|
91
|
+
```
|
|
92
|
+
```python
|
|
93
|
+
[-0.700234640213188, -0.581266257710429, -1.1328482266445354]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Embed multiple texts:
|
|
97
|
+
```python
|
|
98
|
+
input_texts = ["Document 1...", "Document 2..."]
|
|
99
|
+
vectors = embed.embed_documents(input_texts)
|
|
100
|
+
print(len(vectors))
|
|
101
|
+
# The first 3 coordinates for the first vector
|
|
102
|
+
print(vectors[0][:3])
|
|
103
|
+
```
|
|
104
|
+
```python
|
|
105
|
+
2
|
|
106
|
+
[-0.5670477847544458, -0.31403828652395727, -0.5840547508955257]
|
|
107
|
+
```
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
size: int
|
|
111
|
+
"""The size of the embedding vector."""
|
|
112
|
+
|
|
113
|
+
def _get_embedding(self, seed: int) -> list[float]:
|
|
114
|
+
# set the seed for the random generator
|
|
115
|
+
rng = np.random.default_rng(seed)
|
|
116
|
+
return list(rng.normal(size=self.size))
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def _get_seed(text: str) -> int:
|
|
120
|
+
"""Get a seed for the random generator, using the hash of the text."""
|
|
121
|
+
return int(hashlib.sha256(text.encode("utf-8")).hexdigest(), 16) % 10**8
|
|
122
|
+
|
|
123
|
+
@override
|
|
124
|
+
def embed_documents(self, texts: list[str]) -> list[list[float]]:
|
|
125
|
+
return [self._get_embedding(seed=self._get_seed(_)) for _ in texts]
|
|
126
|
+
|
|
127
|
+
@override
|
|
128
|
+
def embed_query(self, text: str) -> list[float]:
|
|
129
|
+
return self._get_embedding(seed=self._get_seed(text))
|
coco_core/env.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Utilities for getting information about the runtime environment."""
|
|
2
|
+
|
|
3
|
+
import platform
|
|
4
|
+
from functools import lru_cache
|
|
5
|
+
|
|
6
|
+
from coco_core import __version__
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@lru_cache(maxsize=1)
|
|
10
|
+
def get_runtime_environment() -> dict[str, str]:
|
|
11
|
+
"""Get information about the Coco runtime environment.
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
A dictionary with information about the runtime environment.
|
|
15
|
+
"""
|
|
16
|
+
return {
|
|
17
|
+
"library_version": __version__,
|
|
18
|
+
"library": "trustcoco-core",
|
|
19
|
+
"platform": platform.platform(),
|
|
20
|
+
"runtime": "python",
|
|
21
|
+
"runtime_version": platform.python_version(),
|
|
22
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Example selectors.
|
|
2
|
+
|
|
3
|
+
**Example selector** implements logic for selecting examples to include them in prompts.
|
|
4
|
+
This allows us to select examples that are most relevant to the input.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from coco_core._import_utils import import_attr
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from coco_core.example_selectors.base import BaseExampleSelector
|
|
13
|
+
from coco_core.example_selectors.length_based import (
|
|
14
|
+
LengthBasedExampleSelector,
|
|
15
|
+
)
|
|
16
|
+
from coco_core.example_selectors.semantic_similarity import (
|
|
17
|
+
MaxMarginalRelevanceExampleSelector,
|
|
18
|
+
SemanticSimilarityExampleSelector,
|
|
19
|
+
sorted_values,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
__all__ = (
|
|
23
|
+
"BaseExampleSelector",
|
|
24
|
+
"LengthBasedExampleSelector",
|
|
25
|
+
"MaxMarginalRelevanceExampleSelector",
|
|
26
|
+
"SemanticSimilarityExampleSelector",
|
|
27
|
+
"sorted_values",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
_dynamic_imports = {
|
|
31
|
+
"BaseExampleSelector": "base",
|
|
32
|
+
"LengthBasedExampleSelector": "length_based",
|
|
33
|
+
"MaxMarginalRelevanceExampleSelector": "semantic_similarity",
|
|
34
|
+
"SemanticSimilarityExampleSelector": "semantic_similarity",
|
|
35
|
+
"sorted_values": "semantic_similarity",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __getattr__(attr_name: str) -> object:
|
|
40
|
+
module_name = _dynamic_imports.get(attr_name)
|
|
41
|
+
result = import_attr(attr_name, module_name, __spec__.parent)
|
|
42
|
+
globals()[attr_name] = result
|
|
43
|
+
return result
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def __dir__() -> list[str]:
|
|
47
|
+
return list(__all__)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Interface for selecting examples to include in prompts."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from coco_core.runnables import run_in_executor
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BaseExampleSelector(ABC):
|
|
10
|
+
"""Interface for selecting examples to include in prompts."""
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def add_example(self, example: dict[str, str]) -> Any:
|
|
14
|
+
"""Add new example to store.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
example: A dictionary with keys as input variables
|
|
18
|
+
and values as their values.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Any return value.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
async def aadd_example(self, example: dict[str, str]) -> Any:
|
|
25
|
+
"""Async add new example to store.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
example: A dictionary with keys as input variables
|
|
29
|
+
and values as their values.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Any return value.
|
|
33
|
+
"""
|
|
34
|
+
return await run_in_executor(None, self.add_example, example)
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def select_examples(self, input_variables: dict[str, str]) -> list[dict[str, Any]]:
|
|
38
|
+
"""Select which examples to use based on the inputs.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
input_variables: A dictionary with keys as input variables
|
|
42
|
+
and values as their values.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
A list of examples.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
async def aselect_examples(
|
|
49
|
+
self, input_variables: dict[str, str]
|
|
50
|
+
) -> list[dict[str, Any]]:
|
|
51
|
+
"""Async select which examples to use based on the inputs.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
input_variables: A dictionary with keys as input variables
|
|
55
|
+
and values as their values.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
A list of examples.
|
|
59
|
+
"""
|
|
60
|
+
return await run_in_executor(None, self.select_examples, input_variables)
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Select examples based on length."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field, model_validator
|
|
8
|
+
from typing_extensions import Self
|
|
9
|
+
|
|
10
|
+
from coco_core.example_selectors.base import BaseExampleSelector
|
|
11
|
+
from coco_core.prompts.prompt import PromptTemplate
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _get_length_based(text: str) -> int:
|
|
15
|
+
return len(re.split(r"\n| ", text))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LengthBasedExampleSelector(BaseExampleSelector, BaseModel):
|
|
19
|
+
r"""Select examples based on length.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
```python
|
|
23
|
+
from coco_core.example_selectors import LengthBasedExampleSelector
|
|
24
|
+
from coco_core.prompts import PromptTemplate
|
|
25
|
+
|
|
26
|
+
# Define examples
|
|
27
|
+
examples = [
|
|
28
|
+
{"input": "happy", "output": "sad"},
|
|
29
|
+
{"input": "tall", "output": "short"},
|
|
30
|
+
{"input": "fast", "output": "slow"},
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
# Create prompt template
|
|
34
|
+
example_prompt = PromptTemplate(
|
|
35
|
+
input_variables=["input", "output"],
|
|
36
|
+
template="Input: {input}\nOutput: {output}",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Create selector with max length constraint
|
|
40
|
+
selector = LengthBasedExampleSelector(
|
|
41
|
+
examples=examples,
|
|
42
|
+
example_prompt=example_prompt,
|
|
43
|
+
max_length=50, # Maximum prompt length
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Select examples for a new input
|
|
47
|
+
selected = selector.select_examples({"input": "large", "output": "tiny"})
|
|
48
|
+
# Returns examples that fit within max_length constraint
|
|
49
|
+
```
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
examples: list[dict[str, Any]]
|
|
53
|
+
"""A list of the examples that the prompt template expects."""
|
|
54
|
+
|
|
55
|
+
example_prompt: PromptTemplate
|
|
56
|
+
"""Prompt template used to format the examples."""
|
|
57
|
+
|
|
58
|
+
get_text_length: Callable[[str], int] = _get_length_based
|
|
59
|
+
"""Function to measure prompt length. Defaults to word count."""
|
|
60
|
+
|
|
61
|
+
max_length: int = 2048
|
|
62
|
+
"""Max length for the prompt, beyond which examples are cut."""
|
|
63
|
+
|
|
64
|
+
example_text_lengths: list[int] = Field(default_factory=list)
|
|
65
|
+
"""Length of each example."""
|
|
66
|
+
|
|
67
|
+
def add_example(self, example: dict[str, str]) -> None:
|
|
68
|
+
"""Add new example to list.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
example: A dictionary with keys as input variables
|
|
72
|
+
and values as their values.
|
|
73
|
+
"""
|
|
74
|
+
self.examples.append(example)
|
|
75
|
+
string_example = self.example_prompt.format(**example)
|
|
76
|
+
self.example_text_lengths.append(self.get_text_length(string_example))
|
|
77
|
+
|
|
78
|
+
async def aadd_example(self, example: dict[str, str]) -> None:
|
|
79
|
+
"""Async add new example to list.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
example: A dictionary with keys as input variables
|
|
83
|
+
and values as their values.
|
|
84
|
+
"""
|
|
85
|
+
self.add_example(example)
|
|
86
|
+
|
|
87
|
+
@model_validator(mode="after")
|
|
88
|
+
def post_init(self) -> Self:
|
|
89
|
+
"""Validate that the examples are formatted correctly."""
|
|
90
|
+
if self.example_text_lengths:
|
|
91
|
+
return self
|
|
92
|
+
string_examples = [self.example_prompt.format(**eg) for eg in self.examples]
|
|
93
|
+
self.example_text_lengths = [self.get_text_length(eg) for eg in string_examples]
|
|
94
|
+
return self
|
|
95
|
+
|
|
96
|
+
def select_examples(self, input_variables: dict[str, str]) -> list[dict[str, Any]]:
|
|
97
|
+
"""Select which examples to use based on the input lengths.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
input_variables: A dictionary with keys as input variables
|
|
101
|
+
and values as their values.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
A list of examples to include in the prompt.
|
|
105
|
+
"""
|
|
106
|
+
inputs = " ".join(input_variables.values())
|
|
107
|
+
remaining_length = self.max_length - self.get_text_length(inputs)
|
|
108
|
+
i = 0
|
|
109
|
+
examples = []
|
|
110
|
+
while remaining_length > 0 and i < len(self.examples):
|
|
111
|
+
new_length = remaining_length - self.example_text_lengths[i]
|
|
112
|
+
if new_length < 0:
|
|
113
|
+
break
|
|
114
|
+
examples.append(self.examples[i])
|
|
115
|
+
remaining_length = new_length
|
|
116
|
+
i += 1
|
|
117
|
+
return examples
|
|
118
|
+
|
|
119
|
+
async def aselect_examples(
|
|
120
|
+
self, input_variables: dict[str, str]
|
|
121
|
+
) -> list[dict[str, Any]]:
|
|
122
|
+
"""Async select which examples to use based on the input lengths.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
input_variables: A dictionary with keys as input variables
|
|
126
|
+
and values as their values.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
A list of examples to include in the prompt.
|
|
130
|
+
"""
|
|
131
|
+
return self.select_examples(input_variables)
|