Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs[patch]: Adds docs for dispatching custom events #6088

Merged
merged 4 commits into from
Jul 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 230 additions & 0 deletions docs/core_docs/docs/how_to/callbacks_custom_events.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# How to dispatch custom callback events\n",
"\n",
":::info Prerequisites\n",
"\n",
"This guide assumes familiarity with the following concepts:\n",
"\n",
"- [Callbacks](/docs/concepts/#callbacks)\n",
"- [Custom callback handlers](/docs/how_to/custom_callbacks)\n",
"- [Stream Events API](/docs/concepts#streamevents)\n",
"\n",
":::\n",
"\n",
"In some situations, you may want to dipsatch a custom callback event from within a [Runnable](/docs/concepts/#runnable-interface) so it can be surfaced\n",
"in a custom callback handler or via the [Stream Events API](/docs/concepts/#streamevents).\n",
"\n",
"For example, if you have a long running tool with multiple steps, you can dispatch custom events between the steps and use these custom events to monitor progress.\n",
"You could also surface these custom events to an end user of your application to show them how the current task is progressing.\n",
"\n",
"To dispatch a custom event you need to decide on two attributes for the event: the `name` and the `data`.\n",
"\n",
"| Attribute | Type | Description |\n",
"|-----------|------|----------------------------------------------------------------------------------------------------------|\n",
"| name | string | A user defined name for the event. |\n",
"| data | any | The data associated with the event. This can be anything, though we suggest making it JSON serializable. |\n",
"\n",
"\n",
":::info\n",
"- Custom callback events can only be dispatched from within an existing `Runnable`.\n",
"- If using `streamEvents`, you must use `version: \"v2\"` to consume custom events.\n",
"- Sending or rendering custom callback events in LangSmith is not yet supported.\n",
":::\n",
"\n",
"## Stream Events API\n",
"\n",
"The most useful way to consume custom events is via the [`.streamEvents()`](/docs/concepts/#streamevents) method.\n",
"\n",
"We can use the `dispatchCustomEvent` API to emit custom events from this method. \n",
"\n",
":::caution Compatibility\n",
"Dispatching custom callback events requires `@langchain/core>=0.2.16`. See [this guide](/docs/how_to/installation/#installing-integration-packages) for some considerations to take when upgrading `@langchain/core`.\n",
"\n",
"The default entrypoint below triggers an import and initialization of [`async_hooks`](https://nodejs.org/api/async_hooks.html) to enable automatic `RunnableConfig` passing, which is not supported in all environments. If you see import issues, you must import from `@langchain/callbacks/dispatch/web` and propagate the `RunnableConfig` object manually (see example below).\n",
":::"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" event: 'on_custom_event',\n",
" run_id: '9eac217d-3a2d-4563-a91f-3bd49bee4b3d',\n",
" name: 'event1',\n",
" tags: [],\n",
" metadata: {},\n",
" data: { reversed: 'dlrow olleh' }\n",
"}\n",
"{\n",
" event: 'on_custom_event',\n",
" run_id: '9eac217d-3a2d-4563-a91f-3bd49bee4b3d',\n",
" name: 'event2',\n",
" tags: [],\n",
" metadata: {},\n",
" data: 5\n",
"}\n"
]
}
],
"source": [
"import { RunnableLambda } from \"@langchain/core/runnables\";\n",
"import { dispatchCustomEvent } from \"@langchain/core/callbacks/dispatch\";\n",
"\n",
"const reflect = RunnableLambda.from(async (value: string) => {\n",
" await dispatchCustomEvent(\"event1\", { reversed: value.split(\"\").reverse().join(\"\") });\n",
" await dispatchCustomEvent(\"event2\", 5);\n",
" return value;\n",
"});\n",
"\n",
"const eventStream = await reflect.streamEvents(\"hello world\", { version: \"v2\" });\n",
"\n",
"for await (const event of eventStream) {\n",
" if (event.event === \"on_custom_event\") {\n",
" console.log(event);\n",
" }\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you are in a web environment that does not support `async_hooks`, you must import from the web entrypoint and propagate the config manually instead:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" event: 'on_custom_event',\n",
" run_id: 'dee1e4f0-c5ff-4118-9391-461a0dcc4cb2',\n",
" name: 'event1',\n",
" tags: [],\n",
" metadata: {},\n",
" data: { reversed: 'dlrow olleh' }\n",
"}\n",
"{\n",
" event: 'on_custom_event',\n",
" run_id: 'dee1e4f0-c5ff-4118-9391-461a0dcc4cb2',\n",
" name: 'event2',\n",
" tags: [],\n",
" metadata: {},\n",
" data: 5\n",
"}\n"
]
}
],
"source": [
"import { RunnableConfig, RunnableLambda } from \"@langchain/core/runnables\";\n",
"import { dispatchCustomEvent as dispatchCustomEventWeb } from \"@langchain/core/callbacks/dispatch/web\";\n",
"\n",
"const reflect = RunnableLambda.from(async (value: string, config?: RunnableConfig) => {\n",
" await dispatchCustomEventWeb(\"event1\", { reversed: value.split(\"\").reverse().join(\"\") }, config);\n",
" await dispatchCustomEventWeb(\"event2\", 5, config);\n",
" return value;\n",
"});\n",
"\n",
"const eventStream = await reflect.streamEvents(\"hello world\", { version: \"v2\" });\n",
"\n",
"for await (const event of eventStream) {\n",
" if (event.event === \"on_custom_event\") {\n",
" console.log(event);\n",
" }\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Callback Handler\n",
"\n",
"Let's see how to emit custom events with `dispatchCustomEvent`.\n",
"\n",
"Remember, you **must** call `dispatchCustomEvent` from within an existing `Runnable`."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"event1 { reversed: 'dlrow olleh' } 9c3770ac-c83d-4626-9643-b5fd80eb5431\n",
"event2 5 9c3770ac-c83d-4626-9643-b5fd80eb5431\n",
"hello world\n"
]
}
],
"source": [
"import { RunnableConfig, RunnableLambda } from \"@langchain/core/runnables\";\n",
"import { dispatchCustomEvent } from \"@langchain/core/callbacks/dispatch\";\n",
"\n",
"const reflect = RunnableLambda.from(async (value: string) => {\n",
" await dispatchCustomEvent(\"event1\", { reversed: value.split(\"\").reverse().join(\"\") });\n",
" await dispatchCustomEvent(\"event2\", 5);\n",
" return value;\n",
"});\n",
"\n",
"await reflect.invoke(\"hello world\", {\n",
" callbacks: [{\n",
" handleCustomEvent(eventName, data, runId) {\n",
" console.log(eventName, data, runId);\n",
" },\n",
" }]\n",
"});"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Related\n",
"\n",
"You've now seen how to emit custom events from within your chains.\n",
"\n",
"You can check out the more in depth guide for [stream events](/docs/how_to/streaming/#using-stream-events) for more ways to parse and receive intermediate steps from your chains."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "TypeScript",
"language": "typescript",
"name": "tslab"
},
"language_info": {
"codemirror_mode": {
"mode": "typescript",
"name": "javascript",
"typescript": true
},
"file_extension": ".ts",
"mimetype": "text/typescript",
"name": "typescript",
"version": "3.7.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Loading