Skip to content

doc: update READMEs for sync/async #16

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

Merged
merged 1 commit into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
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
1 change: 0 additions & 1 deletion DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Below are the details to set up a development environment and run tests.
## Install
1. Clone the repository:
```bash

git clone https://github.com/googleapis/genai-toolbox-langchain-python
```
1. Navigate to the repo directory:
Expand Down
101 changes: 46 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ applications, enabling advanced orchestration and interaction with GenAI models.
- [Binding Parameters to a Tool](#binding-parameters-to-a-tool)
- [Binding Parameters While Loading](#binding-parameters-while-loading)
- [Binding Dynamic Values](#binding-dynamic-values)
- [Error Handling](#error-handling)
- [Asynchronous Usage](#asynchronous-usage)

<!-- /TOC -->

Expand All @@ -39,21 +39,16 @@ applications, enabling advanced orchestration and interaction with GenAI models.
Here's a minimal example to get you started:

```py
import asyncio
from toolbox_langchain_sdk import ToolboxClient
from langchain_google_vertexai import ChatVertexAI

async def main():
toolbox = ToolboxClient("http://127.0.0.1:5000")
tools = await toolbox.load_toolset()

model = ChatVertexAI(model="gemini-1.5-pro-002")
agent = model.bind_tools(tools)
result = agent.invoke("How's the weather today?")
print(result)
toolbox = ToolboxClient("http://127.0.0.1:5000")
tools = toolbox.load_toolset()

if __name__ == "__main__":
asyncio.run(main())
model = ChatVertexAI(model="gemini-1.5-pro-002")
agent = model.bind_tools(tools)
result = agent.invoke("How's the weather today?")
print(result)
```

## Installation
Expand All @@ -79,18 +74,6 @@ from toolbox_langchain_sdk import ToolboxClient
toolbox = ToolboxClient("http://127.0.0.1:5000")
```

> [!IMPORTANT]
> The toolbox client requires an asynchronous environment.
> For guidance on running asynchronous Python programs, see
> [asyncio documentation](https://docs.python.org/3/library/asyncio-runner.html#running-an-asyncio-program).

> [!TIP]
> You can also pass your own `ClientSession` to reuse the same session:
> ```py
> async with ClientSession() as session:
> toolbox = ToolboxClient("http://localhost:5000", session)
> ```

## Loading Tools

### Load a toolset
Expand All @@ -100,16 +83,16 @@ or a specific one:

```py
# Load all tools
tools = await toolbox.load_toolset()
tools = toolbox.load_toolset()

# Load a specific toolset
tools = await toolbox.load_toolset("my-toolset")
tools = toolbox.load_toolset("my-toolset")
```

### Load a single tool

```py
tool = await toolbox.load_tool("my-tool")
tool = toolbox.load_tool("my-tool")
```

Loading individual tools gives you finer-grained control over which tools are
Expand Down Expand Up @@ -190,10 +173,10 @@ graph.invoke({"messages": [HumanMessage(content="Do something with the tools")]}

## Manual usage

Execute a tool manually using the `ainvoke` method:
Execute a tool manually using the `invoke` method:

```py
result = await tools[0].ainvoke({"name": "Alice", "age": 30})
result = tools[0].invoke({"name": "Alice", "age": 30})
```

This is useful for testing tools or when you need precise control over tool
Expand Down Expand Up @@ -235,8 +218,8 @@ async def get_auth_token():
#### Add Authentication to a Tool

```py
toolbox = ToolboxClient("http://localhost:5000")
tools = await toolbox.load_toolset()
toolbox = ToolboxClient("http://127.0.0.1:5000")
tools = toolbox.load_toolset()

auth_tool = tools[0].add_auth_token("my_auth", get_auth_token) # Single token

Expand All @@ -250,9 +233,9 @@ auth_tools = [tool.add_auth_token("my_auth", get_auth_token) for tool in tools]
#### Add Authentication While Loading

```py
auth_tool = await toolbox.load_tool(auth_tokens={"my_auth": get_auth_token})
auth_tool = toolbox.load_tool(auth_tokens={"my_auth": get_auth_token})

auth_tools = await toolbox.load_toolset(auth_tokens={"my_auth": get_auth_token})
auth_tools = toolbox.load_toolset(auth_tokens={"my_auth": get_auth_token})
```

> [!NOTE]
Expand All @@ -262,24 +245,19 @@ auth_tools = await toolbox.load_toolset(auth_tokens={"my_auth": get_auth_token})
### Complete Example

```py
import asyncio
from toolbox_langchain_sdk import ToolboxClient

async def get_auth_token():
# ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
# This example just returns a placeholder. Replace with your actual token retrieval.
return "YOUR_ID_TOKEN" # Placeholder

async def main():
toolbox = ToolboxClient("http://localhost:5000")
tool = await toolbox.load_tool("my-tool")

auth_tool = tool.add_auth_token("my_auth", get_auth_token)
result = await auth_tool.ainvoke({"input": "some input"})
print(result)
toolbox = ToolboxClient("http://127.0.0.1:5000")
tool = toolbox.load_tool("my-tool")

if __name__ == "__main__":
asyncio.run(main())
auth_tool = tool.add_auth_token("my_auth", get_auth_token)
result = auth_tool.invoke({"input": "some input"})
print(result)
```

## Binding Parameter Values
Expand All @@ -294,8 +272,8 @@ modified by the LLM. This is useful for:
### Binding Parameters to a Tool

```py
toolbox = ToolboxClient("http://localhost:5000")
tools = await toolbox.load_toolset()
toolbox = ToolboxClient("http://127.0.0.1:5000")
tools = toolbox.load_toolset()

bound_tool = tool[0].bind_param("param", "value") # Single param

Expand All @@ -309,9 +287,9 @@ bound_tools = [tool.bind_param("param", "value") for tool in tools]
### Binding Parameters While Loading

```py
bound_tool = await toolbox.load_tool(bound_params={"param": "value"})
bound_tool = toolbox.load_tool(bound_params={"param": "value"})

bound_tools = await toolbox.load_toolset(bound_params={"param": "value"})
bound_tools = toolbox.load_toolset(bound_params={"param": "value"})
```

> [!NOTE]
Expand All @@ -332,15 +310,28 @@ dynamic_bound_tool = tool.bind_param("param", get_dynamic_value)
> [!IMPORTANT]
> You don't need to modify tool configurations to bind parameter values.

## Error Handling
## Asynchronous Usage

For better performance through [cooperative
multitasking](https://en.wikipedia.org/wiki/Cooperative_multitasking), you can
use the asynchronous interfaces of the `ToolboxClient`.

When interacting with the Toolbox service or executing tools, you might
encounter errors. Handle potential exceptions gracefully:
> [!Note]
> Asynchronous interfaces like `aload_tool` and `aload_toolset` require an
> asynchronous environment. For guidance on running asynchronous Python
> programs, see [asyncio
> documentation](https://docs.python.org/3/library/asyncio-runner.html#running-an-asyncio-program).

```py
try:
result = await tool.ainvoke({"input": "some input"})
except Exception as e:
print(f"An error occurred: {e}")
# Implement error recovery logic, e.g., retrying the request or logging the error
import asyncio
from toolbox_langchain_sdk import ToolboxClient

async def main():
toolbox = ToolboxClient("http://127.0.0.1:5000")
tool = await client.aload_tool("my-tool")
tools = await client.aload_toolset()
response = await tool.ainvoke()

if __name__ == "__main__":
asyncio.run(main())
```