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,239 @@
1
+ """Prompt template that contains few shot examples."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from pydantic import ConfigDict, model_validator
7
+ from typing_extensions import Self
8
+
9
+ from coco_core._api import deprecated
10
+ from coco_core.example_selectors import BaseExampleSelector
11
+ from coco_core.prompts.prompt import PromptTemplate
12
+ from coco_core.prompts.string import (
13
+ DEFAULT_FORMATTER_MAPPING,
14
+ PromptTemplateFormat,
15
+ StringPromptTemplate,
16
+ )
17
+
18
+
19
+ class FewShotPromptWithTemplates(StringPromptTemplate):
20
+ """Prompt template that contains few shot examples."""
21
+
22
+ examples: list[dict[str, Any]] | None = None
23
+ """Examples to format into the prompt.
24
+
25
+ Either this or `example_selector` should be provided.
26
+ """
27
+
28
+ example_selector: BaseExampleSelector | None = None
29
+ """`ExampleSelector` to choose the examples to format into the prompt.
30
+
31
+ Either this or `examples` should be provided.
32
+ """
33
+
34
+ example_prompt: PromptTemplate
35
+ """`PromptTemplate` used to format an individual example."""
36
+
37
+ suffix: StringPromptTemplate
38
+ """A `PromptTemplate` to put after the examples."""
39
+
40
+ example_separator: str = "\n\n"
41
+ """String separator used to join the prefix, the examples, and suffix."""
42
+
43
+ prefix: StringPromptTemplate | None = None
44
+ """A `PromptTemplate` to put before the examples."""
45
+
46
+ template_format: PromptTemplateFormat = "f-string"
47
+ """The format of the prompt template.
48
+
49
+ Options are: `'f-string'`, `'jinja2'`, `'mustache'`.
50
+ """
51
+
52
+ validate_template: bool = False
53
+ """Whether or not to try validating the template."""
54
+
55
+ @classmethod
56
+ def get_lc_namespace(cls) -> list[str]:
57
+ """Get the namespace of the Coco object.
58
+
59
+ Returns:
60
+ `["coco", "prompts", "few_shot_with_templates"]`
61
+ """
62
+ return ["coco", "prompts", "few_shot_with_templates"]
63
+
64
+ @model_validator(mode="before")
65
+ @classmethod
66
+ def check_examples_and_selector(cls, values: dict[str, Any]) -> Any:
67
+ """Check that one and only one of examples/example_selector are provided."""
68
+ examples = values.get("examples")
69
+ example_selector = values.get("example_selector")
70
+ if examples and example_selector:
71
+ msg = "Only one of 'examples' and 'example_selector' should be provided"
72
+ raise ValueError(msg)
73
+
74
+ if examples is None and example_selector is None:
75
+ msg = "One of 'examples' and 'example_selector' should be provided"
76
+ raise ValueError(msg)
77
+
78
+ return values
79
+
80
+ @model_validator(mode="after")
81
+ def template_is_valid(self) -> Self:
82
+ """Check that prefix, suffix, and input variables are consistent."""
83
+ if self.validate_template:
84
+ input_variables = self.input_variables
85
+ expected_input_variables = set(self.suffix.input_variables)
86
+ expected_input_variables |= set(self.partial_variables)
87
+ if self.prefix is not None:
88
+ expected_input_variables |= set(self.prefix.input_variables)
89
+ missing_vars = expected_input_variables.difference(input_variables)
90
+ if missing_vars:
91
+ msg = (
92
+ f"Got input_variables={input_variables}, but based on "
93
+ f"prefix/suffix expected {expected_input_variables}"
94
+ )
95
+ raise ValueError(msg)
96
+ else:
97
+ self.input_variables = sorted(
98
+ set(self.suffix.input_variables)
99
+ | set(self.prefix.input_variables if self.prefix else [])
100
+ - set(self.partial_variables)
101
+ )
102
+ return self
103
+
104
+ model_config = ConfigDict(
105
+ arbitrary_types_allowed=True,
106
+ extra="forbid",
107
+ )
108
+
109
+ def _get_examples(self, **kwargs: Any) -> list[dict[str, Any]]:
110
+ if self.examples is not None:
111
+ return self.examples
112
+ if self.example_selector is not None:
113
+ return self.example_selector.select_examples(kwargs)
114
+ msg = "One of 'examples' and 'example_selector' should be provided"
115
+ raise ValueError(msg)
116
+
117
+ async def _aget_examples(self, **kwargs: Any) -> list[dict[str, Any]]:
118
+ if self.examples is not None:
119
+ return self.examples
120
+ if self.example_selector is not None:
121
+ return await self.example_selector.aselect_examples(kwargs)
122
+ msg = "One of 'examples' and 'example_selector' should be provided"
123
+ raise ValueError(msg)
124
+
125
+ def format(self, **kwargs: Any) -> str:
126
+ """Format the prompt with the inputs.
127
+
128
+ Args:
129
+ **kwargs: Any arguments to be passed to the prompt template.
130
+
131
+ Returns:
132
+ A formatted string.
133
+
134
+ Example:
135
+ ```python
136
+ prompt.format(variable1="foo")
137
+ ```
138
+ """
139
+ kwargs = self._merge_partial_and_user_variables(**kwargs)
140
+ # Get the examples to use.
141
+ examples = self._get_examples(**kwargs)
142
+ # Format the examples.
143
+ example_strings = [
144
+ self.example_prompt.format(**example) for example in examples
145
+ ]
146
+ # Create the overall prefix.
147
+ if self.prefix is None:
148
+ prefix = ""
149
+ else:
150
+ prefix_kwargs = {
151
+ k: v for k, v in kwargs.items() if k in self.prefix.input_variables
152
+ }
153
+ for k in prefix_kwargs:
154
+ kwargs.pop(k)
155
+ prefix = self.prefix.format(**prefix_kwargs)
156
+
157
+ # Create the overall suffix
158
+ suffix_kwargs = {
159
+ k: v for k, v in kwargs.items() if k in self.suffix.input_variables
160
+ }
161
+ for k in suffix_kwargs:
162
+ kwargs.pop(k)
163
+ suffix = self.suffix.format(
164
+ **suffix_kwargs,
165
+ )
166
+
167
+ pieces = [prefix, *example_strings, suffix]
168
+ template = self.example_separator.join([piece for piece in pieces if piece])
169
+ # Format the template with the input variables.
170
+ return DEFAULT_FORMATTER_MAPPING[self.template_format](template, **kwargs)
171
+
172
+ async def aformat(self, **kwargs: Any) -> str:
173
+ """Async format the prompt with the inputs.
174
+
175
+ Args:
176
+ **kwargs: Any arguments to be passed to the prompt template.
177
+
178
+ Returns:
179
+ A formatted string.
180
+ """
181
+ kwargs = self._merge_partial_and_user_variables(**kwargs)
182
+ # Get the examples to use.
183
+ examples = await self._aget_examples(**kwargs)
184
+ # Format the examples.
185
+ example_strings = [
186
+ # We can use the sync method here as PromptTemplate doesn't block
187
+ self.example_prompt.format(**example)
188
+ for example in examples
189
+ ]
190
+ # Create the overall prefix.
191
+ if self.prefix is None:
192
+ prefix = ""
193
+ else:
194
+ prefix_kwargs = {
195
+ k: v for k, v in kwargs.items() if k in self.prefix.input_variables
196
+ }
197
+ for k in prefix_kwargs:
198
+ kwargs.pop(k)
199
+ prefix = await self.prefix.aformat(**prefix_kwargs)
200
+
201
+ # Create the overall suffix
202
+ suffix_kwargs = {
203
+ k: v for k, v in kwargs.items() if k in self.suffix.input_variables
204
+ }
205
+ for k in suffix_kwargs:
206
+ kwargs.pop(k)
207
+ suffix = await self.suffix.aformat(
208
+ **suffix_kwargs,
209
+ )
210
+
211
+ pieces = [prefix, *example_strings, suffix]
212
+ template = self.example_separator.join([piece for piece in pieces if piece])
213
+ # Format the template with the input variables.
214
+ return DEFAULT_FORMATTER_MAPPING[self.template_format](template, **kwargs)
215
+
216
+ @property
217
+ def _prompt_type(self) -> str:
218
+ """Return the prompt type key."""
219
+ return "few_shot_with_templates"
220
+
221
+ @deprecated(
222
+ since="1.2.21",
223
+ removal="2.0.0",
224
+ alternative="Use `dumpd`/`dumps` from `coco_core.load` to serialize "
225
+ "prompts and `load`/`loads` to deserialize them.",
226
+ )
227
+ def save(self, file_path: Path | str) -> None:
228
+ """Save the prompt to a file.
229
+
230
+ Args:
231
+ file_path: The path to save the prompt to.
232
+
233
+ Raises:
234
+ ValueError: If `example_selector` is provided.
235
+ """
236
+ if self.example_selector:
237
+ msg = "Saving an example selector is not currently supported"
238
+ raise ValueError(msg)
239
+ return super().save(file_path)
@@ -0,0 +1,177 @@
1
+ """Image prompt template for a multimodal model."""
2
+
3
+ from typing import Any, Literal, cast
4
+
5
+ from pydantic import Field
6
+
7
+ from coco_core.prompt_values import ImagePromptValue, ImageURL, PromptValue
8
+ from coco_core.prompts.base import BasePromptTemplate
9
+ from coco_core.prompts.string import (
10
+ DEFAULT_FORMATTER_MAPPING,
11
+ PromptTemplateFormat,
12
+ get_template_variables,
13
+ )
14
+ from coco_core.runnables import run_in_executor
15
+
16
+
17
+ class ImagePromptTemplate(BasePromptTemplate[ImageURL]):
18
+ """Image prompt template for a multimodal model.
19
+
20
+ Example:
21
+ ```python
22
+ prompt = ImagePromptTemplate(
23
+ input_variables=["image_id"],
24
+ template={"url": "https://example.com/{image_id}.png", "detail": "high"},
25
+ template_format="f-string",
26
+ )
27
+ prompt.format(image_id="cat")
28
+ # {"url": "https://example.com/cat.png", "detail": "high"}
29
+ ```
30
+ """
31
+
32
+ template: dict[str, Any] = Field(default_factory=dict)
33
+ """Template for the prompt."""
34
+
35
+ template_format: PromptTemplateFormat = "f-string"
36
+ """The format of the prompt template.
37
+
38
+ Options are: `'f-string'`, `'mustache'`, `'jinja2'`.
39
+ """
40
+
41
+ def __init__(self, **kwargs: Any) -> None:
42
+ """Create an image prompt template.
43
+
44
+ Raises:
45
+ ValueError: If the input variables contain `'url'`, `'path'`, or
46
+ `'detail'`.
47
+ """
48
+ if "input_variables" not in kwargs:
49
+ kwargs["input_variables"] = []
50
+
51
+ overlap = set(kwargs["input_variables"]) & {"url", "path", "detail"}
52
+ if overlap:
53
+ msg = (
54
+ "input_variables for the image template cannot contain"
55
+ " any of 'url', 'path', or 'detail'."
56
+ f" Found: {overlap}"
57
+ )
58
+ raise ValueError(msg)
59
+
60
+ template = kwargs.get("template", {})
61
+ template_format = kwargs.get("template_format", "f-string")
62
+ for value in template.values():
63
+ if isinstance(value, str):
64
+ get_template_variables(value, template_format)
65
+
66
+ super().__init__(**kwargs)
67
+
68
+ @property
69
+ def _prompt_type(self) -> str:
70
+ """Return the prompt type key."""
71
+ return "image-prompt"
72
+
73
+ @classmethod
74
+ def get_lc_namespace(cls) -> list[str]:
75
+ """Get the namespace of the Coco object.
76
+
77
+ Returns:
78
+ `["coco", "prompts", "image"]`
79
+ """
80
+ return ["coco", "prompts", "image"]
81
+
82
+ def format_prompt(self, **kwargs: Any) -> PromptValue:
83
+ """Format the prompt with the inputs.
84
+
85
+ Args:
86
+ **kwargs: Any arguments to be passed to the prompt template.
87
+
88
+ Returns:
89
+ A formatted string.
90
+ """
91
+ return ImagePromptValue(image_url=self.format(**kwargs))
92
+
93
+ async def aformat_prompt(self, **kwargs: Any) -> PromptValue:
94
+ """Async format the prompt with the inputs.
95
+
96
+ Args:
97
+ **kwargs: Any arguments to be passed to the prompt template.
98
+
99
+ Returns:
100
+ A formatted string.
101
+ """
102
+ return ImagePromptValue(image_url=await self.aformat(**kwargs))
103
+
104
+ def format(
105
+ self,
106
+ **kwargs: Any,
107
+ ) -> ImageURL:
108
+ """Format the prompt with the inputs.
109
+
110
+ Args:
111
+ **kwargs: Any arguments to be passed to the prompt template.
112
+
113
+ Returns:
114
+ A formatted string.
115
+
116
+ Raises:
117
+ ValueError: If the url is not provided.
118
+ ValueError: If the url is not a string.
119
+ ValueError: If `'path'` is provided in the template or kwargs.
120
+
121
+ Example:
122
+ ```python
123
+ prompt.format(variable1="foo")
124
+ ```
125
+ """
126
+ formatted = {}
127
+ for k, v in self.template.items():
128
+ if isinstance(v, str):
129
+ formatted[k] = DEFAULT_FORMATTER_MAPPING[self.template_format](
130
+ v, **kwargs
131
+ )
132
+ else:
133
+ formatted[k] = v
134
+ url = kwargs.get("url") or formatted.get("url")
135
+ if kwargs.get("path") or formatted.get("path"):
136
+ msg = (
137
+ "Loading images from 'path' has been removed as of 0.3.15 for security "
138
+ "reasons. Please specify images by 'url'."
139
+ )
140
+ raise ValueError(msg)
141
+ detail = kwargs.get("detail") or formatted.get("detail")
142
+ if not url:
143
+ msg = "Must provide url."
144
+ raise ValueError(msg)
145
+ if not isinstance(url, str):
146
+ msg = "url must be a string."
147
+ raise ValueError(msg) # noqa: TRY004
148
+ output: ImageURL = {"url": url}
149
+ if detail:
150
+ # Don't check literal values here: let the API check them
151
+ output["detail"] = cast("Literal['auto', 'low', 'high']", detail)
152
+ return output
153
+
154
+ async def aformat(self, **kwargs: Any) -> ImageURL:
155
+ """Async format the prompt with the inputs.
156
+
157
+ Args:
158
+ **kwargs: Any arguments to be passed to the prompt template.
159
+
160
+ Returns:
161
+ A formatted string.
162
+ """
163
+ return await run_in_executor(None, self.format, **kwargs)
164
+
165
+ def pretty_repr(
166
+ self,
167
+ html: bool = False, # noqa: FBT001,FBT002
168
+ ) -> str:
169
+ """Return a pretty representation of the prompt.
170
+
171
+ Args:
172
+ html: Whether to return an html formatted string.
173
+
174
+ Returns:
175
+ A pretty representation of the prompt.
176
+ """
177
+ raise NotImplementedError