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.
Files changed (400) hide show
  1. coco/__init__.py +3 -0
  2. coco/agents/__init__.py +9 -0
  3. coco/agents/_subagent_transformer.py +307 -0
  4. coco/agents/factory.py +2164 -0
  5. coco/agents/middleware/__init__.py +100 -0
  6. coco/agents/middleware/_execution.py +385 -0
  7. coco/agents/middleware/_redaction.py +454 -0
  8. coco/agents/middleware/_retry.py +134 -0
  9. coco/agents/middleware/_trace_policy.py +61 -0
  10. coco/agents/middleware/context_editing.py +306 -0
  11. coco/agents/middleware/file_search.py +433 -0
  12. coco/agents/middleware/human_in_the_loop.py +680 -0
  13. coco/agents/middleware/internal_call_transformer.py +108 -0
  14. coco/agents/middleware/model_call_limit.py +267 -0
  15. coco/agents/middleware/model_fallback.py +417 -0
  16. coco/agents/middleware/model_retry.py +327 -0
  17. coco/agents/middleware/pii.py +878 -0
  18. coco/agents/middleware/provider_tool_search.py +307 -0
  19. coco/agents/middleware/shell_tool.py +949 -0
  20. coco/agents/middleware/summarization.py +910 -0
  21. coco/agents/middleware/todo.py +357 -0
  22. coco/agents/middleware/tool_call_limit.py +495 -0
  23. coco/agents/middleware/tool_emulator.py +251 -0
  24. coco/agents/middleware/tool_error.py +209 -0
  25. coco/agents/middleware/tool_retry.py +421 -0
  26. coco/agents/middleware/tool_selection.py +515 -0
  27. coco/agents/middleware/types.py +2201 -0
  28. coco/agents/structured_output.py +472 -0
  29. coco/chat_models/__init__.py +7 -0
  30. coco/chat_models/base.py +1082 -0
  31. coco/embeddings/__init__.py +18 -0
  32. coco/embeddings/base.py +279 -0
  33. coco/mcp/__init__.py +36 -0
  34. coco/mcp/adapter.py +245 -0
  35. coco/mcp/elicitation.py +394 -0
  36. coco/mcp/tools.py +307 -0
  37. coco/messages/__init__.py +73 -0
  38. coco/py.typed +0 -0
  39. coco/rate_limiters/__init__.py +13 -0
  40. coco/tools/__init__.py +22 -0
  41. coco/tools/tool_node.py +20 -0
  42. coco_anthropic/__init__.py +15 -0
  43. coco_anthropic/_client_utils.py +81 -0
  44. coco_anthropic/_compat.py +228 -0
  45. coco_anthropic/_sdk_compat.py +124 -0
  46. coco_anthropic/_version.py +3 -0
  47. coco_anthropic/chat_models.py +3349 -0
  48. coco_anthropic/data/__init__.py +1 -0
  49. coco_anthropic/data/_profiles.py +491 -0
  50. coco_anthropic/data/profile_augmentations.toml +69 -0
  51. coco_anthropic/experimental.py +140 -0
  52. coco_anthropic/llms.py +428 -0
  53. coco_anthropic/middleware/__init__.py +25 -0
  54. coco_anthropic/middleware/anthropic_tools.py +1197 -0
  55. coco_anthropic/middleware/bash.py +84 -0
  56. coco_anthropic/middleware/file_search.py +360 -0
  57. coco_anthropic/middleware/prompt_caching.py +276 -0
  58. coco_anthropic/output_parsers.py +93 -0
  59. coco_anthropic/py.typed +0 -0
  60. coco_core/__init__.py +20 -0
  61. coco_core/_api/__init__.py +87 -0
  62. coco_core/_api/beta_decorator.py +266 -0
  63. coco_core/_api/deprecation.py +637 -0
  64. coco_core/_api/internal.py +23 -0
  65. coco_core/_api/path.py +50 -0
  66. coco_core/_import_utils.py +41 -0
  67. coco_core/_protocol.py +625 -0
  68. coco_core/_security/__init__.py +36 -0
  69. coco_core/_security/_exceptions.py +9 -0
  70. coco_core/_security/_policy.py +313 -0
  71. coco_core/_security/_ssrf_protection.py +155 -0
  72. coco_core/_security/_transport.py +254 -0
  73. coco_core/agents.py +258 -0
  74. coco_core/caches.py +272 -0
  75. coco_core/callbacks/__init__.py +132 -0
  76. coco_core/callbacks/base.py +1229 -0
  77. coco_core/callbacks/file.py +266 -0
  78. coco_core/callbacks/manager.py +2826 -0
  79. coco_core/callbacks/stdout.py +123 -0
  80. coco_core/callbacks/streaming_stdout.py +154 -0
  81. coco_core/callbacks/usage.py +124 -0
  82. coco_core/chat_history.py +267 -0
  83. coco_core/chat_loaders.py +26 -0
  84. coco_core/chat_sessions.py +19 -0
  85. coco_core/cross_encoders.py +18 -0
  86. coco_core/document_loaders/__init__.py +36 -0
  87. coco_core/document_loaders/base.py +155 -0
  88. coco_core/document_loaders/blob_loaders.py +38 -0
  89. coco_core/documents/__init__.py +55 -0
  90. coco_core/documents/base.py +347 -0
  91. coco_core/documents/compressor.py +74 -0
  92. coco_core/documents/transformers.py +79 -0
  93. coco_core/embeddings/__init__.py +31 -0
  94. coco_core/embeddings/embeddings.py +78 -0
  95. coco_core/embeddings/fake.py +129 -0
  96. coco_core/env.py +22 -0
  97. coco_core/example_selectors/__init__.py +47 -0
  98. coco_core/example_selectors/base.py +60 -0
  99. coco_core/example_selectors/length_based.py +131 -0
  100. coco_core/example_selectors/semantic_similarity.py +366 -0
  101. coco_core/exceptions.py +166 -0
  102. coco_core/globals.py +72 -0
  103. coco_core/indexing/__init__.py +53 -0
  104. coco_core/indexing/api.py +954 -0
  105. coco_core/indexing/base.py +661 -0
  106. coco_core/indexing/in_memory.py +104 -0
  107. coco_core/language_models/__init__.py +116 -0
  108. coco_core/language_models/_compat_bridge.py +844 -0
  109. coco_core/language_models/_utils.py +343 -0
  110. coco_core/language_models/base.py +500 -0
  111. coco_core/language_models/chat_model_stream.py +1525 -0
  112. coco_core/language_models/chat_models.py +2748 -0
  113. coco_core/language_models/fake.py +137 -0
  114. coco_core/language_models/fake_chat_models.py +396 -0
  115. coco_core/language_models/llms.py +1569 -0
  116. coco_core/language_models/model_profile.py +183 -0
  117. coco_core/load/__init__.py +44 -0
  118. coco_core/load/_validation.py +191 -0
  119. coco_core/load/dump.py +120 -0
  120. coco_core/load/load.py +828 -0
  121. coco_core/load/mapping.py +1097 -0
  122. coco_core/load/serializable.py +406 -0
  123. coco_core/messages/__init__.py +198 -0
  124. coco_core/messages/ai.py +854 -0
  125. coco_core/messages/base.py +518 -0
  126. coco_core/messages/block_translators/__init__.py +112 -0
  127. coco_core/messages/block_translators/anthropic.py +534 -0
  128. coco_core/messages/block_translators/bedrock.py +108 -0
  129. coco_core/messages/block_translators/bedrock_converse.py +329 -0
  130. coco_core/messages/block_translators/coco_v0.py +303 -0
  131. coco_core/messages/block_translators/google_genai.py +610 -0
  132. coco_core/messages/block_translators/google_vertexai.py +21 -0
  133. coco_core/messages/block_translators/groq.py +157 -0
  134. coco_core/messages/block_translators/openai.py +1089 -0
  135. coco_core/messages/chat.py +64 -0
  136. coco_core/messages/content.py +1488 -0
  137. coco_core/messages/function.py +62 -0
  138. coco_core/messages/human.py +70 -0
  139. coco_core/messages/modifier.py +33 -0
  140. coco_core/messages/system.py +70 -0
  141. coco_core/messages/tool.py +418 -0
  142. coco_core/messages/utils.py +2442 -0
  143. coco_core/output_parsers/__init__.py +101 -0
  144. coco_core/output_parsers/base.py +361 -0
  145. coco_core/output_parsers/format_instructions.py +16 -0
  146. coco_core/output_parsers/json.py +139 -0
  147. coco_core/output_parsers/list.py +249 -0
  148. coco_core/output_parsers/openai_functions.py +324 -0
  149. coco_core/output_parsers/openai_tools.py +383 -0
  150. coco_core/output_parsers/pydantic.py +141 -0
  151. coco_core/output_parsers/string.py +63 -0
  152. coco_core/output_parsers/transform.py +175 -0
  153. coco_core/output_parsers/xml.py +301 -0
  154. coco_core/outputs/__init__.py +66 -0
  155. coco_core/outputs/chat_generation.py +147 -0
  156. coco_core/outputs/chat_result.py +39 -0
  157. coco_core/outputs/generation.py +80 -0
  158. coco_core/outputs/llm_result.py +112 -0
  159. coco_core/outputs/run_info.py +22 -0
  160. coco_core/prompt_values.py +161 -0
  161. coco_core/prompts/__init__.py +101 -0
  162. coco_core/prompts/base.py +508 -0
  163. coco_core/prompts/chat.py +1495 -0
  164. coco_core/prompts/dict.py +177 -0
  165. coco_core/prompts/few_shot.py +483 -0
  166. coco_core/prompts/few_shot_with_templates.py +239 -0
  167. coco_core/prompts/image.py +177 -0
  168. coco_core/prompts/loading.py +296 -0
  169. coco_core/prompts/message.py +97 -0
  170. coco_core/prompts/prompt.py +312 -0
  171. coco_core/prompts/string.py +399 -0
  172. coco_core/prompts/structured.py +214 -0
  173. coco_core/py.typed +0 -0
  174. coco_core/rate_limiters.py +254 -0
  175. coco_core/retrievers.py +328 -0
  176. coco_core/runnables/__init__.py +136 -0
  177. coco_core/runnables/base.py +6725 -0
  178. coco_core/runnables/branch.py +457 -0
  179. coco_core/runnables/config.py +712 -0
  180. coco_core/runnables/configurable.py +710 -0
  181. coco_core/runnables/fallbacks.py +663 -0
  182. coco_core/runnables/graph.py +741 -0
  183. coco_core/runnables/graph_ascii.py +366 -0
  184. coco_core/runnables/graph_mermaid.py +503 -0
  185. coco_core/runnables/graph_png.py +215 -0
  186. coco_core/runnables/history.py +631 -0
  187. coco_core/runnables/passthrough.py +849 -0
  188. coco_core/runnables/retry.py +379 -0
  189. coco_core/runnables/router.py +239 -0
  190. coco_core/runnables/schema.py +188 -0
  191. coco_core/runnables/utils.py +798 -0
  192. coco_core/stores.py +291 -0
  193. coco_core/structured_query.py +203 -0
  194. coco_core/sys_info.py +154 -0
  195. coco_core/tools/__init__.py +95 -0
  196. coco_core/tools/base.py +1948 -0
  197. coco_core/tools/convert.py +497 -0
  198. coco_core/tools/render.py +67 -0
  199. coco_core/tools/retriever.py +94 -0
  200. coco_core/tools/simple.py +208 -0
  201. coco_core/tools/structured.py +322 -0
  202. coco_core/tracers/__init__.py +47 -0
  203. coco_core/tracers/_compat.py +95 -0
  204. coco_core/tracers/_context.py +337 -0
  205. coco_core/tracers/_streaming.py +53 -0
  206. coco_core/tracers/base.py +955 -0
  207. coco_core/tracers/coco.py +279 -0
  208. coco_core/tracers/context.py +205 -0
  209. coco_core/tracers/core.py +766 -0
  210. coco_core/tracers/event_stream.py +1101 -0
  211. coco_core/tracers/log_stream.py +765 -0
  212. coco_core/tracers/memory_stream.py +200 -0
  213. coco_core/tracers/root_listeners.py +130 -0
  214. coco_core/tracers/run_collector.py +40 -0
  215. coco_core/tracers/schemas.py +14 -0
  216. coco_core/tracers/stdout.py +205 -0
  217. coco_core/utils/__init__.py +111 -0
  218. coco_core/utils/_gateway.py +274 -0
  219. coco_core/utils/_merge.py +218 -0
  220. coco_core/utils/aiter.py +357 -0
  221. coco_core/utils/env.py +86 -0
  222. coco_core/utils/formatting.py +80 -0
  223. coco_core/utils/function_calling.py +869 -0
  224. coco_core/utils/html.py +132 -0
  225. coco_core/utils/image.py +15 -0
  226. coco_core/utils/input.py +82 -0
  227. coco_core/utils/interactive_env.py +12 -0
  228. coco_core/utils/iter.py +229 -0
  229. coco_core/utils/json.py +230 -0
  230. coco_core/utils/json_schema.py +273 -0
  231. coco_core/utils/mustache.py +706 -0
  232. coco_core/utils/pydantic.py +631 -0
  233. coco_core/utils/strings.py +69 -0
  234. coco_core/utils/usage.py +61 -0
  235. coco_core/utils/utils.py +528 -0
  236. coco_core/utils/uuid.py +57 -0
  237. coco_core/vectorstores/__init__.py +53 -0
  238. coco_core/vectorstores/base.py +1111 -0
  239. coco_core/vectorstores/in_memory.py +546 -0
  240. coco_core/vectorstores/utils.py +163 -0
  241. coco_core/version.py +3 -0
  242. coco_framework-0.1.0.dist-info/METADATA +184 -0
  243. coco_framework-0.1.0.dist-info/RECORD +400 -0
  244. coco_framework-0.1.0.dist-info/WHEEL +4 -0
  245. coco_framework-0.1.0.dist-info/licenses/LICENSE +24 -0
  246. coco_framework-0.1.0.dist-info/licenses/NOTICE +15 -0
  247. coco_graph/_internal/__init__.py +4 -0
  248. coco_graph/_internal/_cache.py +31 -0
  249. coco_graph/_internal/_config.py +474 -0
  250. coco_graph/_internal/_constants.py +140 -0
  251. coco_graph/_internal/_fields.py +213 -0
  252. coco_graph/_internal/_future.py +220 -0
  253. coco_graph/_internal/_pydantic.py +275 -0
  254. coco_graph/_internal/_queue.py +124 -0
  255. coco_graph/_internal/_replay.py +90 -0
  256. coco_graph/_internal/_retry.py +29 -0
  257. coco_graph/_internal/_runnable.py +969 -0
  258. coco_graph/_internal/_scratchpad.py +19 -0
  259. coco_graph/_internal/_serde.py +253 -0
  260. coco_graph/_internal/_timeout.py +25 -0
  261. coco_graph/_internal/_typing.py +54 -0
  262. coco_graph/cache/base/__init__.py +48 -0
  263. coco_graph/cache/base/py.typed +0 -0
  264. coco_graph/cache/memory/__init__.py +73 -0
  265. coco_graph/cache/redis/__init__.py +144 -0
  266. coco_graph/cache/sqlite/__init__.py +120 -0
  267. coco_graph/callbacks.py +394 -0
  268. coco_graph/channels/__init__.py +29 -0
  269. coco_graph/channels/any_value.py +72 -0
  270. coco_graph/channels/base.py +121 -0
  271. coco_graph/channels/binop.py +155 -0
  272. coco_graph/channels/delta.py +202 -0
  273. coco_graph/channels/ephemeral_value.py +79 -0
  274. coco_graph/channels/last_value.py +151 -0
  275. coco_graph/channels/named_barrier_value.py +167 -0
  276. coco_graph/channels/topic.py +94 -0
  277. coco_graph/channels/untracked_value.py +73 -0
  278. coco_graph/checkpoint/base/__init__.py +861 -0
  279. coco_graph/checkpoint/base/id.py +109 -0
  280. coco_graph/checkpoint/base/py.typed +0 -0
  281. coco_graph/checkpoint/memory/__init__.py +698 -0
  282. coco_graph/checkpoint/memory/py.typed +0 -0
  283. coco_graph/checkpoint/postgres/__init__.py +602 -0
  284. coco_graph/checkpoint/postgres/_ainternal.py +23 -0
  285. coco_graph/checkpoint/postgres/_internal.py +21 -0
  286. coco_graph/checkpoint/postgres/aio.py +691 -0
  287. coco_graph/checkpoint/postgres/base.py +666 -0
  288. coco_graph/checkpoint/postgres/py.typed +0 -0
  289. coco_graph/checkpoint/postgres/shallow.py +967 -0
  290. coco_graph/checkpoint/serde/__init__.py +0 -0
  291. coco_graph/checkpoint/serde/_msgpack.py +97 -0
  292. coco_graph/checkpoint/serde/base.py +64 -0
  293. coco_graph/checkpoint/serde/encrypted.py +80 -0
  294. coco_graph/checkpoint/serde/event_hooks.py +52 -0
  295. coco_graph/checkpoint/serde/jsonplus.py +883 -0
  296. coco_graph/checkpoint/serde/py.typed +0 -0
  297. coco_graph/checkpoint/serde/types.py +68 -0
  298. coco_graph/checkpoint/sqlite/__init__.py +645 -0
  299. coco_graph/checkpoint/sqlite/_delta.py +172 -0
  300. coco_graph/checkpoint/sqlite/aio.py +738 -0
  301. coco_graph/checkpoint/sqlite/py.typed +0 -0
  302. coco_graph/checkpoint/sqlite/utils.py +116 -0
  303. coco_graph/config.py +196 -0
  304. coco_graph/constants.py +64 -0
  305. coco_graph/errors.py +241 -0
  306. coco_graph/func/__init__.py +620 -0
  307. coco_graph/graph/__init__.py +12 -0
  308. coco_graph/graph/_branch.py +225 -0
  309. coco_graph/graph/_node.py +103 -0
  310. coco_graph/graph/message.py +437 -0
  311. coco_graph/graph/state.py +1978 -0
  312. coco_graph/graph/ui.py +227 -0
  313. coco_graph/managed/__init__.py +3 -0
  314. coco_graph/managed/base.py +31 -0
  315. coco_graph/managed/is_last_step.py +24 -0
  316. coco_graph/prebuilt/__init__.py +23 -0
  317. coco_graph/prebuilt/_tool_call_stream.py +117 -0
  318. coco_graph/prebuilt/_tool_call_transformer.py +165 -0
  319. coco_graph/prebuilt/chat_agent_executor.py +1015 -0
  320. coco_graph/prebuilt/interrupt.py +105 -0
  321. coco_graph/prebuilt/py.typed +0 -0
  322. coco_graph/prebuilt/tool_node.py +2030 -0
  323. coco_graph/prebuilt/tool_validator.py +221 -0
  324. coco_graph/pregel/__init__.py +3 -0
  325. coco_graph/pregel/_algo.py +1460 -0
  326. coco_graph/pregel/_call.py +298 -0
  327. coco_graph/pregel/_checkpoint.py +331 -0
  328. coco_graph/pregel/_config.py +0 -0
  329. coco_graph/pregel/_draw.py +294 -0
  330. coco_graph/pregel/_executor.py +223 -0
  331. coco_graph/pregel/_io.py +174 -0
  332. coco_graph/pregel/_log.py +3 -0
  333. coco_graph/pregel/_loop.py +1988 -0
  334. coco_graph/pregel/_messages.py +461 -0
  335. coco_graph/pregel/_read.py +312 -0
  336. coco_graph/pregel/_retry.py +854 -0
  337. coco_graph/pregel/_runner.py +941 -0
  338. coco_graph/pregel/_tools.py +268 -0
  339. coco_graph/pregel/_utils.py +221 -0
  340. coco_graph/pregel/_validate.py +120 -0
  341. coco_graph/pregel/_write.py +192 -0
  342. coco_graph/pregel/debug.py +302 -0
  343. coco_graph/pregel/main.py +4364 -0
  344. coco_graph/pregel/protocol.py +288 -0
  345. coco_graph/pregel/types.py +38 -0
  346. coco_graph/py.typed +0 -0
  347. coco_graph/runtime.py +350 -0
  348. coco_graph/store/base/__init__.py +1322 -0
  349. coco_graph/store/base/batch.py +371 -0
  350. coco_graph/store/base/embed.py +436 -0
  351. coco_graph/store/base/py.typed +0 -0
  352. coco_graph/store/memory/__init__.py +592 -0
  353. coco_graph/store/memory/py.typed +0 -0
  354. coco_graph/store/postgres/__init__.py +4 -0
  355. coco_graph/store/postgres/aio.py +592 -0
  356. coco_graph/store/postgres/base.py +1480 -0
  357. coco_graph/store/postgres/py.typed +0 -0
  358. coco_graph/store/sqlite/__init__.py +4 -0
  359. coco_graph/store/sqlite/aio.py +632 -0
  360. coco_graph/store/sqlite/base.py +1514 -0
  361. coco_graph/stream/__init__.py +45 -0
  362. coco_graph/stream/_convert.py +32 -0
  363. coco_graph/stream/_mux.py +523 -0
  364. coco_graph/stream/_types.py +330 -0
  365. coco_graph/stream/run_stream.py +735 -0
  366. coco_graph/stream/stream_channel.py +341 -0
  367. coco_graph/stream/transformers.py +1039 -0
  368. coco_graph/types.py +1079 -0
  369. coco_graph/typing.py +48 -0
  370. coco_graph/utils/__init__.py +1 -0
  371. coco_graph/utils/config.py +4 -0
  372. coco_graph/utils/runnable.py +3 -0
  373. coco_graph/version.py +13 -0
  374. coco_graph/warnings.py +69 -0
  375. coco_openai/__init__.py +20 -0
  376. coco_openai/_compat.py +45 -0
  377. coco_openai/_version.py +3 -0
  378. coco_openai/chat_models/__init__.py +6 -0
  379. coco_openai/chat_models/_client_utils.py +684 -0
  380. coco_openai/chat_models/_compat.py +525 -0
  381. coco_openai/chat_models/azure.py +1227 -0
  382. coco_openai/chat_models/base.py +5654 -0
  383. coco_openai/chat_models/codex.py +557 -0
  384. coco_openai/chatgpt_oauth.py +1063 -0
  385. coco_openai/data/__init__.py +1 -0
  386. coco_openai/data/_profiles.py +1655 -0
  387. coco_openai/data/profile_augmentations.toml +127 -0
  388. coco_openai/embeddings/__init__.py +6 -0
  389. coco_openai/embeddings/azure.py +240 -0
  390. coco_openai/embeddings/base.py +820 -0
  391. coco_openai/llms/__init__.py +6 -0
  392. coco_openai/llms/azure.py +249 -0
  393. coco_openai/llms/base.py +919 -0
  394. coco_openai/middleware/__init__.py +11 -0
  395. coco_openai/middleware/openai_moderation.py +484 -0
  396. coco_openai/output_parsers/__init__.py +9 -0
  397. coco_openai/output_parsers/tools.py +9 -0
  398. coco_openai/py.typed +0 -0
  399. coco_openai/tools/__init__.py +5 -0
  400. 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}'"