docs: Update Portkey provider integration (#20412)

**Description:** Updates the documentation for Portkey and Langchain.
Also updates the notebook. The current documentation is fairly old and
is non-functional.
**Twitter handle:** @portkeyai

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
pull/19680/head
Rohit Agarwal 3 months ago committed by GitHub
parent 0758da8940
commit 7d7a08e458
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,113 +1,174 @@
# Portkey
>[Portkey](https://docs.portkey.ai/overview/introduction) is a platform designed to streamline the deployment
> and management of Generative AI applications.
> It provides comprehensive features for monitoring, managing models,
> and improving the performance of your AI applications.
[Portkey](https://portkey.ai) is the Control Panel for AI apps. With it's popular AI Gateway and Observability Suite, hundreds of teams ship **reliable**, **cost-efficient**, and **fast** apps.
## LLMOps for Langchain
Portkey brings production readiness to Langchain. With Portkey, you can
- [x] view detailed **metrics & logs** for all requests,
- [x] enable **semantic cache** to reduce latency & costs,
- [x] implement automatic **retries & fallbacks** for failed requests,
- [x] add **custom tags** to requests for better tracking and analysis and [more](https://docs.portkey.ai).
- [x] Connect to 150+ models through a unified API,
- [x] View 42+ **metrics & logs** for all requests,
- [x] Enable **semantic cache** to reduce latency & costs,
- [x] Implement automatic **retries & fallbacks** for failed requests,
- [x] Add **custom tags** to requests for better tracking and analysis and [more](https://portkey.ai/docs).
### Using Portkey with Langchain
Using Portkey is as simple as just choosing which Portkey features you want, enabling them via `headers=Portkey.Config` and passing it in your LLM calls.
To start, get your Portkey API key by [signing up here](https://app.portkey.ai/login). (Click the profile icon on the top left, then click on "Copy API Key")
## Quickstart - Portkey & Langchain
Since Portkey is fully compatible with the OpenAI signature, you can connect to the Portkey AI Gateway through the `ChatOpenAI` interface.
- Set the `base_url` as `PORTKEY_GATEWAY_URL`
- Add `default_headers` to consume the headers needed by Portkey using the `createHeaders` helper method.
To start, get your Portkey API key by [signing up here](https://app.portkey.ai/signup). (Click the profile icon on the bottom left, then click on "Copy API Key") or deploy the open source AI gateway in [your own environment](https://github.com/Portkey-AI/gateway/blob/main/docs/installation-deployments.md).
Next, install the Portkey SDK
```python
pip install -U portkey_ai
```
We can now connect to the Portkey AI Gateway by updating the `ChatOpenAI` model in Langchain
```python
from langchain_openai import ChatOpenAI
from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL
PORTKEY_API_KEY = "..." # Not needed when hosting your own gateway
PROVIDER_API_KEY = "..." # Add the API key of the AI provider being used
portkey_headers = createHeaders(api_key=PORTKEY_API_KEY,provider="openai")
llm = ChatOpenAI(api_key=PROVIDER_API_KEY, base_url=PORTKEY_GATEWAY_URL, default_headers=portkey_headers)
llm.invoke("What is the meaning of life, universe and everything?")
```
The request is routed through your Portkey AI Gateway to the specified `provider`. Portkey will also start logging all the requests in your account that makes debugging extremely simple.
![View logs from Langchain in Portkey](https://assets.portkey.ai/docs/langchain-logs.gif)
## Using 150+ models through the AI Gateway
The power of the AI gateway comes when you're able to use the above code snippet to connect with 150+ models across 20+ providers supported through the AI gateway.
Let's modify the code above to make a call to Anthropic's `claude-3-opus-20240229` model.
Portkey supports **[Virtual Keys](https://docs.portkey.ai/docs/product/ai-gateway-streamline-llm-integrations/virtual-keys)** which are an easy way to store and manage API keys in a secure vault. Lets try using a Virtual Key to make LLM calls. You can navigate to the Virtual Keys tab in Portkey and create a new key for Anthropic.
The `virtual_key` parameter sets the authentication and provider for the AI provider being used. In our case we're using the Anthropic Virtual key.
> Notice that the `api_key` can be left blank as that authentication won't be used.
For OpenAI, a simple integration with logging feature would look like this:
```python
from langchain_openai import OpenAI
from langchain_community.utilities import Portkey
from langchain_openai import ChatOpenAI
from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL
PORTKEY_API_KEY = "..."
VIRTUAL_KEY = "..." # Anthropic's virtual key we copied above
portkey_headers = createHeaders(api_key=PORTKEY_API_KEY,virtual_key=VIRTUAL_KEY)
llm = ChatOpenAI(api_key="X", base_url=PORTKEY_GATEWAY_URL, default_headers=portkey_headers, model="claude-3-opus-20240229")
llm.invoke("What is the meaning of life, universe and everything?")
```
# Add the Portkey API Key from your account
headers = Portkey.Config(
api_key = "<PORTKEY_API_KEY>"
The Portkey AI gateway will authenticate the API request to Anthropic and get the response back in the OpenAI format for you to consume.
The AI gateway extends Langchain's `ChatOpenAI` class making it a single interface to call any provider and any model.
## Advanced Routing - Load Balancing, Fallbacks, Retries
The Portkey AI Gateway brings capabilities like load-balancing, fallbacks, experimentation and canary testing to Langchain through a configuration-first approach.
Let's take an **example** where we might want to split traffic between `gpt-4` and `claude-opus` 50:50 to test the two large models. The gateway configuration for this would look like the following:
```python
config = {
"strategy": {
"mode": "loadbalance"
},
"targets": [{
"virtual_key": "openai-25654", # OpenAI's virtual key
"override_params": {"model": "gpt4"},
"weight": 0.5
}, {
"virtual_key": "anthropic-25654", # Anthropic's virtual key
"override_params": {"model": "claude-3-opus-20240229"},
"weight": 0.5
}]
}
```
We can then use this config in our requests being made from langchain.
```python
portkey_headers = createHeaders(
api_key=PORTKEY_API_KEY,
config=config
)
llm = OpenAI(temperature=0.9, headers=headers)
llm.predict("What would be a good company name for a company that makes colorful socks?")
llm = ChatOpenAI(api_key="X", base_url=PORTKEY_GATEWAY_URL, default_headers=portkey_headers)
llm.invoke("What is the meaning of life, universe and everything?")
```
Your logs will be captured on your [Portkey dashboard](https://app.portkey.ai).
A common Portkey X Langchain use case is to **trace a chain or an agent** and view all the LLM calls originating from that request.
When the LLM is invoked, Portkey will distribute the requests to `gpt-4` and `claude-3-opus-20240229` in the ratio of the defined weights.
You can find more config examples [here](https://docs.portkey.ai/docs/api-reference/config-object#examples).
## **Tracing Chains & Agents**
### **Tracing Chains & Agents**
Portkey's Langchain integration gives you full visibility into the running of an agent. Let's take an example of a [popular agentic workflow](https://python.langchain.com/docs/use_cases/tool_use/quickstart/#agents).
We only need to modify the `ChatOpenAI` class to use the AI Gateway as above.
```python
from langchain.agents import AgentType, initialize_agent, load_tools
from langchain_openai import OpenAI
from langchain_community.utilities import Portkey
# Add the Portkey API Key from your account
headers = Portkey.Config(
api_key = "<PORTKEY_API_KEY>",
trace_id = "fef659"
from langchain import hub
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
prompt = hub.pull("hwchase17/openai-tools-agent")
portkey_headers = createHeaders(
api_key=PORTKEY_API_KEY,
virtual_key=OPENAI_VIRTUAL_KEY,
trace_id="uuid-uuid-uuid-uuid"
)
llm = OpenAI(temperature=0, headers=headers)
tools = load_tools(["serpapi", "llm-math"], llm=llm)
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
@tool
def multiply(first_int: int, second_int: int) -> int:
"""Multiply two integers together."""
return first_int * second_int
@tool
def exponentiate(base: int, exponent: int) -> int:
"Exponentiate the base to the exponent power."
return base**exponent
tools = [multiply, exponentiate]
model = ChatOpenAI(api_key="X", base_url=PORTKEY_GATEWAY_URL, default_headers=portkey_headers, temperature=0)
# Let's test it out!
agent.run("What was the high temperature in SF yesterday in Fahrenheit? What is that number raised to the .023 power?")
# Construct the OpenAI Tools agent
agent = create_openai_tools_agent(model, tools, prompt)
# Create an agent executor by passing in the agent and tools
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_executor.invoke({
"input": "Take 3 to the fifth power and multiply that by thirty six, then square the result"
})
```
**You can see the requests' logs along with the trace id on Portkey dashboard:**
![Langchain Agent Logs on Portkey](https://assets.portkey.ai/docs/agent_tracing.gif)
<img src="/img/portkey-dashboard.gif" height="250"/>
<img src="/img/portkey-tracing.png" height="250"/>
## Advanced Features
1. **Logging:** Log all your LLM requests automatically by sending them through Portkey. Each request log contains `timestamp`, `model name`, `total cost`, `request time`, `request json`, `response json`, and additional Portkey features.
2. **Tracing:** Trace id can be passed along with each request and is visibe on the logs on Portkey dashboard. You can also set a **distinct trace id** for each request. You can [append user feedback](https://docs.portkey.ai/key-features/feedback-api) to a trace id as well.
3. **Caching:** Respond to previously served customers queries from cache instead of sending them again to OpenAI. Match exact strings OR semantically similar strings. Cache can save costs and reduce latencies by 20x.
4. **Retries:** Automatically reprocess any unsuccessful API requests **`upto 5`** times. Uses an **`exponential backoff`** strategy, which spaces out retry attempts to prevent network overload.
5. **Tagging:** Track and audit each user interaction in high detail with predefined tags.
| Feature | Config Key | Value (Type) | Required/Optional |
| -- | -- | -- | -- |
| API Key | `api_key` | API Key (`string`) | ✅ Required |
| [Tracing Requests](https://docs.portkey.ai/key-features/request-tracing) | `trace_id` | Custom `string` | ❔ Optional |
| [Automatic Retries](https://docs.portkey.ai/key-features/automatic-retries) | `retry_count` | `integer` [1,2,3,4,5] | ❔ Optional |
| [Enabling Cache](https://docs.portkey.ai/key-features/request-caching) | `cache` | `simple` OR `semantic` | ❔ Optional |
| Cache Force Refresh | `cache_force_refresh` | `True` | ❔ Optional |
| Set Cache Expiry | `cache_age` | `integer` (in seconds) | ❔ Optional |
| [Add User](https://docs.portkey.ai/key-features/custom-metadata) | `user` | `string` | ❔ Optional |
| [Add Organisation](https://docs.portkey.ai/key-features/custom-metadata) | `organisation` | `string` | ❔ Optional |
| [Add Environment](https://docs.portkey.ai/key-features/custom-metadata) | `environment` | `string` | ❔ Optional |
| [Add Prompt (version/id/string)](https://docs.portkey.ai/key-features/custom-metadata) | `prompt` | `string` | ❔ Optional |
## **Enabling all Portkey Features:**
```py
headers = Portkey.Config(
# Mandatory
api_key="<PORTKEY_API_KEY>",
# Cache Options
cache="semantic",
cache_force_refresh="True",
cache_age=1729,
# Advanced
retry_count=5,
trace_id="langchain_agent",
# Metadata
environment="production",
user="john",
organisation="acme",
prompt="Frost"
)
```
Additional Docs are available here:
- Observability - https://portkey.ai/docs/product/observability-modern-monitoring-for-llms
- AI Gateway - https://portkey.ai/docs/product/ai-gateway-streamline-llm-integrations
- Prompt Library - https://portkey.ai/docs/product/prompt-library
You can check out our popular Open Source AI Gateway here - https://github.com/portkey-ai/gateway
For detailed information on each feature and how to use it, [please refer to the Portkey docs](https://docs.portkey.ai). If you have any questions or need further assistance, [reach out to us on Twitter.](https://twitter.com/portkeyai).
For detailed information on each feature and how to use it, [please refer to the Portkey docs](https://portkey.ai/docs). If you have any questions or need further assistance, [reach out to us on Twitter.](https://twitter.com/portkeyai) or our [support email](mailto:hello@portkey.ai).

@ -6,7 +6,7 @@
"source": [
"# Log, Trace, and Monitor\n",
"\n",
"When building apps or agents using Langchain, you end up making multiple API calls to fulfill a single user request. However, these requests are not chained when you want to analyse them. With [**Portkey**](/docs/integrations/providers/portkey), all the embeddings, completion, and other requests from a single user request will get logged and traced to a common ID, enabling you to gain full visibility of user interactions.\n",
"When building apps or agents using Langchain, you end up making multiple API calls to fulfill a single user request. However, these requests are not chained when you want to analyse them. With [**Portkey**](/docs/integrations/providers/portkey/), all the embeddings, completions, and other requests from a single user request will get logged and traced to a common ID, enabling you to gain full visibility of user interactions.\n",
"\n",
"This notebook serves as a step-by-step guide on how to log, trace, and monitor Langchain LLM calls using `Portkey` in your Langchain app."
]
@ -20,15 +20,15 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"from langchain.agents import AgentType, initialize_agent, load_tools\n",
"from langchain_community.utilities import Portkey\n",
"from langchain_openai import OpenAI"
"from langchain.agents import AgentExecutor, create_openai_tools_agent\n",
"from langchain_openai import ChatOpenAI\n",
"from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders"
]
},
{
@ -40,11 +40,11 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"os.environ[\"OPENAI_API_KEY\"] = \"<OPENAI_API_KEY>\""
"os.environ[\"OPENAI_API_KEY\"] = \"...\""
]
},
{
@ -52,18 +52,18 @@
"metadata": {},
"source": [
"## Get Portkey API Key\n",
"1. Sign up for [Portkey here](https://app.portkey.ai/login)\n",
"2. On your [dashboard](https://app.portkey.ai/), click on the profile icon on the top left, then click on \"Copy API Key\"\n",
"1. Sign up for [Portkey here](https://app.portkey.ai/signup)\n",
"2. On your [dashboard](https://app.portkey.ai/), click on the profile icon on the bottom left, then click on \"Copy API Key\"\n",
"3. Paste it below"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"PORTKEY_API_KEY = \"<PORTKEY_API_KEY>\" # Paste your Portkey API Key here"
"PORTKEY_API_KEY = \"...\" # Paste your Portkey API Key here"
]
},
{
@ -77,11 +77,11 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"TRACE_ID = \"portkey_langchain_demo\" # Set trace id here"
"TRACE_ID = \"uuid-trace-id\" # Set trace id here"
]
},
{
@ -93,13 +93,12 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"headers = Portkey.Config(\n",
" api_key=PORTKEY_API_KEY,\n",
" trace_id=TRACE_ID,\n",
"portkey_headers = createHeaders(\n",
" api_key=PORTKEY_API_KEY, provider=\"openai\", trace_id=TRACE_ID\n",
")"
]
},
@ -107,24 +106,99 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Run your agent as usual. The **only** change is that we will **include the above headers** in the request now."
"Define the prompts and the tools to use"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"llm = OpenAI(temperature=0, headers=headers)\n",
"tools = load_tools([\"serpapi\", \"llm-math\"], llm=llm)\n",
"agent = initialize_agent(\n",
" tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True\n",
"from langchain import hub\n",
"from langchain_core.tools import tool\n",
"\n",
"prompt = hub.pull(\"hwchase17/openai-tools-agent\")\n",
"\n",
"\n",
"@tool\n",
"def multiply(first_int: int, second_int: int) -> int:\n",
" \"\"\"Multiply two integers together.\"\"\"\n",
" return first_int * second_int\n",
"\n",
"\n",
"@tool\n",
"def exponentiate(base: int, exponent: int) -> int:\n",
" \"Exponentiate the base to the exponent power.\"\n",
" return base**exponent\n",
"\n",
"\n",
"tools = [multiply, exponentiate]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Run your agent as usual. The **only** change is that we will **include the above headers** in the request now."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3m\n",
"Invoking: `exponentiate` with `{'base': 3, 'exponent': 5}`\n",
"\n",
"\n",
"\u001b[0m\u001b[33;1m\u001b[1;3m243\u001b[0m\u001b[32;1m\u001b[1;3m\n",
"Invoking: `multiply` with `{'first_int': 243, 'second_int': 36}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m8748\u001b[0m\u001b[32;1m\u001b[1;3m\n",
"Invoking: `exponentiate` with `{'base': 8748, 'exponent': 2}`\n",
"\n",
"\n",
"\u001b[0m\u001b[33;1m\u001b[1;3m76527504\u001b[0m\u001b[32;1m\u001b[1;3mThe result of taking 3 to the fifth power, multiplying it by 36, and then squaring the result is 76,527,504.\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'input': 'Take 3 to the fifth power and multiply that by thirty six, then square the result',\n",
" 'output': 'The result of taking 3 to the fifth power, multiplying it by 36, and then squaring the result is 76,527,504.'}"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = ChatOpenAI(\n",
" base_url=PORTKEY_GATEWAY_URL, default_headers=portkey_headers, temperature=0\n",
")\n",
"\n",
"# Let's test it out!\n",
"agent.run(\n",
" \"What was the high temperature in SF yesterday in Fahrenheit? What is that number raised to the .023 power?\"\n",
"# Construct the OpenAI Tools agent\n",
"agent = create_openai_tools_agent(model, tools, prompt)\n",
"\n",
"# Create an agent executor by passing in the agent and tools\n",
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n",
"\n",
"agent_executor.invoke(\n",
" {\n",
" \"input\": \"Take 3 to the fifth power and multiply that by thirty six, then square the result\"\n",
" }\n",
")"
]
},
@ -138,10 +212,13 @@
"- Sending your request through Portkey ensures that all of the requests are logged by default\n",
"- Each request log contains `timestamp`, `model name`, `total cost`, `request time`, `request json`, `response json`, and additional Portkey features\n",
"\n",
"**Tracing**\n",
"- Trace id is passed along with each request and is visibe on the logs on Portkey dashboard\n",
"**[Tracing](https://portkey.ai/docs/product/observability-modern-monitoring-for-llms/traces)**\n",
"- Trace id is passed along with each request and is visible on the logs on Portkey dashboard\n",
"- You can also set a **distinct trace id** for each request if you want\n",
"- You can append user feedback to a trace id as well. [More info on this here](https://docs.portkey.ai/key-features/feedback-api)"
"- You can append user feedback to a trace id as well. [More info on this here](https://portkey.ai/docs/product/observability-modern-monitoring-for-llms/feedback)\n",
"\n",
"For the above request, you will be able to view the entire log trace like this\n",
"![View Langchain traces on Portkey](https://assets.portkey.ai/docs/agent_tracing.gif)"
]
},
{
@ -154,62 +231,15 @@
"\n",
"**Caching**\n",
"\n",
"Respond to previously served customers queries from cache instead of sending them again to OpenAI. Match exact strings OR semantically similar strings. Cache can save costs and reduce latencies by 20x.\n",
"Respond to previously served customers queries from cache instead of sending them again to OpenAI. Match exact strings OR semantically similar strings. Cache can save costs and reduce latencies by 20x. [Docs](https://portkey.ai/docs/product/ai-gateway-streamline-llm-integrations/cache-simple-and-semantic)\n",
"\n",
"**Retries**\n",
"\n",
"Automatically reprocess any unsuccessful API requests **`upto 5`** times. Uses an **`exponential backoff`** strategy, which spaces out retry attempts to prevent network overload.\n",
"\n",
"| Feature | Config Key | Value (Type) |\n",
"| -- | -- | -- |\n",
"| [🔁 Automatic Retries](https://docs.portkey.ai/key-features/automatic-retries) | `retry_count` | `integer` [1,2,3,4,5] |\n",
"| [🧠 Enabling Cache](https://docs.portkey.ai/key-features/request-caching) | `cache` | `simple` OR `semantic` |\n",
"Automatically reprocess any unsuccessful API requests **`upto 5`** times. Uses an **`exponential backoff`** strategy, which spaces out retry attempts to prevent network overload.[Docs](https://portkey.ai/docs/product/ai-gateway-streamline-llm-integrations)\n",
"\n",
"**Tagging**\n",
"\n",
"Track and audit ach user interaction in high detail with predefined tags.\n",
"\n",
"| Tag | Config Key | Value (Type) |\n",
"| -- | -- | -- |\n",
"| User Tag | `user` | `string` |\n",
"| Organisation Tag | `organisation` | `string` |\n",
"| Environment Tag | `environment` | `string` |\n",
"| Prompt Tag (version/id/string) | `prompt` | `string` |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Code Example With All Features"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"headers = Portkey.Config(\n",
" # Mandatory\n",
" api_key=\"<PORTKEY_API_KEY>\",\n",
" # Cache Options\n",
" cache=\"semantic\",\n",
" cache_force_refresh=\"True\",\n",
" cache_age=1729,\n",
" # Advanced\n",
" retry_count=5,\n",
" trace_id=\"langchain_agent\",\n",
" # Metadata\n",
" environment=\"production\",\n",
" user=\"john\",\n",
" organisation=\"acme\",\n",
" prompt=\"Frost\",\n",
")\n",
"\n",
"llm = OpenAI(temperature=0.9, headers=headers)\n",
"\n",
"print(llm(\"Two roads diverged in the yellow woods\"))"
"Track and audit each user interaction in high detail with predefined tags. [Docs](https://portkey.ai/docs/product/observability-modern-monitoring-for-llms/metadata)"
]
}
],
@ -229,7 +259,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
"version": "3.9.1"
}
},
"nbformat": 4,

Loading…
Cancel
Save