Skip to content

Commit dc47da9

Browse files
authored
feat(llamaindex-sdk): Implement OAuth support for LlamaIndex. (#159)
* Update docs for Authenticated Tools. * Implement test cases for OAuth in LlamaIndex. * Sync SDK dependency versions b/w LangChain and LlamaIndex.
1 parent 2e162e8 commit dc47da9

File tree

4 files changed

+37
-34
lines changed

4 files changed

+37
-34
lines changed

README.md

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,32 @@ This SDK allows you to seamlessly integrate the functionalities of
44
[Toolbox](https://github.com/googleapis/genai-toolbox) into your LLM
55
applications, enabling advanced orchestration and interaction with GenAI models.
66

7+
<!-- TOC ignore:true -->
8+
## Table of Contents
79
<!-- TOC -->
810

9-
- [GenAI Toolbox SDK](#genai-toolbox-sdk)
10-
- [Installation](#installation)
11-
- [Usage](#usage)
12-
- [Load a toolset](#load-a-toolset)
13-
- [Load a single tool](#load-a-single-tool)
14-
- [Use with LangChain](#use-with-langchain)
15-
- [Use with LangGraph](#use-with-langgraph)
16-
- [Represent Tools as Nodes](#represent-tools-as-nodes)
17-
- [Connect Tools with LLM](#connect-tools-with-llm)
18-
- [Manual usage](#manual-usage)
19-
- [Authenticating Tools](#authenticating-tools)
20-
- [Supported Authentication Mechanisms](#supported-authentication-mechanisms)
21-
- [Configuring Tools for Authentication](#configuring-tools-for-authentication)
22-
- [Configure SDK for Authentication](#configure-sdk-for-authentication)
23-
- [Complete Example](#complete-example)
11+
- [Installation](#installation)
12+
- [Usage](#usage)
13+
- [Load a toolset](#load-a-toolset)
14+
- [Load a single tool](#load-a-single-tool)
15+
- [Use with LangChain](#use-with-langchain)
16+
- [Use with LangGraph](#use-with-langgraph)
17+
- [Represent Tools as Nodes](#represent-tools-as-nodes)
18+
- [Connect Tools with LLM](#connect-tools-with-llm)
19+
- [Manual usage](#manual-usage)
20+
- [Authenticating Tools](#authenticating-tools)
21+
- [Supported Authentication Mechanisms](#supported-authentication-mechanisms)
22+
- [Configuring Tools for Authentication](#configuring-tools-for-authentication)
23+
- [Configure SDK for Authentication](#configure-sdk-for-authentication)
24+
- [Complete Example](#complete-example)
2425

2526
<!-- /TOC -->
27+
2628
## Installation
2729

2830
> [!IMPORTANT]
29-
> This SDK is not yet available on PyPI. For now, install it from source by following these [installation instructions](DEVELOPER.md).
31+
> This SDK is not yet available on PyPI. For now, install it from source by
32+
> following these [installation instructions](DEVELOPER.md).
3033
3134
You can install the Toolbox SDK for LangChain using `pip`.
3235

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ authors = [
88
{name = "Google LLC", email = "[email protected]"}
99
]
1010
dependencies = [
11-
"aiohttp>=3.7.0,<4.0.0",
1211
"langchain-core>=0.2.23,<1.0.0",
13-
"PyYAML>=6.0.0,<7.0.0",
14-
"pydantic>=2.0,<3.0.0",
12+
"PyYAML>=6.0.1,<7.0.0",
13+
"pydantic>=2.7.0,<3.0.0",
14+
"aiohttp>=3.8.6,<4.0.0",
1515
]
1616

1717
classifiers = [

tests/test_client.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import aiohttp
66
import pytest
77
from langchain_core.tools import StructuredTool
8+
from pydantic import BaseModel
89

910
from toolbox_langchain_sdk import ToolboxClient
1011
from toolbox_langchain_sdk.utils import ManifestSchema, ParameterSchema, ToolSchema
@@ -166,7 +167,7 @@ async def test_load_tool_success(mock_generate_tool, mock_load_manifest):
166167
mock_generate_tool.return_value = StructuredTool(
167168
name="test_tool",
168169
description="This is test tool.",
169-
args_schema=None,
170+
args_schema=BaseModel,
170171
coroutine=AsyncMock(),
171172
)
172173

@@ -201,13 +202,13 @@ async def test_load_toolset_success(mock_generate_tool, mock_load_manifest):
201202
StructuredTool(
202203
name="test_tool",
203204
description="This is test tool.",
204-
args_schema=None,
205+
args_schema=BaseModel,
205206
coroutine=AsyncMock(),
206207
),
207208
StructuredTool(
208209
name="test_tool2",
209210
description="This is test tool 2.",
210-
args_schema=None,
211+
args_schema=BaseModel,
211212
coroutine=AsyncMock(),
212213
),
213214
] * 2

tests/test_utils.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import asyncio
22
import json
3+
import re
34
import warnings
45
from typing import Union
56
from unittest.mock import AsyncMock, Mock, patch
67

78
import aiohttp
89
import pytest
9-
from aiohttp import ClientSession
1010
from pydantic import BaseModel
1111

1212
from toolbox_langchain_sdk.utils import (
@@ -91,8 +91,6 @@ async def test_load_manifest_invalid_json(self, mock_get, mock_manifest):
9191
with pytest.raises(Exception) as e:
9292
session = aiohttp.ClientSession()
9393
await _load_manifest(URL, session)
94-
await session.close()
95-
mock_get.assert_called_once_with(URL)
9694

9795
mock_get.assert_called_once_with(URL)
9896
assert isinstance(e.value, json.JSONDecodeError)
@@ -111,14 +109,12 @@ async def test_load_manifest_invalid_manifest(self, mock_get, mock_manifest):
111109
with pytest.raises(Exception) as e:
112110
session = aiohttp.ClientSession()
113111
await _load_manifest(URL, session)
114-
await session.close()
115-
mock_get.assert_called_once_with(URL)
116112

117113
mock_get.assert_called_once_with(URL)
118114
assert isinstance(e.value, ValueError)
119-
assert (
120-
str(e.value)
121-
== "Invalid JSON data from https://my-toolbox.com/test: 2 validation errors for ManifestSchema\nserverVersion\n Field required [type=missing, input_value={'something': 'invalid'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/missing\ntools\n Field required [type=missing, input_value={'something': 'invalid'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/missing"
115+
assert re.match(
116+
r"Invalid JSON data from https://my-toolbox.com/test: 2 validation errors for ManifestSchema\nserverVersion\n Field required \[type=missing, input_value={'something': 'invalid'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/\d+\.\d+/v/missing\ntools\n Field required \[type=missing, input_value={'something': 'invalid'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/\d+\.\d+/v/missing",
117+
str(e.value),
122118
)
123119

124120
@pytest.mark.asyncio
@@ -132,7 +128,6 @@ async def test_load_manifest_api_error(self, mock_get, mock_manifest):
132128
with pytest.raises(aiohttp.ClientError) as exc_info:
133129
session = aiohttp.ClientSession()
134130
await _load_manifest(URL, session)
135-
await session.close()
136131
mock_get.assert_called_once_with(URL)
137132
assert exc_info.value == error
138133

@@ -180,7 +175,11 @@ async def test_invoke_tool(self, mock_post):
180175
mock_post.return_value.__aenter__.return_value = mock_response
181176

182177
result = await _invoke_tool(
183-
"http://localhost:8000", ClientSession(), "tool_name", {"input": "data"}, {}
178+
"http://localhost:8000",
179+
aiohttp.ClientSession(),
180+
"tool_name",
181+
{"input": "data"},
182+
{},
184183
)
185184

186185
mock_post.assert_called_once_with(
@@ -204,7 +203,7 @@ async def test_invoke_tool_unsecure_with_auth(self, mock_post):
204203
):
205204
result = await _invoke_tool(
206205
"http://localhost:8000",
207-
ClientSession(),
206+
aiohttp.ClientSession(),
208207
"tool_name",
209208
{"input": "data"},
210209
{"my_test_auth": lambda: "fake_id_token"},
@@ -220,7 +219,7 @@ async def test_invoke_tool_unsecure_with_auth(self, mock_post):
220219
@pytest.mark.asyncio
221220
@patch("aiohttp.ClientSession.post")
222221
async def test_invoke_tool_secure_with_auth(self, mock_post):
223-
session = ClientSession()
222+
session = aiohttp.ClientSession()
224223
mock_response = Mock()
225224
mock_response.raise_for_status = Mock()
226225
mock_response.json = AsyncMock(return_value={"key": "value"})

0 commit comments

Comments
 (0)