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,19 @@
|
|
|
1
|
+
"""**Chat Sessions** are a collection of messages and function calls."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from typing import Any, TypedDict
|
|
5
|
+
|
|
6
|
+
from coco_core.messages import BaseMessage
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ChatSession(TypedDict, total=False):
|
|
10
|
+
"""Chat Session.
|
|
11
|
+
|
|
12
|
+
Chat Session represents a single conversation, channel, or other group of messages.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
messages: Sequence[BaseMessage]
|
|
16
|
+
"""A sequence of the Coco chat messages loaded from the source."""
|
|
17
|
+
|
|
18
|
+
functions: Sequence[dict[str, Any]]
|
|
19
|
+
"""A sequence of the function calling specs for the messages."""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Cross Encoder interface."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseCrossEncoder(ABC):
|
|
7
|
+
"""Interface for cross encoder models."""
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def score(self, text_pairs: list[tuple[str, str]]) -> list[float]:
|
|
11
|
+
"""Score pairs' similarity.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
text_pairs: List of pairs of texts.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
List of scores.
|
|
18
|
+
"""
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Document loaders."""
|
|
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.document_loaders.base import BaseBlobParser, BaseLoader
|
|
9
|
+
from coco_core.document_loaders.blob_loaders import Blob, BlobLoader, PathLike
|
|
10
|
+
|
|
11
|
+
__all__ = (
|
|
12
|
+
"BaseBlobParser",
|
|
13
|
+
"BaseLoader",
|
|
14
|
+
"Blob",
|
|
15
|
+
"BlobLoader",
|
|
16
|
+
"PathLike",
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
_dynamic_imports = {
|
|
20
|
+
"BaseBlobParser": "base",
|
|
21
|
+
"BaseLoader": "base",
|
|
22
|
+
"Blob": "blob_loaders",
|
|
23
|
+
"BlobLoader": "blob_loaders",
|
|
24
|
+
"PathLike": "blob_loaders",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def __getattr__(attr_name: str) -> object:
|
|
29
|
+
module_name = _dynamic_imports.get(attr_name)
|
|
30
|
+
result = import_attr(attr_name, module_name, __spec__.parent)
|
|
31
|
+
globals()[attr_name] = result
|
|
32
|
+
return result
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def __dir__() -> list[str]:
|
|
36
|
+
return list(__all__)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Abstract interface for document loader implementations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from coco_core.runnables import run_in_executor
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import AsyncIterator, Iterator
|
|
12
|
+
|
|
13
|
+
from coco_text_splitters import TextSplitter
|
|
14
|
+
|
|
15
|
+
from coco_core.documents import Document
|
|
16
|
+
from coco_core.documents.base import Blob
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
from coco_text_splitters import RecursiveCharacterTextSplitter
|
|
20
|
+
|
|
21
|
+
_HAS_TEXT_SPLITTERS = True
|
|
22
|
+
except ImportError:
|
|
23
|
+
_HAS_TEXT_SPLITTERS = False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BaseLoader(ABC): # noqa: B024
|
|
27
|
+
"""Interface for document loader.
|
|
28
|
+
|
|
29
|
+
Implementations should implement the lazy-loading method using generators to avoid
|
|
30
|
+
loading all documents into memory at once.
|
|
31
|
+
|
|
32
|
+
`load` is provided just for user convenience and should not be overridden.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
# Sub-classes should not implement this method directly. Instead, they
|
|
36
|
+
# should implement the lazy load method.
|
|
37
|
+
def load(self) -> list[Document]:
|
|
38
|
+
"""Load data into `Document` objects.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
The documents.
|
|
42
|
+
"""
|
|
43
|
+
return list(self.lazy_load())
|
|
44
|
+
|
|
45
|
+
async def aload(self) -> list[Document]:
|
|
46
|
+
"""Load data into `Document` objects.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
The documents.
|
|
50
|
+
"""
|
|
51
|
+
return [document async for document in self.alazy_load()]
|
|
52
|
+
|
|
53
|
+
def load_and_split(
|
|
54
|
+
self, text_splitter: TextSplitter | None = None
|
|
55
|
+
) -> list[Document]:
|
|
56
|
+
"""Load `Document` and split into chunks. Chunks are returned as `Document`.
|
|
57
|
+
|
|
58
|
+
!!! danger
|
|
59
|
+
|
|
60
|
+
Do not override this method. It should be considered to be deprecated!
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
text_splitter: `TextSplitter` instance to use for splitting documents.
|
|
64
|
+
|
|
65
|
+
Defaults to `RecursiveCharacterTextSplitter`.
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
ImportError: If `trustcoco-text-splitters` is not installed and no
|
|
69
|
+
`text_splitter` is provided.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
List of `Document` objects.
|
|
73
|
+
"""
|
|
74
|
+
if text_splitter is None:
|
|
75
|
+
if not _HAS_TEXT_SPLITTERS:
|
|
76
|
+
msg = (
|
|
77
|
+
"Unable to import from coco_text_splitters. Please specify "
|
|
78
|
+
"text_splitter or install coco_text_splitters with "
|
|
79
|
+
"`pip install -U trustcoco-text-splitters`."
|
|
80
|
+
)
|
|
81
|
+
raise ImportError(msg)
|
|
82
|
+
|
|
83
|
+
text_splitter_: TextSplitter = RecursiveCharacterTextSplitter()
|
|
84
|
+
else:
|
|
85
|
+
text_splitter_ = text_splitter
|
|
86
|
+
docs = self.load()
|
|
87
|
+
return text_splitter_.split_documents(docs)
|
|
88
|
+
|
|
89
|
+
# Attention: This method will be upgraded into an abstractmethod once it's
|
|
90
|
+
# implemented in all the existing subclasses.
|
|
91
|
+
def lazy_load(self) -> Iterator[Document]:
|
|
92
|
+
"""A lazy loader for `Document`.
|
|
93
|
+
|
|
94
|
+
Yields:
|
|
95
|
+
The `Document` objects.
|
|
96
|
+
"""
|
|
97
|
+
if type(self).load != BaseLoader.load:
|
|
98
|
+
return iter(self.load())
|
|
99
|
+
msg = f"{self.__class__.__name__} does not implement lazy_load()"
|
|
100
|
+
raise NotImplementedError(msg)
|
|
101
|
+
|
|
102
|
+
async def alazy_load(self) -> AsyncIterator[Document]:
|
|
103
|
+
"""A lazy loader for `Document`.
|
|
104
|
+
|
|
105
|
+
Yields:
|
|
106
|
+
The `Document` objects.
|
|
107
|
+
"""
|
|
108
|
+
iterator = await run_in_executor(None, self.lazy_load)
|
|
109
|
+
done = object()
|
|
110
|
+
while True:
|
|
111
|
+
doc = await run_in_executor(None, next, iterator, done)
|
|
112
|
+
if doc is done:
|
|
113
|
+
break
|
|
114
|
+
yield doc # type: ignore[misc]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class BaseBlobParser(ABC):
|
|
118
|
+
"""Abstract interface for blob parsers.
|
|
119
|
+
|
|
120
|
+
A blob parser provides a way to parse raw data stored in a blob into one or more
|
|
121
|
+
`Document` objects.
|
|
122
|
+
|
|
123
|
+
The parser can be composed with blob loaders, making it easy to reuse a parser
|
|
124
|
+
independent of how the blob was originally loaded.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
@abstractmethod
|
|
128
|
+
def lazy_parse(self, blob: Blob) -> Iterator[Document]:
|
|
129
|
+
"""Lazy parsing interface.
|
|
130
|
+
|
|
131
|
+
Subclasses are required to implement this method.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
blob: `Blob` instance
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Generator of `Document` objects
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
def parse(self, blob: Blob) -> list[Document]:
|
|
141
|
+
"""Eagerly parse the blob into a `Document` or list of `Document` objects.
|
|
142
|
+
|
|
143
|
+
This is a convenience method for interactive development environment.
|
|
144
|
+
|
|
145
|
+
Production applications should favor the `lazy_parse` method instead.
|
|
146
|
+
|
|
147
|
+
Subclasses should generally not over-ride this parse method.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
blob: `Blob` instance
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
List of `Document` objects
|
|
154
|
+
"""
|
|
155
|
+
return list(self.lazy_parse(blob))
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Schema for Blobs and Blob Loaders.
|
|
2
|
+
|
|
3
|
+
The goal is to facilitate decoupling of content loading from content parsing code. In
|
|
4
|
+
addition, content loading code should provide a lazy loading interface by default.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
# Re-export Blob and PathLike for backwards compatibility
|
|
13
|
+
from coco_core.documents.base import Blob, PathLike
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Iterator
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BlobLoader(ABC):
|
|
20
|
+
"""Abstract interface for blob loaders implementation.
|
|
21
|
+
|
|
22
|
+
Implementer should be able to load raw content from a storage system according to
|
|
23
|
+
some criteria and return the raw content lazily as a stream of blobs.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def yield_blobs(
|
|
28
|
+
self,
|
|
29
|
+
) -> Iterator[Blob]:
|
|
30
|
+
"""A lazy loader for raw data represented by Coco's `Blob` object.
|
|
31
|
+
|
|
32
|
+
Yields:
|
|
33
|
+
`Blob` objects.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Re-export Blob and Pathlike for backwards compatibility
|
|
38
|
+
__all__ = ["Blob", "BlobLoader", "PathLike"]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Documents module for data retrieval and processing workflows.
|
|
2
|
+
|
|
3
|
+
This module provides core abstractions for handling data in retrieval-augmented
|
|
4
|
+
generation (RAG) pipelines, vector stores, and document processing workflows.
|
|
5
|
+
|
|
6
|
+
!!! warning "Documents vs. message content"
|
|
7
|
+
|
|
8
|
+
This module is distinct from `coco_core.messages.content`, which provides
|
|
9
|
+
multimodal content blocks for **LLM chat I/O** (text, images, audio, etc. within
|
|
10
|
+
messages).
|
|
11
|
+
|
|
12
|
+
**Key distinction:**
|
|
13
|
+
|
|
14
|
+
- **Documents** (this module): For **data retrieval and processing workflows**
|
|
15
|
+
- Vector stores, retrievers, RAG pipelines
|
|
16
|
+
- Text chunking, embedding, and semantic search
|
|
17
|
+
- Example: Chunks of a PDF stored in a vector database
|
|
18
|
+
|
|
19
|
+
- **Content Blocks** (`messages.content`): For **LLM conversational I/O**
|
|
20
|
+
- Multimodal message content sent to/from models
|
|
21
|
+
- Tool calls, reasoning, citations within chat
|
|
22
|
+
- Example: An image sent to a vision model in a chat message (via
|
|
23
|
+
[`ImageContentBlock`][coco.messages.ImageContentBlock])
|
|
24
|
+
|
|
25
|
+
While both can represent similar data types (text, files), they serve different
|
|
26
|
+
architectural purposes in Coco applications.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from typing import TYPE_CHECKING
|
|
30
|
+
|
|
31
|
+
from coco_core._import_utils import import_attr
|
|
32
|
+
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
from coco_core.documents.base import Document
|
|
35
|
+
from coco_core.documents.compressor import BaseDocumentCompressor
|
|
36
|
+
from coco_core.documents.transformers import BaseDocumentTransformer
|
|
37
|
+
|
|
38
|
+
__all__ = ("BaseDocumentCompressor", "BaseDocumentTransformer", "Document")
|
|
39
|
+
|
|
40
|
+
_dynamic_imports = {
|
|
41
|
+
"Document": "base",
|
|
42
|
+
"BaseDocumentCompressor": "compressor",
|
|
43
|
+
"BaseDocumentTransformer": "transformers",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def __getattr__(attr_name: str) -> object:
|
|
48
|
+
module_name = _dynamic_imports.get(attr_name)
|
|
49
|
+
result = import_attr(attr_name, module_name, __spec__.parent)
|
|
50
|
+
globals()[attr_name] = result
|
|
51
|
+
return result
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def __dir__() -> list[str]:
|
|
55
|
+
return list(__all__)
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
"""Base classes for media and documents.
|
|
2
|
+
|
|
3
|
+
This module contains core abstractions for **data retrieval and processing workflows**:
|
|
4
|
+
|
|
5
|
+
- `BaseMedia`: Base class providing `id` and `metadata` fields
|
|
6
|
+
- `Blob`: Raw data loading (files, binary data) - used by document loaders
|
|
7
|
+
- `Document`: Text content for retrieval (RAG, vector stores, semantic search)
|
|
8
|
+
|
|
9
|
+
!!! note "Not for LLM chat messages"
|
|
10
|
+
|
|
11
|
+
These classes are for data processing pipelines, not LLM I/O. For multimodal
|
|
12
|
+
content in chat messages (images, audio in conversations), see
|
|
13
|
+
`coco.messages` content blocks instead.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import contextlib
|
|
19
|
+
import mimetypes
|
|
20
|
+
from io import BufferedReader, BytesIO
|
|
21
|
+
from pathlib import Path, PurePath
|
|
22
|
+
from typing import TYPE_CHECKING, Any, Literal, cast
|
|
23
|
+
|
|
24
|
+
from pydantic import ConfigDict, Field, model_validator
|
|
25
|
+
|
|
26
|
+
from coco_core.load.serializable import Serializable
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from collections.abc import Generator
|
|
30
|
+
|
|
31
|
+
PathLike = str | PurePath
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BaseMedia(Serializable):
|
|
35
|
+
"""Base class for content used in retrieval and data processing workflows.
|
|
36
|
+
|
|
37
|
+
Provides common fields for content that needs to be stored, indexed, or searched.
|
|
38
|
+
|
|
39
|
+
!!! note
|
|
40
|
+
|
|
41
|
+
For multimodal content in **chat messages** (images, audio sent to/from LLMs),
|
|
42
|
+
use `coco.messages` content blocks instead.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
# The ID field is optional at the moment.
|
|
46
|
+
# It will likely become required in a future major release after
|
|
47
|
+
# it has been adopted by enough VectorStore implementations.
|
|
48
|
+
id: str | None = Field(default=None, coerce_numbers_to_str=True)
|
|
49
|
+
"""An optional identifier for the document.
|
|
50
|
+
|
|
51
|
+
Ideally this should be unique across the document collection and formatted
|
|
52
|
+
as a UUID, but this will not be enforced.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
metadata: dict[Any, Any] = Field(default_factory=dict)
|
|
56
|
+
"""Arbitrary metadata associated with the content."""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Blob(BaseMedia):
|
|
60
|
+
"""Raw data abstraction for document loading and file processing.
|
|
61
|
+
|
|
62
|
+
Represents raw bytes or text, either in-memory or by file reference. Used
|
|
63
|
+
primarily by document loaders to decouple data loading from parsing.
|
|
64
|
+
|
|
65
|
+
Inspired by [Mozilla's `Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
|
66
|
+
|
|
67
|
+
???+ example "Initialize a blob from in-memory data"
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from coco_core.documents import Blob
|
|
71
|
+
|
|
72
|
+
blob = Blob.from_data("Hello, world!")
|
|
73
|
+
|
|
74
|
+
# Read the blob as a string
|
|
75
|
+
print(blob.as_string())
|
|
76
|
+
|
|
77
|
+
# Read the blob as bytes
|
|
78
|
+
print(blob.as_bytes())
|
|
79
|
+
|
|
80
|
+
# Read the blob as a byte stream
|
|
81
|
+
with blob.as_bytes_io() as f:
|
|
82
|
+
print(f.read())
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
??? example "Load from memory and specify MIME type and metadata"
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from coco_core.documents import Blob
|
|
89
|
+
|
|
90
|
+
blob = Blob.from_data(
|
|
91
|
+
data="Hello, world!",
|
|
92
|
+
mime_type="text/plain",
|
|
93
|
+
metadata={"source": "https://example.com"},
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
??? example "Load the blob from a file"
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from coco_core.documents import Blob
|
|
101
|
+
|
|
102
|
+
blob = Blob.from_path("path/to/file.txt")
|
|
103
|
+
|
|
104
|
+
# Read the blob as a string
|
|
105
|
+
print(blob.as_string())
|
|
106
|
+
|
|
107
|
+
# Read the blob as bytes
|
|
108
|
+
print(blob.as_bytes())
|
|
109
|
+
|
|
110
|
+
# Read the blob as a byte stream
|
|
111
|
+
with blob.as_bytes_io() as f:
|
|
112
|
+
print(f.read())
|
|
113
|
+
```
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
data: bytes | str | None = None
|
|
117
|
+
"""Raw data associated with the `Blob`."""
|
|
118
|
+
|
|
119
|
+
mimetype: str | None = None
|
|
120
|
+
"""MIME type, not to be confused with a file extension."""
|
|
121
|
+
|
|
122
|
+
encoding: str = "utf-8"
|
|
123
|
+
"""Encoding to use if decoding the bytes into a string.
|
|
124
|
+
|
|
125
|
+
Uses `utf-8` as default encoding if decoding to string.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
path: PathLike | None = None
|
|
129
|
+
"""Location where the original content was found."""
|
|
130
|
+
|
|
131
|
+
model_config = ConfigDict(
|
|
132
|
+
arbitrary_types_allowed=True,
|
|
133
|
+
frozen=True,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def source(self) -> str | None:
|
|
138
|
+
"""The source location of the blob as string if known otherwise none.
|
|
139
|
+
|
|
140
|
+
If a path is associated with the `Blob`, it will default to the path location.
|
|
141
|
+
|
|
142
|
+
Unless explicitly set via a metadata field called `'source'`, in which
|
|
143
|
+
case that value will be used instead.
|
|
144
|
+
"""
|
|
145
|
+
if self.metadata and "source" in self.metadata:
|
|
146
|
+
return cast("str | None", self.metadata["source"])
|
|
147
|
+
return str(self.path) if self.path else None
|
|
148
|
+
|
|
149
|
+
@model_validator(mode="before")
|
|
150
|
+
@classmethod
|
|
151
|
+
def check_blob_is_valid(cls, values: dict[str, Any]) -> Any:
|
|
152
|
+
"""Verify that either data or path is provided."""
|
|
153
|
+
if "data" not in values and "path" not in values:
|
|
154
|
+
msg = "Either data or path must be provided"
|
|
155
|
+
raise ValueError(msg)
|
|
156
|
+
return values
|
|
157
|
+
|
|
158
|
+
def as_string(self) -> str:
|
|
159
|
+
"""Read data as a string.
|
|
160
|
+
|
|
161
|
+
Raises:
|
|
162
|
+
ValueError: If the blob cannot be represented as a string.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
The data as a string.
|
|
166
|
+
"""
|
|
167
|
+
if self.data is None and self.path:
|
|
168
|
+
return Path(self.path).read_text(encoding=self.encoding)
|
|
169
|
+
if isinstance(self.data, bytes):
|
|
170
|
+
return self.data.decode(self.encoding)
|
|
171
|
+
if isinstance(self.data, str):
|
|
172
|
+
return self.data
|
|
173
|
+
msg = f"Unable to get string for blob {self}"
|
|
174
|
+
raise ValueError(msg)
|
|
175
|
+
|
|
176
|
+
def as_bytes(self) -> bytes:
|
|
177
|
+
"""Read data as bytes.
|
|
178
|
+
|
|
179
|
+
Raises:
|
|
180
|
+
ValueError: If the blob cannot be represented as bytes.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
The data as bytes.
|
|
184
|
+
"""
|
|
185
|
+
if isinstance(self.data, bytes):
|
|
186
|
+
return self.data
|
|
187
|
+
if isinstance(self.data, str):
|
|
188
|
+
return self.data.encode(self.encoding)
|
|
189
|
+
if self.data is None and self.path:
|
|
190
|
+
return Path(self.path).read_bytes()
|
|
191
|
+
msg = f"Unable to get bytes for blob {self}"
|
|
192
|
+
raise ValueError(msg)
|
|
193
|
+
|
|
194
|
+
@contextlib.contextmanager
|
|
195
|
+
def as_bytes_io(self) -> Generator[BytesIO | BufferedReader, None, None]:
|
|
196
|
+
"""Read data as a byte stream.
|
|
197
|
+
|
|
198
|
+
Raises:
|
|
199
|
+
NotImplementedError: If the blob cannot be represented as a byte stream.
|
|
200
|
+
|
|
201
|
+
Yields:
|
|
202
|
+
The data as a byte stream.
|
|
203
|
+
"""
|
|
204
|
+
if isinstance(self.data, bytes):
|
|
205
|
+
yield BytesIO(self.data)
|
|
206
|
+
elif self.data is None and self.path:
|
|
207
|
+
with Path(self.path).open("rb") as f:
|
|
208
|
+
yield f
|
|
209
|
+
else:
|
|
210
|
+
msg = f"Unable to convert blob {self}"
|
|
211
|
+
raise NotImplementedError(msg)
|
|
212
|
+
|
|
213
|
+
@classmethod
|
|
214
|
+
def from_path(
|
|
215
|
+
cls,
|
|
216
|
+
path: PathLike,
|
|
217
|
+
*,
|
|
218
|
+
encoding: str = "utf-8",
|
|
219
|
+
mime_type: str | None = None,
|
|
220
|
+
guess_type: bool = True,
|
|
221
|
+
metadata: dict[Any, Any] | None = None,
|
|
222
|
+
) -> Blob:
|
|
223
|
+
"""Load the blob from a path like object.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
path: Path-like object to file to be read
|
|
227
|
+
encoding: Encoding to use if decoding the bytes into a string
|
|
228
|
+
mime_type: If provided, will be set as the MIME type of the data
|
|
229
|
+
guess_type: If `True`, the MIME type will be guessed from the file
|
|
230
|
+
extension, if a MIME type was not provided
|
|
231
|
+
metadata: Metadata to associate with the `Blob`
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
`Blob` instance
|
|
235
|
+
"""
|
|
236
|
+
if mime_type is None and guess_type:
|
|
237
|
+
mimetype = mimetypes.guess_type(path)[0]
|
|
238
|
+
else:
|
|
239
|
+
mimetype = mime_type
|
|
240
|
+
# We do not load the data immediately, instead we treat the blob as a
|
|
241
|
+
# reference to the underlying data.
|
|
242
|
+
return cls(
|
|
243
|
+
data=None,
|
|
244
|
+
mimetype=mimetype,
|
|
245
|
+
encoding=encoding,
|
|
246
|
+
path=path,
|
|
247
|
+
metadata=metadata if metadata is not None else {},
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
@classmethod
|
|
251
|
+
def from_data(
|
|
252
|
+
cls,
|
|
253
|
+
data: str | bytes,
|
|
254
|
+
*,
|
|
255
|
+
encoding: str = "utf-8",
|
|
256
|
+
mime_type: str | None = None,
|
|
257
|
+
path: str | None = None,
|
|
258
|
+
metadata: dict[Any, Any] | None = None,
|
|
259
|
+
) -> Blob:
|
|
260
|
+
"""Initialize the `Blob` from in-memory data.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
data: The in-memory data associated with the `Blob`
|
|
264
|
+
encoding: Encoding to use if decoding the bytes into a string
|
|
265
|
+
mime_type: If provided, will be set as the MIME type of the data
|
|
266
|
+
path: If provided, will be set as the source from which the data came
|
|
267
|
+
metadata: Metadata to associate with the `Blob`
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
`Blob` instance
|
|
271
|
+
"""
|
|
272
|
+
return cls(
|
|
273
|
+
data=data,
|
|
274
|
+
mimetype=mime_type,
|
|
275
|
+
encoding=encoding,
|
|
276
|
+
path=path,
|
|
277
|
+
metadata=metadata if metadata is not None else {},
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def __repr__(self) -> str:
|
|
281
|
+
"""Return the blob representation."""
|
|
282
|
+
str_repr = f"Blob {id(self)}"
|
|
283
|
+
if self.source:
|
|
284
|
+
str_repr += f" {self.source}"
|
|
285
|
+
return str_repr
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class Document(BaseMedia):
|
|
289
|
+
"""Class for storing a piece of text and associated metadata.
|
|
290
|
+
|
|
291
|
+
!!! note
|
|
292
|
+
|
|
293
|
+
`Document` is for **retrieval workflows**, not chat I/O. For sending text
|
|
294
|
+
to an LLM in a conversation, use message types from `coco.messages`.
|
|
295
|
+
|
|
296
|
+
Example:
|
|
297
|
+
```python
|
|
298
|
+
from coco_core.documents import Document
|
|
299
|
+
|
|
300
|
+
document = Document(
|
|
301
|
+
page_content="Hello, world!", metadata={"source": "https://example.com"}
|
|
302
|
+
)
|
|
303
|
+
```
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
page_content: str
|
|
307
|
+
"""String text."""
|
|
308
|
+
|
|
309
|
+
type: Literal["Document"] = "Document"
|
|
310
|
+
|
|
311
|
+
def __init__(self, page_content: str, **kwargs: Any) -> None:
|
|
312
|
+
"""Pass page_content in as positional or named arg."""
|
|
313
|
+
# my-py is complaining that page_content is not defined on the base class.
|
|
314
|
+
# Here, we're relying on pydantic base class to handle the validation.
|
|
315
|
+
super().__init__(page_content=page_content, **kwargs) # type: ignore[call-arg,unused-ignore]
|
|
316
|
+
|
|
317
|
+
@classmethod
|
|
318
|
+
def is_lc_serializable(cls) -> bool:
|
|
319
|
+
"""Return `True` as this class is serializable."""
|
|
320
|
+
return True
|
|
321
|
+
|
|
322
|
+
@classmethod
|
|
323
|
+
def get_lc_namespace(cls) -> list[str]:
|
|
324
|
+
"""Get the namespace of the Coco object.
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
`["coco", "schema", "document"]`
|
|
328
|
+
"""
|
|
329
|
+
return ["coco", "schema", "document"]
|
|
330
|
+
|
|
331
|
+
def __str__(self) -> str:
|
|
332
|
+
"""Override `__str__` to restrict it to page_content and metadata.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
A string representation of the `Document`.
|
|
336
|
+
"""
|
|
337
|
+
# The format matches pydantic format for __str__.
|
|
338
|
+
#
|
|
339
|
+
# The purpose of this change is to make sure that user code that feeds
|
|
340
|
+
# Document objects directly into prompts remains unchanged due to the addition
|
|
341
|
+
# of the id field (or any other fields in the future).
|
|
342
|
+
#
|
|
343
|
+
# This override will likely be removed in the future in favor of a more general
|
|
344
|
+
# solution of formatting content directly inside the prompts.
|
|
345
|
+
if self.metadata:
|
|
346
|
+
return f"page_content='{self.page_content}' metadata={self.metadata}"
|
|
347
|
+
return f"page_content='{self.page_content}'"
|