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,766 @@
1
+ """Utilities for the root listener."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import traceback
7
+ from abc import ABC, abstractmethod
8
+ from datetime import datetime, timezone
9
+ from typing import (
10
+ TYPE_CHECKING,
11
+ Any,
12
+ Literal,
13
+ cast,
14
+ )
15
+
16
+ from coco_core.exceptions import TracerException
17
+ from coco_core.load import dumpd
18
+ from coco_core.tracers.schemas import Run
19
+ from coco_core.utils._gateway import GATEWAY_METADATA_RESPONSE_KEY
20
+
21
+ if TYPE_CHECKING:
22
+ from collections.abc import Coroutine, Sequence
23
+ from uuid import UUID
24
+
25
+ from tenacity import RetryCallState
26
+
27
+ from coco_core.documents import Document
28
+ from coco_core.messages import BaseMessage
29
+ from coco_core.outputs import (
30
+ ChatGeneration,
31
+ ChatGenerationChunk,
32
+ GenerationChunk,
33
+ LLMResult,
34
+ )
35
+
36
+ logger = logging.getLogger(__name__)
37
+
38
+ SCHEMA_FORMAT_TYPE = Literal["original", "streaming_events"]
39
+
40
+ # Key under which gateway metadata is attached to a run's metadata for tracing.
41
+ _GATEWAY_RUN_METADATA_KEY = "ls_gateway_info"
42
+
43
+
44
+ def _extract_gateway_metadata(response: LLMResult) -> dict[str, Any] | None:
45
+ """Extract LangSmith gateway metadata from a model response.
46
+
47
+ When a request is routed through the LangSmith gateway, the gateway returns
48
+ metadata (e.g. the resolved provider and model) that integrations surface on
49
+ the generation's `generation_info` under `GATEWAY_METADATA_RESPONSE_KEY`.
50
+
51
+ Args:
52
+ response: The `LLMResult` produced by the model.
53
+
54
+ Returns:
55
+ The gateway metadata, or `None` if the response carries none.
56
+ """
57
+ for generations in response.generations:
58
+ for generation in generations:
59
+ generation_info = getattr(generation, "generation_info", None) or {}
60
+ gateway_metadata = generation_info.get(GATEWAY_METADATA_RESPONSE_KEY)
61
+ if isinstance(gateway_metadata, dict):
62
+ return gateway_metadata
63
+ return None
64
+
65
+
66
+ class _TracerCore(ABC):
67
+ """Abstract base class for tracers.
68
+
69
+ This class provides common methods, and reusable methods for tracers.
70
+ """
71
+
72
+ log_missing_parent: bool = True
73
+
74
+ def __init__(
75
+ self,
76
+ *,
77
+ _schema_format: Literal[
78
+ "original", "streaming_events", "original+chat"
79
+ ] = "original",
80
+ run_map: dict[str, Run] | None = None,
81
+ order_map: dict[UUID, tuple[UUID, str]] | None = None,
82
+ _external_run_ids: dict[str, int] | None = None,
83
+ **kwargs: Any,
84
+ ) -> None:
85
+ """Initialize the tracer.
86
+
87
+ Args:
88
+ _schema_format: Primarily changes how the inputs and outputs are handled.
89
+
90
+ For internal use only. This API will change.
91
+
92
+ - `'original'` is the format used by all current tracers.
93
+
94
+ This format is slightly inconsistent with respect to inputs and
95
+ outputs.
96
+ - `'streaming_events'` is used for supporting streaming events, for
97
+ internal usage. It will likely change in the future, or be
98
+ deprecated entirely in favor of a dedicated async tracer for
99
+ streaming events.
100
+ - `'original+chat'` is a format that is the same as `'original'` except
101
+ it does NOT raise an attribute error `on_chat_model_start`
102
+ run_map: Optional shared map of run ID to run.
103
+ order_map: Optional shared map of run ID to trace ordering data.
104
+ _external_run_ids: Optional shared set of externally injected run IDs.
105
+ **kwargs: Additional keyword arguments that will be passed to the
106
+ superclass.
107
+ """
108
+ super().__init__(**kwargs)
109
+
110
+ self._schema_format = _schema_format # For internal use only API will change.
111
+
112
+ self.run_map = run_map if run_map is not None else {}
113
+ """Map of run ID to run. Cleared on run end."""
114
+
115
+ self.order_map = order_map if order_map is not None else {}
116
+ """Map of run ID to (trace_id, dotted_order). Cleared when tracer GCed."""
117
+
118
+ self._external_run_ids: dict[str, int] = (
119
+ _external_run_ids if _external_run_ids is not None else {}
120
+ )
121
+ """Refcount of active children per externally-injected run ID.
122
+
123
+ These runs are added to `run_map` so child runs can find their parent,
124
+ but they are not managed by the tracer's callback lifecycle. When
125
+ the last child finishes the entry is evicted to avoid memory leaks.
126
+ """
127
+
128
+ @abstractmethod
129
+ def _persist_run(self, run: Run) -> Coroutine[Any, Any, None] | None:
130
+ """Persist a run."""
131
+
132
+ @staticmethod
133
+ def _add_child_run(
134
+ parent_run: Run,
135
+ child_run: Run,
136
+ ) -> None:
137
+ """Add child run to a chain run or tool run."""
138
+ parent_run.child_runs.append(child_run)
139
+
140
+ @staticmethod
141
+ def _get_stacktrace(error: BaseException) -> str:
142
+ """Get the stacktrace of the parent error."""
143
+ msg = repr(error)
144
+ try:
145
+ tb = traceback.format_exception(error)
146
+ return (msg + "\n\n".join(tb)).strip()
147
+ except Exception:
148
+ return msg
149
+
150
+ def _start_trace(self, run: Run) -> Coroutine[Any, Any, None] | None: # type: ignore[return]
151
+ current_dotted_order = run.start_time.strftime("%Y%m%dT%H%M%S%fZ") + str(run.id)
152
+ if run.parent_run_id:
153
+ if parent := self.order_map.get(run.parent_run_id):
154
+ run.trace_id, run.dotted_order = parent
155
+ run.dotted_order += "." + current_dotted_order
156
+ if parent_run := self.run_map.get(str(run.parent_run_id)):
157
+ self._add_child_run(parent_run, run)
158
+ parent_key = str(run.parent_run_id)
159
+ if parent_key in self._external_run_ids:
160
+ self._external_run_ids[parent_key] += 1
161
+ else:
162
+ if self.log_missing_parent:
163
+ logger.debug(
164
+ "Parent run %s not found for run %s. Treating as a root run.",
165
+ run.parent_run_id,
166
+ run.id,
167
+ )
168
+ run.parent_run_id = None
169
+ run.trace_id = run.id
170
+ run.dotted_order = current_dotted_order
171
+ else:
172
+ run.trace_id = run.id
173
+ run.dotted_order = current_dotted_order
174
+ self.order_map[run.id] = (run.trace_id, run.dotted_order)
175
+ self.run_map[str(run.id)] = run
176
+
177
+ def _get_run(self, run_id: UUID, run_type: str | set[str] | None = None) -> Run:
178
+ try:
179
+ run = self.run_map[str(run_id)]
180
+ except KeyError as exc:
181
+ msg = f"No indexed run ID {run_id}."
182
+ raise TracerException(msg) from exc
183
+
184
+ if isinstance(run_type, str):
185
+ run_types: set[str] | None = {run_type}
186
+ else:
187
+ run_types = run_type
188
+ if run_types is not None and run.run_type not in run_types:
189
+ msg = (
190
+ f"Found {run.run_type} run at ID {run_id}, "
191
+ f"but expected {run_types} run."
192
+ )
193
+ raise TracerException(msg)
194
+ return run
195
+
196
+ def _create_chat_model_run(
197
+ self,
198
+ serialized: dict[str, Any],
199
+ messages: list[list[BaseMessage]],
200
+ run_id: UUID,
201
+ tags: list[str] | None = None,
202
+ parent_run_id: UUID | None = None,
203
+ metadata: dict[str, Any] | None = None,
204
+ name: str | None = None,
205
+ **kwargs: Any,
206
+ ) -> Run:
207
+ """Create a chat model run."""
208
+ if self._schema_format not in {"streaming_events", "original+chat"}:
209
+ # Please keep this un-implemented for backwards compatibility.
210
+ # When it's unimplemented old tracers that use the "original" format
211
+ # fallback on the on_llm_start method implementation if they
212
+ # find that the on_chat_model_start method is not implemented.
213
+ # This can eventually be cleaned up by writing a "modern" tracer
214
+ # that has all the updated schema changes corresponding to
215
+ # the "streaming_events" format.
216
+ msg = (
217
+ f"Chat model tracing is not supported in "
218
+ f"for {self._schema_format} format."
219
+ )
220
+ raise NotImplementedError(msg)
221
+ start_time = datetime.now(timezone.utc)
222
+ if metadata:
223
+ kwargs.update({"metadata": metadata})
224
+ return Run(
225
+ id=run_id,
226
+ parent_run_id=parent_run_id,
227
+ serialized=serialized,
228
+ inputs={"messages": [[dumpd(msg) for msg in batch] for batch in messages]},
229
+ extra=kwargs,
230
+ events=[{"name": "start", "time": start_time}],
231
+ start_time=start_time,
232
+ # WARNING: This is valid ONLY for streaming_events.
233
+ # run_type="llm" is what's used by virtually all tracers.
234
+ # Changing this to "chat_model" may break triggering on_llm_start
235
+ run_type="chat_model",
236
+ tags=tags,
237
+ name=name,
238
+ )
239
+
240
+ def _create_llm_run(
241
+ self,
242
+ serialized: dict[str, Any],
243
+ prompts: list[str],
244
+ run_id: UUID,
245
+ tags: list[str] | None = None,
246
+ parent_run_id: UUID | None = None,
247
+ metadata: dict[str, Any] | None = None,
248
+ name: str | None = None,
249
+ **kwargs: Any,
250
+ ) -> Run:
251
+ """Create a llm run."""
252
+ start_time = datetime.now(timezone.utc)
253
+ if metadata:
254
+ kwargs.update({"metadata": metadata})
255
+ return Run(
256
+ id=run_id,
257
+ parent_run_id=parent_run_id,
258
+ serialized=serialized,
259
+ # TODO: Figure out how to expose kwargs here
260
+ inputs={"prompts": prompts},
261
+ extra=kwargs,
262
+ events=[{"name": "start", "time": start_time}],
263
+ start_time=start_time,
264
+ run_type="llm",
265
+ tags=tags or [],
266
+ name=name,
267
+ )
268
+
269
+ def _llm_run_with_token_event(
270
+ self,
271
+ token: str | list[str | dict[str, Any]],
272
+ run_id: UUID,
273
+ chunk: GenerationChunk | ChatGenerationChunk | None = None,
274
+ parent_run_id: UUID | None = None,
275
+ ) -> Run:
276
+ """Append token event to LLM run and return the run."""
277
+ _ = parent_run_id
278
+ llm_run = self._get_run(run_id, run_type={"llm", "chat_model"})
279
+ event_kwargs: dict[str, Any] = {"token": token}
280
+ if chunk:
281
+ event_kwargs["chunk"] = chunk
282
+ llm_run.events.append(
283
+ {
284
+ "name": "new_token",
285
+ "time": datetime.now(timezone.utc),
286
+ "kwargs": event_kwargs,
287
+ },
288
+ )
289
+ return llm_run
290
+
291
+ def _llm_run_with_retry_event(
292
+ self,
293
+ retry_state: RetryCallState,
294
+ run_id: UUID,
295
+ ) -> Run:
296
+ llm_run = self._get_run(run_id)
297
+ retry_d: dict[str, Any] = {
298
+ "slept": retry_state.idle_for,
299
+ "attempt": retry_state.attempt_number,
300
+ }
301
+ if retry_state.outcome is None:
302
+ retry_d["outcome"] = "N/A"
303
+ elif retry_state.outcome.failed:
304
+ retry_d["outcome"] = "failed"
305
+ exception = retry_state.outcome.exception()
306
+ retry_d["exception"] = str(exception)
307
+ retry_d["exception_type"] = exception.__class__.__name__
308
+ else:
309
+ retry_d["outcome"] = "success"
310
+ retry_d["result"] = str(retry_state.outcome.result())
311
+ llm_run.events.append(
312
+ {
313
+ "name": "retry",
314
+ "time": datetime.now(timezone.utc),
315
+ "kwargs": retry_d,
316
+ },
317
+ )
318
+ return llm_run
319
+
320
+ def _complete_llm_run(self, response: LLMResult, run_id: UUID) -> Run:
321
+ llm_run = self._get_run(run_id, run_type={"llm", "chat_model"})
322
+ if getattr(llm_run, "outputs", None) is None:
323
+ llm_run.outputs = {}
324
+ else:
325
+ llm_run.outputs = cast("dict[str, Any]", llm_run.outputs)
326
+ if not llm_run.extra.get("__omit_auto_outputs", False):
327
+ llm_run.outputs.update(response.model_dump())
328
+ for i, generations in enumerate(response.generations):
329
+ for j, generation in enumerate(generations):
330
+ output_generation = llm_run.outputs["generations"][i][j]
331
+ if "message" in output_generation:
332
+ output_generation["message"] = dumpd(
333
+ cast("ChatGeneration", generation).message
334
+ )
335
+ llm_run.end_time = datetime.now(timezone.utc)
336
+ llm_run.events.append({"name": "end", "time": llm_run.end_time})
337
+
338
+ tool_call_count = 0
339
+ for generations in response.generations:
340
+ for generation in generations:
341
+ if hasattr(generation, "message"):
342
+ msg = generation.message
343
+ if hasattr(msg, "tool_calls") and msg.tool_calls:
344
+ tool_call_count += len(msg.tool_calls)
345
+ if tool_call_count > 0:
346
+ llm_run.extra["tool_call_count"] = tool_call_count
347
+
348
+ self._attach_gateway_metadata(llm_run, response)
349
+
350
+ return llm_run
351
+
352
+ def _attach_gateway_metadata(self, run: Run, response: LLMResult) -> None:
353
+ """Promote LangSmith gateway metadata from the response to run metadata."""
354
+ gateway_metadata = _extract_gateway_metadata(response)
355
+ if gateway_metadata is None:
356
+ return
357
+ metadata = run.extra.setdefault("metadata", {})
358
+ metadata[_GATEWAY_RUN_METADATA_KEY] = gateway_metadata
359
+ # The resolved gateway identity takes precedence over request-time metadata.
360
+ for source, target in (("model", "ls_model_name"), ("provider", "ls_provider")):
361
+ value = gateway_metadata.get(source)
362
+ if isinstance(value, str) and (value := value.strip()):
363
+ metadata[target] = value
364
+
365
+ def _errored_llm_run(
366
+ self, error: BaseException, run_id: UUID, response: LLMResult | None = None
367
+ ) -> Run:
368
+ llm_run = self._get_run(run_id, run_type={"llm", "chat_model"})
369
+ llm_run.error = self._get_stacktrace(error)
370
+ if response:
371
+ if getattr(llm_run, "outputs", None) is None:
372
+ llm_run.outputs = {}
373
+ else:
374
+ llm_run.outputs = cast("dict[str, Any]", llm_run.outputs)
375
+ if not llm_run.extra.get("__omit_auto_outputs", False):
376
+ llm_run.outputs.update(response.model_dump())
377
+ for i, generations in enumerate(response.generations):
378
+ for j, generation in enumerate(generations):
379
+ output_generation = llm_run.outputs["generations"][i][j]
380
+ if "message" in output_generation:
381
+ output_generation["message"] = dumpd(
382
+ cast("ChatGeneration", generation).message
383
+ )
384
+ self._attach_gateway_metadata(llm_run, response)
385
+ llm_run.end_time = datetime.now(timezone.utc)
386
+ llm_run.events.append({"name": "error", "time": llm_run.end_time})
387
+
388
+ return llm_run
389
+
390
+ def _create_chain_run(
391
+ self,
392
+ serialized: dict[str, Any],
393
+ inputs: dict[str, Any],
394
+ run_id: UUID,
395
+ tags: list[str] | None = None,
396
+ parent_run_id: UUID | None = None,
397
+ metadata: dict[str, Any] | None = None,
398
+ run_type: str | None = None,
399
+ name: str | None = None,
400
+ **kwargs: Any,
401
+ ) -> Run:
402
+ """Create a chain Run."""
403
+ start_time = datetime.now(timezone.utc)
404
+ if metadata:
405
+ kwargs.update({"metadata": metadata})
406
+ return Run(
407
+ id=run_id,
408
+ parent_run_id=parent_run_id,
409
+ serialized=serialized,
410
+ inputs=self._get_chain_inputs(inputs),
411
+ extra=kwargs,
412
+ events=[{"name": "start", "time": start_time}],
413
+ start_time=start_time,
414
+ child_runs=[],
415
+ run_type=run_type or "chain",
416
+ name=name,
417
+ tags=tags or [],
418
+ )
419
+
420
+ def _get_chain_inputs(self, inputs: Any) -> Any:
421
+ """Get the inputs for a chain run."""
422
+ if self._schema_format in {"original", "original+chat"}:
423
+ return inputs if isinstance(inputs, dict) else {"input": inputs}
424
+ if self._schema_format == "streaming_events":
425
+ return {
426
+ "input": inputs,
427
+ }
428
+ msg = f"Invalid format: {self._schema_format}"
429
+ raise ValueError(msg)
430
+
431
+ def _get_chain_outputs(self, outputs: Any) -> Any:
432
+ """Get the outputs for a chain run."""
433
+ if self._schema_format in {"original", "original+chat"}:
434
+ return outputs if isinstance(outputs, dict) else {"output": outputs}
435
+ if self._schema_format == "streaming_events":
436
+ return {
437
+ "output": outputs,
438
+ }
439
+ msg = f"Invalid format: {self._schema_format}"
440
+ raise ValueError(msg)
441
+
442
+ def _complete_chain_run(
443
+ self,
444
+ outputs: dict[str, Any],
445
+ run_id: UUID,
446
+ inputs: dict[str, Any] | None = None,
447
+ ) -> Run:
448
+ """Update a chain run with outputs and end time."""
449
+ chain_run = self._get_run(run_id)
450
+ if getattr(chain_run, "outputs", None) is None:
451
+ chain_run.outputs = {}
452
+ if not chain_run.extra.get("__omit_auto_outputs", False):
453
+ cast("dict[str, Any]", chain_run.outputs).update(
454
+ self._get_chain_outputs(outputs)
455
+ )
456
+ chain_run.end_time = datetime.now(timezone.utc)
457
+ chain_run.events.append({"name": "end", "time": chain_run.end_time})
458
+ if inputs is not None:
459
+ chain_run.inputs = self._get_chain_inputs(inputs)
460
+ return chain_run
461
+
462
+ def _errored_chain_run(
463
+ self,
464
+ error: BaseException,
465
+ inputs: dict[str, Any] | None,
466
+ run_id: UUID,
467
+ ) -> Run:
468
+ chain_run = self._get_run(run_id)
469
+ chain_run.error = self._get_stacktrace(error)
470
+ chain_run.end_time = datetime.now(timezone.utc)
471
+ chain_run.events.append({"name": "error", "time": chain_run.end_time})
472
+ if inputs is not None:
473
+ chain_run.inputs = self._get_chain_inputs(inputs)
474
+ return chain_run
475
+
476
+ def _create_tool_run(
477
+ self,
478
+ serialized: dict[str, Any],
479
+ input_str: str,
480
+ run_id: UUID,
481
+ tags: list[str] | None = None,
482
+ parent_run_id: UUID | None = None,
483
+ metadata: dict[str, Any] | None = None,
484
+ name: str | None = None,
485
+ inputs: dict[str, Any] | None = None,
486
+ **kwargs: Any,
487
+ ) -> Run:
488
+ """Create a tool run."""
489
+ start_time = datetime.now(timezone.utc)
490
+ if metadata:
491
+ kwargs.update({"metadata": metadata})
492
+
493
+ if self._schema_format in {"original", "original+chat"}:
494
+ inputs = inputs if isinstance(inputs, dict) else {"input": input_str}
495
+ elif self._schema_format == "streaming_events":
496
+ inputs = {"input": inputs}
497
+ else:
498
+ msg = f"Invalid format: {self._schema_format}"
499
+ raise AssertionError(msg)
500
+
501
+ return Run(
502
+ id=run_id,
503
+ parent_run_id=parent_run_id,
504
+ serialized=serialized,
505
+ # Wrapping in dict since Run requires a dict object.
506
+ inputs=inputs,
507
+ extra=kwargs,
508
+ events=[{"name": "start", "time": start_time}],
509
+ start_time=start_time,
510
+ child_runs=[],
511
+ run_type="tool",
512
+ tags=tags or [],
513
+ name=name,
514
+ )
515
+
516
+ def _complete_tool_run(
517
+ self,
518
+ output: dict[str, Any],
519
+ run_id: UUID,
520
+ ) -> Run:
521
+ """Update a tool run with outputs and end time."""
522
+ tool_run = self._get_run(run_id, run_type="tool")
523
+ if getattr(tool_run, "outputs", None) is None:
524
+ tool_run.outputs = {}
525
+ if not tool_run.extra.get("__omit_auto_outputs", False):
526
+ cast("dict[str, Any]", tool_run.outputs).update({"output": output})
527
+ tool_run.end_time = datetime.now(timezone.utc)
528
+ tool_run.events.append({"name": "end", "time": tool_run.end_time})
529
+ return tool_run
530
+
531
+ def _errored_tool_run(
532
+ self,
533
+ error: BaseException,
534
+ run_id: UUID,
535
+ ) -> Run:
536
+ """Update a tool run with error and end time."""
537
+ tool_run = self._get_run(run_id, run_type="tool")
538
+ tool_run.error = self._get_stacktrace(error)
539
+ tool_run.end_time = datetime.now(timezone.utc)
540
+ tool_run.events.append({"name": "error", "time": tool_run.end_time})
541
+ return tool_run
542
+
543
+ def _create_retrieval_run(
544
+ self,
545
+ serialized: dict[str, Any],
546
+ query: str,
547
+ run_id: UUID,
548
+ parent_run_id: UUID | None = None,
549
+ tags: list[str] | None = None,
550
+ metadata: dict[str, Any] | None = None,
551
+ name: str | None = None,
552
+ **kwargs: Any,
553
+ ) -> Run:
554
+ """Create a retrieval run."""
555
+ start_time = datetime.now(timezone.utc)
556
+ if metadata:
557
+ kwargs.update({"metadata": metadata})
558
+ return Run(
559
+ id=run_id,
560
+ name=name or "Retriever",
561
+ parent_run_id=parent_run_id,
562
+ serialized=serialized,
563
+ inputs={"query": query},
564
+ extra=kwargs,
565
+ events=[{"name": "start", "time": start_time}],
566
+ start_time=start_time,
567
+ tags=tags,
568
+ child_runs=[],
569
+ run_type="retriever",
570
+ )
571
+
572
+ def _complete_retrieval_run(
573
+ self,
574
+ documents: Sequence[Document],
575
+ run_id: UUID,
576
+ ) -> Run:
577
+ """Update a retrieval run with outputs and end time."""
578
+ retrieval_run = self._get_run(run_id, run_type="retriever")
579
+ if getattr(retrieval_run, "outputs", None) is None:
580
+ retrieval_run.outputs = {}
581
+ if not retrieval_run.extra.get("__omit_auto_outputs", False):
582
+ cast("dict[str, Any]", retrieval_run.outputs).update(
583
+ {"documents": documents}
584
+ )
585
+ retrieval_run.end_time = datetime.now(timezone.utc)
586
+ retrieval_run.events.append({"name": "end", "time": retrieval_run.end_time})
587
+ return retrieval_run
588
+
589
+ def _errored_retrieval_run(
590
+ self,
591
+ error: BaseException,
592
+ run_id: UUID,
593
+ ) -> Run:
594
+ retrieval_run = self._get_run(run_id, run_type="retriever")
595
+ retrieval_run.error = self._get_stacktrace(error)
596
+ retrieval_run.end_time = datetime.now(timezone.utc)
597
+ retrieval_run.events.append({"name": "error", "time": retrieval_run.end_time})
598
+ return retrieval_run
599
+
600
+ def __deepcopy__(self, memo: dict[int, Any] | None = None) -> _TracerCore:
601
+ """Return self deepcopied."""
602
+ return self
603
+
604
+ def __copy__(self) -> _TracerCore:
605
+ """Return self copied."""
606
+ return self
607
+
608
+ def _end_trace(self, run: Run) -> Coroutine[Any, Any, None] | None:
609
+ """End a trace for a run.
610
+
611
+ Args:
612
+ run: The run.
613
+ """
614
+ _ = run
615
+ return None
616
+
617
+ def _on_run_create(self, run: Run) -> Coroutine[Any, Any, None] | None:
618
+ """Process a run upon creation.
619
+
620
+ Args:
621
+ run: The created run.
622
+ """
623
+ _ = run
624
+ return None
625
+
626
+ def _on_run_update(self, run: Run) -> Coroutine[Any, Any, None] | None:
627
+ """Process a run upon update.
628
+
629
+ Args:
630
+ run: The updated run.
631
+ """
632
+ _ = run
633
+ return None
634
+
635
+ def _on_llm_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
636
+ """Process the LLM Run upon start.
637
+
638
+ Args:
639
+ run: The LLM run.
640
+ """
641
+ _ = run
642
+ return None
643
+
644
+ def _on_llm_new_token(
645
+ self,
646
+ run: Run,
647
+ token: str | list[str | dict[str, Any]],
648
+ chunk: GenerationChunk | ChatGenerationChunk | None,
649
+ ) -> Coroutine[Any, Any, None] | None:
650
+ """Process new LLM token.
651
+
652
+ Args:
653
+ run: The LLM run.
654
+ token: The new token, or a list of content blocks.
655
+ chunk: Optional chunk.
656
+ """
657
+ _ = (run, token, chunk)
658
+ return None
659
+
660
+ def _on_llm_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
661
+ """Process the LLM Run.
662
+
663
+ Args:
664
+ run: The LLM run.
665
+ """
666
+ _ = run
667
+ return None
668
+
669
+ def _on_llm_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
670
+ """Process the LLM Run upon error.
671
+
672
+ Args:
673
+ run: The LLM run.
674
+ """
675
+ _ = run
676
+ return None
677
+
678
+ def _on_chain_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
679
+ """Process the Chain Run upon start.
680
+
681
+ Args:
682
+ run: The chain run.
683
+ """
684
+ _ = run
685
+ return None
686
+
687
+ def _on_chain_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
688
+ """Process the Chain Run.
689
+
690
+ Args:
691
+ run: The chain run.
692
+ """
693
+ _ = run
694
+ return None
695
+
696
+ def _on_chain_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
697
+ """Process the Chain Run upon error.
698
+
699
+ Args:
700
+ run: The chain run.
701
+ """
702
+ _ = run
703
+ return None
704
+
705
+ def _on_tool_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
706
+ """Process the Tool Run upon start.
707
+
708
+ Args:
709
+ run: The tool run.
710
+ """
711
+ _ = run
712
+ return None
713
+
714
+ def _on_tool_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
715
+ """Process the Tool Run.
716
+
717
+ Args:
718
+ run: The tool run.
719
+ """
720
+ _ = run
721
+ return None
722
+
723
+ def _on_tool_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
724
+ """Process the Tool Run upon error.
725
+
726
+ Args:
727
+ run: The tool run.
728
+ """
729
+ _ = run
730
+ return None
731
+
732
+ def _on_chat_model_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
733
+ """Process the Chat Model Run upon start.
734
+
735
+ Args:
736
+ run: The chat model run.
737
+ """
738
+ _ = run
739
+ return None
740
+
741
+ def _on_retriever_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
742
+ """Process the Retriever Run upon start.
743
+
744
+ Args:
745
+ run: The retriever run.
746
+ """
747
+ _ = run
748
+ return None
749
+
750
+ def _on_retriever_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
751
+ """Process the Retriever Run.
752
+
753
+ Args:
754
+ run: The retriever run.
755
+ """
756
+ _ = run
757
+ return None
758
+
759
+ def _on_retriever_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
760
+ """Process the Retriever Run upon error.
761
+
762
+ Args:
763
+ run: The retriever run.
764
+ """
765
+ _ = run
766
+ return None