Skip to content

chore(examples): improve llama-index calling apis example #33

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 2 commits into from
May 9, 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
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"poetryMonorepo.appendExtraPaths": true,
"python.analysis.extraPaths": [
"examples/calling-apis/langchain-examples",
"examples/calling-apis/llama-index-examples",
"examples/async-user-confirmation/langchain-examples/src",
"examples/async-user-confirmation/llama-index-examples/src",
"examples/async-user-confirmation/sample-api",
"examples/authorization-for-rag/langchain-examples/langchain_rag",
"examples/authorization-for-rag/llama-index-examples/llama_index_rag",
"examples/authorization-for-tools/langchain-examples/src",
"examples/authorization-for-tools/llama-index-examples/src",
"examples/calling-apis/langchain-examples/src",
"examples/calling-apis/llama-index-examples/src",
"packages/auth0-ai/auth0_ai/auth0_ai",
"packages/auth0-ai-langchain/auth0_ai_langchain/auth0_ai_langchain",
"packages/auth0-ai-llamaindex/auth0_ai_llamaindex/auth0_ai_llamaindex"
Expand Down
2 changes: 2 additions & 0 deletions examples/calling-apis/llama-index-examples/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
AUTH0_DOMAIN="<auth0-domain>"
AUTH0_CLIENT_ID="<auth0-client-id>"
AUTH0_CLIENT_SECRET="<auth0-client-secret>"
APP_BASE_URL="http://localhost:3000"
APP_SECRET_KEY="<use [openssl rand -hex 32] to generate a 32 bytes value>"

# OpenAI
OPENAI_API_KEY="<openai-api-key>"
35 changes: 21 additions & 14 deletions examples/calling-apis/llama-index-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,30 @@

- An OpenAI account and API key create one [here](https://platform.openai.com).
- [Use this page for instructions on how to find your OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key).
- A [Google OAuth 2.0 Client](https://console.cloud.google.com/apis/credentials) configured with access to the `https://www.googleapis.com/auth/calendar.freebusy` scope (Google Calendar API).
- An [Auth0](https://manage.auth0.com/) account with the following configuration:
- **Google connection** set up with:
- The client ID and secret from the previously created Google client.
- The following settings:
- **Offline access** enabled.
- **https://www.googleapis.com/auth/calendar.freebusy** scope granted.
- **Token Vault** enabled.
- **Regular Web Application** set up with:
- **Allowed Callback URLs**: `http://localhost:3000/login/callback`
- **Allowed Logout URLs**: `http://localhost:3000/`
- **Connections**: The previously created **Google connection**.
- **Advanced Settings -> Grant Types**: **Token Exchange (Federated Connection)** and **Refresh Token**.
- An **[Auth0](https://auth0.com)** account and the following settings and resources configured:
- An application to initiate the authorization flow:
- **Application Type**: `Regular Web Application`
- **Allowed Callback URLs**: `http://localhost:3000/auth/callback`
- **Allowed Logout URLs**: `http://localhost:3000`
- **Advanced Settings -> Grant Types**: `Refresh Token` and `Token Exchange (Federated Connection)` (or `urn:auth0:params:oauth:grant-type:token-exchange:federated-connection-access-token`)
- Either **Google**, **Slack** or **Github** social connections enabled for the application:
- **Google connection** set up instructions:
- Create a [Google OAuth 2.0 Client](https://console.cloud.google.com/apis/credentials) configured with access to the `https://www.googleapis.com/auth/calendar.freebusy` scope (Google Calendar API).
- On Auth0 Dashboard, set up the client ID and secret from the previously created Google client.
- Enable following settings:
- **Offline access** enabled.
- **https://www.googleapis.com/auth/calendar.freebusy** scope granted.
- **Token Vault** enabled.
- **Slack connection** set up instructions:
- Create a [Slack App](https://api.slack.com/apps) and follow the [Auth0's Signin with Slack](https://marketplace.auth0.com/integrations/sign-in-with-slack) `installation` instructions to set up the connection.
- On Slack's OAuth & Permission settings, make sure to add the `channels:read` scope to the User Token scopes.
- **Github connection** set up instructions:
- Register a new app in [GitHub Developer Settings: OAuth Apps](https://github.com/settings/developers#oauth-apps) and follow the [Auth0's Github social connection](https://marketplace.auth0.com/integrations/github-social-connection) `installation` instructions to set up the connection.
- On Auth0 Dashboard, set up the client ID and secret from the previously created Github App.

### Setup

Create a `.env` file using the format below:
Copy the file `.env.example` to `.env` and fill in the required values:

```sh
# Auth0
Expand Down
105 changes: 102 additions & 3 deletions examples/calling-apis/llama-index-examples/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion examples/calling-apis/llama-index-examples/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ python = "^3.11"
python-dotenv = "^1.0.1"
flask = { extras = ["async"], version = "^3.1.0" }
requests = "^2.32.3"
authlib = "^1.5.1"
hypercorn = "^0.17.3"
llama-index = "^0.12.33"
llama-index-agent-openai = "^0.4.6"
auth0-server-python = "^1.0.0b4"
auth0-ai-llamaindex = { path = "../../../packages/auth0-ai-llamaindex", develop = true }
slack-sdk = "^3.35.0"
pygithub = "^2.6.1"
asgiref = "^3.8.1"

[build-system]
requires = ["poetry-core"]
Expand Down
6 changes: 3 additions & 3 deletions examples/calling-apis/llama-index-examples/scripts/start.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import asyncio
from asgiref.wsgi import WsgiToAsgi
from hypercorn.config import Config
from hypercorn.asyncio import serve
from src.app.app import app


def main():
config = Config()
config.bind = ["0.0.0.0:3000"]
config.worker_class = "asyncio"
config.use_reloader = True

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(serve(app, config))
asyncio.run(serve(WsgiToAsgi(app), config))
25 changes: 25 additions & 0 deletions examples/calling-apis/llama-index-examples/src/agents/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from datetime import datetime
from llama_index.agent.openai import OpenAIAgent

from .memory import get_memory
from .tools.check_user_calendar import check_user_calendar_tool
from .tools.list_channels import list_slack_channels_tool
from .tools.list_repositories import list_github_repositories_tool


system_prompt = f"""You are an assistant designed to answer random user's questions.
**Additional Guidelines**:
- Today’s date for reference: {datetime.now().isoformat()}
"""


async def get_agent(user_id: str, chat_id: str):
chat_memory = await get_memory(user_id, chat_id)
return OpenAIAgent.from_tools(
model="gpt-4o",
memory=chat_memory,
system_prompt=system_prompt,
tools=[check_user_calendar_tool, list_github_repositories_tool,
list_slack_channels_tool],
verbose=True
)
12 changes: 12 additions & 0 deletions examples/calling-apis/llama-index-examples/src/agents/memory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from llama_index.core.storage.chat_store import SimpleChatStore
from llama_index.core.memory import ChatMemoryBuffer

chat_store = SimpleChatStore()


async def get_memory(user_id: str, chat_id: str):
return ChatMemoryBuffer.from_defaults(
token_limit=3000,
chat_store=chat_store,
chat_store_key=f"{user_id}_{chat_id}",
)
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import requests
from datetime import datetime, timedelta
from typing import Annotated

import requests
from auth0_ai_llamaindex.federated_connections import (
FederatedConnectionError,
get_credentials_for_connection,
)
from llama_index.core.tools import FunctionTool

from auth0_ai_llamaindex.federated_connections import FederatedConnectionError, get_credentials_for_connection
from src.auth0.auth0_ai import with_calendar_free_busy_access


def add_hours(dt: datetime, hours: int) -> str:
return (dt + timedelta(hours=hours)).isoformat()
Expand All @@ -31,7 +29,8 @@ def check_user_calendar_tool_function(

response = requests.post(
url,
headers={"Authorization": f"{credentials["token_type"]} {credentials["access_token"]}"},
headers={
"Authorization": f"{credentials["token_type"]} {credentials["access_token"]}"},
json=body
)

Expand All @@ -46,8 +45,8 @@ def check_user_calendar_tool_function(
return {"available": len(busy_resp["calendars"]["primary"]["busy"]) == 0}


check_user_calendar_tool = FunctionTool.from_defaults(
check_user_calendar_tool = with_calendar_free_busy_access(FunctionTool.from_defaults(
name="check_user_calendar",
description="Use this function to check if the user is available on a certain date and time",
fn=check_user_calendar_tool_function,
)
))
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from llama_index.core.tools import FunctionTool

from auth0_ai_llamaindex.federated_connections import get_credentials_for_connection, FederatedConnectionError
from src.auth0.auth0_ai import with_slack_access


def list_channels_tool_function():
# Get the access token from Auth0 AI
credentials = get_credentials_for_connection()

# Slack SDK
try:
client = WebClient(token=credentials["access_token"])
response = client.conversations_list(
exclude_archived=True,
types="public_channel,private_channel",
limit=10
)
channels = response['channels']
channel_names = [channel['name'] for channel in channels]
return channel_names
except SlackApiError as e:
if e.response['error'] == 'not_authed':
raise FederatedConnectionError(
"Authorization required to access the Federated Connection API")

raise ValueError(f"An error occurred: {e.response['error']}")


list_slack_channels_tool = with_slack_access(FunctionTool.from_defaults(
name="list_slack_channels",
description="List channels for the current user on Slack",
fn=list_channels_tool_function,
))
Loading