forked from phoenix/litellm-mirror
Merge branch 'BerriAI:main' into main
This commit is contained in:
commit
c8b8f93184
50 changed files with 792 additions and 382 deletions
|
@ -3,8 +3,6 @@ import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
# Azure AI Studio
|
# Azure AI Studio
|
||||||
|
|
||||||
## Sample Usage
|
|
||||||
|
|
||||||
**Ensure the following:**
|
**Ensure the following:**
|
||||||
1. The API Base passed ends in the `/v1/` prefix
|
1. The API Base passed ends in the `/v1/` prefix
|
||||||
example:
|
example:
|
||||||
|
@ -14,8 +12,11 @@ import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
2. The `model` passed is listed in [supported models](#supported-models). You **DO NOT** Need to pass your deployment name to litellm. Example `model=azure/Mistral-large-nmefg`
|
2. The `model` passed is listed in [supported models](#supported-models). You **DO NOT** Need to pass your deployment name to litellm. Example `model=azure/Mistral-large-nmefg`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem value="sdk" label="SDK">
|
||||||
|
|
||||||
**Quick Start**
|
|
||||||
```python
|
```python
|
||||||
import litellm
|
import litellm
|
||||||
response = litellm.completion(
|
response = litellm.completion(
|
||||||
|
@ -26,6 +27,9 @@ response = litellm.completion(
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="proxy" label="PROXY">
|
||||||
|
|
||||||
## Sample Usage - LiteLLM Proxy
|
## Sample Usage - LiteLLM Proxy
|
||||||
|
|
||||||
1. Add models to your config.yaml
|
1. Add models to your config.yaml
|
||||||
|
@ -99,6 +103,107 @@ response = litellm.completion(
|
||||||
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Function Calling
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem value="sdk" label="SDK">
|
||||||
|
|
||||||
|
```python
|
||||||
|
from litellm import completion
|
||||||
|
|
||||||
|
# set env
|
||||||
|
os.environ["AZURE_MISTRAL_API_KEY"] = "your-api-key"
|
||||||
|
os.environ["AZURE_MISTRAL_API_BASE"] = "your-api-base"
|
||||||
|
|
||||||
|
tools = [
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_current_weather",
|
||||||
|
"description": "Get the current weather in a given location",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The city and state, e.g. San Francisco, CA",
|
||||||
|
},
|
||||||
|
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
|
||||||
|
},
|
||||||
|
"required": ["location"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
messages = [{"role": "user", "content": "What's the weather like in Boston today?"}]
|
||||||
|
|
||||||
|
response = completion(
|
||||||
|
model="azure/mistral-large-latest",
|
||||||
|
api_base=os.getenv("AZURE_MISTRAL_API_BASE")
|
||||||
|
api_key=os.getenv("AZURE_MISTRAL_API_KEY")
|
||||||
|
messages=messages,
|
||||||
|
tools=tools,
|
||||||
|
tool_choice="auto",
|
||||||
|
)
|
||||||
|
# Add any assertions, here to check response args
|
||||||
|
print(response)
|
||||||
|
assert isinstance(response.choices[0].message.tool_calls[0].function.name, str)
|
||||||
|
assert isinstance(
|
||||||
|
response.choices[0].message.tool_calls[0].function.arguments, str
|
||||||
|
)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem value="proxy" label="PROXY">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://0.0.0.0:4000/v1/chat/completions \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $YOUR_API_KEY" \
|
||||||
|
-d '{
|
||||||
|
"model": "mistral",
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "What'\''s the weather like in Boston today?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_current_weather",
|
||||||
|
"description": "Get the current weather in a given location",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The city and state, e.g. San Francisco, CA"
|
||||||
|
},
|
||||||
|
"unit": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["celsius", "fahrenheit"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["location"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tool_choice": "auto"
|
||||||
|
}'
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
## Supported Models
|
## Supported Models
|
||||||
|
|
||||||
| Model Name | Function Call |
|
| Model Name | Function Call |
|
||||||
|
|
|
@ -50,6 +50,7 @@ All models listed here https://docs.mistral.ai/platform/endpoints are supported.
|
||||||
| mistral-small | `completion(model="mistral/mistral-small", messages)` |
|
| mistral-small | `completion(model="mistral/mistral-small", messages)` |
|
||||||
| mistral-medium | `completion(model="mistral/mistral-medium", messages)` |
|
| mistral-medium | `completion(model="mistral/mistral-medium", messages)` |
|
||||||
| mistral-large-latest | `completion(model="mistral/mistral-large-latest", messages)` |
|
| mistral-large-latest | `completion(model="mistral/mistral-large-latest", messages)` |
|
||||||
|
| open-mixtral-8x22b | `completion(model="mistral/open-mixtral-8x22b", messages)` |
|
||||||
|
|
||||||
|
|
||||||
## Sample Usage - Embedding
|
## Sample Usage - Embedding
|
||||||
|
|
|
@ -253,6 +253,7 @@ litellm.vertex_location = "us-central1 # Your Location
|
||||||
## Anthropic
|
## Anthropic
|
||||||
| Model Name | Function Call |
|
| Model Name | Function Call |
|
||||||
|------------------|--------------------------------------|
|
|------------------|--------------------------------------|
|
||||||
|
| claude-3-opus@20240229 | `completion('vertex_ai/claude-3-opus@20240229', messages)` |
|
||||||
| claude-3-sonnet@20240229 | `completion('vertex_ai/claude-3-sonnet@20240229', messages)` |
|
| claude-3-sonnet@20240229 | `completion('vertex_ai/claude-3-sonnet@20240229', messages)` |
|
||||||
| claude-3-haiku@20240307 | `completion('vertex_ai/claude-3-haiku@20240307', messages)` |
|
| claude-3-haiku@20240307 | `completion('vertex_ai/claude-3-haiku@20240307', messages)` |
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,60 @@ class VertexAIConfig:
|
||||||
and v is not None
|
and v is not None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_supported_openai_params(self):
|
||||||
|
return [
|
||||||
|
"temperature",
|
||||||
|
"top_p",
|
||||||
|
"max_tokens",
|
||||||
|
"stream",
|
||||||
|
"tools",
|
||||||
|
"tool_choice",
|
||||||
|
"response_format",
|
||||||
|
"n",
|
||||||
|
"stop",
|
||||||
|
]
|
||||||
|
|
||||||
|
def map_openai_params(self, non_default_params: dict, optional_params: dict):
|
||||||
|
for param, value in non_default_params.items():
|
||||||
|
if param == "temperature":
|
||||||
|
optional_params["temperature"] = value
|
||||||
|
if param == "top_p":
|
||||||
|
optional_params["top_p"] = value
|
||||||
|
if param == "stream":
|
||||||
|
optional_params["stream"] = value
|
||||||
|
if param == "n":
|
||||||
|
optional_params["candidate_count"] = value
|
||||||
|
if param == "stop":
|
||||||
|
if isinstance(value, str):
|
||||||
|
optional_params["stop_sequences"] = [value]
|
||||||
|
elif isinstance(value, list):
|
||||||
|
optional_params["stop_sequences"] = value
|
||||||
|
if param == "max_tokens":
|
||||||
|
optional_params["max_output_tokens"] = value
|
||||||
|
if param == "response_format" and value["type"] == "json_object":
|
||||||
|
optional_params["response_mime_type"] = "application/json"
|
||||||
|
if param == "tools" and isinstance(value, list):
|
||||||
|
from vertexai.preview import generative_models
|
||||||
|
|
||||||
|
gtool_func_declarations = []
|
||||||
|
for tool in value:
|
||||||
|
gtool_func_declaration = generative_models.FunctionDeclaration(
|
||||||
|
name=tool["function"]["name"],
|
||||||
|
description=tool["function"].get("description", ""),
|
||||||
|
parameters=tool["function"].get("parameters", {}),
|
||||||
|
)
|
||||||
|
gtool_func_declarations.append(gtool_func_declaration)
|
||||||
|
optional_params["tools"] = [
|
||||||
|
generative_models.Tool(
|
||||||
|
function_declarations=gtool_func_declarations
|
||||||
|
)
|
||||||
|
]
|
||||||
|
if param == "tool_choice" and (
|
||||||
|
isinstance(value, str) or isinstance(value, dict)
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
return optional_params
|
||||||
|
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
@ -822,8 +876,8 @@ async def async_completion(
|
||||||
tools=tools,
|
tools=tools,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tools is not None and hasattr(
|
if tools is not None and bool(
|
||||||
response.candidates[0].content.parts[0], "function_call"
|
getattr(response.candidates[0].content.parts[0], "function_call", None)
|
||||||
):
|
):
|
||||||
function_call = response.candidates[0].content.parts[0].function_call
|
function_call = response.candidates[0].content.parts[0].function_call
|
||||||
args_dict = {}
|
args_dict = {}
|
||||||
|
|
|
@ -12,7 +12,6 @@ from typing import Any, Literal, Union, BinaryIO
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import dotenv, traceback, random, asyncio, time, contextvars
|
import dotenv, traceback, random, asyncio, time, contextvars
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import litellm
|
import litellm
|
||||||
from ._logging import verbose_logger
|
from ._logging import verbose_logger
|
||||||
|
|
|
@ -708,6 +708,16 @@
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true
|
"supports_function_calling": true
|
||||||
},
|
},
|
||||||
|
"mistral/open-mixtral-8x7b": {
|
||||||
|
"max_tokens": 8191,
|
||||||
|
"max_input_tokens": 32000,
|
||||||
|
"max_output_tokens": 8191,
|
||||||
|
"input_cost_per_token": 0.000002,
|
||||||
|
"output_cost_per_token": 0.000006,
|
||||||
|
"litellm_provider": "mistral",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true
|
||||||
|
},
|
||||||
"mistral/mistral-embed": {
|
"mistral/mistral-embed": {
|
||||||
"max_tokens": 8192,
|
"max_tokens": 8192,
|
||||||
"max_input_tokens": 8192,
|
"max_input_tokens": 8192,
|
||||||
|
@ -1012,6 +1022,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-1.5-pro-preview-0215": {
|
"gemini-1.5-pro-preview-0215": {
|
||||||
|
@ -1023,6 +1034,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-1.5-pro-preview-0409": {
|
"gemini-1.5-pro-preview-0409": {
|
||||||
|
@ -1034,6 +1046,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-experimental": {
|
"gemini-experimental": {
|
||||||
|
@ -1045,6 +1058,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": false,
|
"supports_function_calling": false,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-pro-vision": {
|
"gemini-pro-vision": {
|
||||||
|
@ -1271,6 +1285,7 @@
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
"supports_vision": true,
|
"supports_vision": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini/gemini-1.5-pro-latest": {
|
"gemini/gemini-1.5-pro-latest": {
|
||||||
|
@ -1283,6 +1298,7 @@
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
"supports_vision": true,
|
"supports_vision": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://ai.google.dev/models/gemini"
|
"source": "https://ai.google.dev/models/gemini"
|
||||||
},
|
},
|
||||||
"gemini/gemini-pro-vision": {
|
"gemini/gemini-pro-vision": {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{11837:function(n,e,t){Promise.resolve().then(t.t.bind(t,99646,23)),Promise.resolve().then(t.t.bind(t,63385,23))},63385:function(){},99646:function(n){n.exports={style:{fontFamily:"'__Inter_c23dc8', '__Inter_Fallback_c23dc8'",fontStyle:"normal"},className:"__className_c23dc8"}}},function(n){n.O(0,[971,69,744],function(){return n(n.s=11837)}),_N_E=n.O()}]);
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{87421:function(n,e,t){Promise.resolve().then(t.t.bind(t,99646,23)),Promise.resolve().then(t.t.bind(t,63385,23))},63385:function(){},99646:function(n){n.exports={style:{fontFamily:"'__Inter_c23dc8', '__Inter_Fallback_c23dc8'",fontStyle:"normal"},className:"__className_c23dc8"}}},function(n){n.O(0,[971,69,744],function(){return n(n.s=87421)}),_N_E=n.O()}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{70377:function(e,n,t){Promise.resolve().then(t.t.bind(t,47690,23)),Promise.resolve().then(t.t.bind(t,48955,23)),Promise.resolve().then(t.t.bind(t,5613,23)),Promise.resolve().then(t.t.bind(t,11902,23)),Promise.resolve().then(t.t.bind(t,31778,23)),Promise.resolve().then(t.t.bind(t,77831,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,69],function(){return n(35317),n(70377)}),_N_E=e.O()}]);
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{32028:function(e,n,t){Promise.resolve().then(t.t.bind(t,47690,23)),Promise.resolve().then(t.t.bind(t,48955,23)),Promise.resolve().then(t.t.bind(t,5613,23)),Promise.resolve().then(t.t.bind(t,11902,23)),Promise.resolve().then(t.t.bind(t,31778,23)),Promise.resolve().then(t.t.bind(t,77831,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,69],function(){return n(35317),n(32028)}),_N_E=e.O()}]);
|
|
@ -1 +1 @@
|
||||||
!function(){"use strict";var e,t,n,r,o,u,i,c,f,a={},l={};function d(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={id:e,loaded:!1,exports:{}},r=!0;try{a[e](n,n.exports,d),r=!1}finally{r&&delete l[e]}return n.loaded=!0,n.exports}d.m=a,e=[],d.O=function(t,n,r,o){if(n){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u<e.length;u++){for(var n=e[u][0],r=e[u][1],o=e[u][2],c=!0,f=0;f<n.length;f++)i>=o&&Object.keys(d.O).every(function(e){return d.O[e](n[f])})?n.splice(f--,1):(c=!1,o<i&&(i=o));if(c){e.splice(u--,1);var a=r();void 0!==a&&(t=a)}}return t},d.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,r){if(1&r&&(e=this(e)),8&r||"object"==typeof e&&e&&(4&r&&e.__esModule||16&r&&"function"==typeof e.then))return e;var o=Object.create(null);d.r(o);var u={};t=t||[null,n({}),n([]),n(n)];for(var i=2&r&&e;"object"==typeof i&&!~t.indexOf(i);i=n(i))Object.getOwnPropertyNames(i).forEach(function(t){u[t]=function(){return e[t]}});return u.default=function(){return e},d.d(o,u),o},d.d=function(e,t){for(var n in t)d.o(t,n)&&!d.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce(function(t,n){return d.f[n](e,t),t},[]))},d.u=function(e){},d.miniCssF=function(e){return"static/css/11cfce8bfdf6e8f1.css"},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r={},o="_N_E:",d.l=function(e,t,n,u){if(r[e]){r[e].push(t);return}if(void 0!==n)for(var i,c,f=document.getElementsByTagName("script"),a=0;a<f.length;a++){var l=f[a];if(l.getAttribute("src")==e||l.getAttribute("data-webpack")==o+n){i=l;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,d.nc&&i.setAttribute("nonce",d.nc),i.setAttribute("data-webpack",o+n),i.src=d.tu(e)),r[e]=[t];var s=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=s.bind(null,i.onerror),i.onload=s.bind(null,i.onload),c&&document.head.appendChild(i)},d.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e},d.tt=function(){return void 0===u&&(u={createScriptURL:function(e){return e}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(u=trustedTypes.createPolicy("nextjs#bundler",u))),u},d.tu=function(e){return d.tt().createScriptURL(e)},d.p="/ui/_next/",i={272:0},d.f.j=function(e,t){var n=d.o(i,e)?i[e]:void 0;if(0!==n){if(n)t.push(n[2]);else if(272!=e){var r=new Promise(function(t,r){n=i[e]=[t,r]});t.push(n[2]=r);var o=d.p+d.u(e),u=Error();d.l(o,function(t){if(d.o(i,e)&&(0!==(n=i[e])&&(i[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",u.name="ChunkLoadError",u.type=r,u.request=o,n[1](u)}},"chunk-"+e,e)}else i[e]=0}},d.O.j=function(e){return 0===i[e]},c=function(e,t){var n,r,o=t[0],u=t[1],c=t[2],f=0;if(o.some(function(e){return 0!==i[e]})){for(n in u)d.o(u,n)&&(d.m[n]=u[n]);if(c)var a=c(d)}for(e&&e(t);f<o.length;f++)r=o[f],d.o(i,r)&&i[r]&&i[r][0](),i[r]=0;return d.O(a)},(f=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(c.bind(null,0)),f.push=c.bind(null,f.push.bind(f))}();
|
!function(){"use strict";var e,t,n,r,o,u,i,c,f,a={},l={};function d(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={id:e,loaded:!1,exports:{}},r=!0;try{a[e](n,n.exports,d),r=!1}finally{r&&delete l[e]}return n.loaded=!0,n.exports}d.m=a,e=[],d.O=function(t,n,r,o){if(n){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u<e.length;u++){for(var n=e[u][0],r=e[u][1],o=e[u][2],c=!0,f=0;f<n.length;f++)i>=o&&Object.keys(d.O).every(function(e){return d.O[e](n[f])})?n.splice(f--,1):(c=!1,o<i&&(i=o));if(c){e.splice(u--,1);var a=r();void 0!==a&&(t=a)}}return t},d.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,r){if(1&r&&(e=this(e)),8&r||"object"==typeof e&&e&&(4&r&&e.__esModule||16&r&&"function"==typeof e.then))return e;var o=Object.create(null);d.r(o);var u={};t=t||[null,n({}),n([]),n(n)];for(var i=2&r&&e;"object"==typeof i&&!~t.indexOf(i);i=n(i))Object.getOwnPropertyNames(i).forEach(function(t){u[t]=function(){return e[t]}});return u.default=function(){return e},d.d(o,u),o},d.d=function(e,t){for(var n in t)d.o(t,n)&&!d.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce(function(t,n){return d.f[n](e,t),t},[]))},d.u=function(e){},d.miniCssF=function(e){return"static/css/dc347b0d22ffde5d.css"},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r={},o="_N_E:",d.l=function(e,t,n,u){if(r[e]){r[e].push(t);return}if(void 0!==n)for(var i,c,f=document.getElementsByTagName("script"),a=0;a<f.length;a++){var l=f[a];if(l.getAttribute("src")==e||l.getAttribute("data-webpack")==o+n){i=l;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,d.nc&&i.setAttribute("nonce",d.nc),i.setAttribute("data-webpack",o+n),i.src=d.tu(e)),r[e]=[t];var s=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=s.bind(null,i.onerror),i.onload=s.bind(null,i.onload),c&&document.head.appendChild(i)},d.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e},d.tt=function(){return void 0===u&&(u={createScriptURL:function(e){return e}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(u=trustedTypes.createPolicy("nextjs#bundler",u))),u},d.tu=function(e){return d.tt().createScriptURL(e)},d.p="/ui/_next/",i={272:0},d.f.j=function(e,t){var n=d.o(i,e)?i[e]:void 0;if(0!==n){if(n)t.push(n[2]);else if(272!=e){var r=new Promise(function(t,r){n=i[e]=[t,r]});t.push(n[2]=r);var o=d.p+d.u(e),u=Error();d.l(o,function(t){if(d.o(i,e)&&(0!==(n=i[e])&&(i[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",u.name="ChunkLoadError",u.type=r,u.request=o,n[1](u)}},"chunk-"+e,e)}else i[e]=0}},d.O.j=function(e){return 0===i[e]},c=function(e,t){var n,r,o=t[0],u=t[1],c=t[2],f=0;if(o.some(function(e){return 0!==i[e]})){for(n in u)d.o(u,n)&&(d.m[n]=u[n]);if(c)var a=c(d)}for(e&&e(t);f<o.length;f++)r=o[f],d.o(i,r)&&i[r]&&i[r][0](),i[r]=0;return d.O(a)},(f=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(c.bind(null,0)),f.push=c.bind(null,f.push.bind(f))}();
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-59f93936973f5f5a.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-bcf69420342937de.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-442a9c01c3fd20f9.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-096338c8e1915716.js" async="" crossorigin=""></script><title>LiteLLM Dashboard</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-59f93936973f5f5a.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/11cfce8bfdf6e8f1.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[88740,[\"289\",\"static/chunks/289-04be6cb9636840d2.js\",\"931\",\"static/chunks/app/page-2c0827b33aed42d7.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/11cfce8bfdf6e8f1.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"TqpzjpOA_s5IXVzgrYZ-F\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[],\"styles\":null}]}]}],null]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"LiteLLM Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"LiteLLM Proxy Admin UI\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/ui/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"16x16\"}],[\"$\",\"meta\",\"5\",{\"name\":\"next-size-adjust\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-75b5d58291566cf9.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-bcf69420342937de.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-442a9c01c3fd20f9.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-9b4fb13a7db53edf.js" async="" crossorigin=""></script><title>LiteLLM Dashboard</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-75b5d58291566cf9.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/dc347b0d22ffde5d.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[21225,[\"289\",\"static/chunks/289-04be6cb9636840d2.js\",\"931\",\"static/chunks/app/page-cb85da9a307105a0.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/dc347b0d22ffde5d.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"y7Wf8hfvd5KooOO87je1n\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[],\"styles\":null}]}]}],null]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"LiteLLM Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"LiteLLM Proxy Admin UI\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/ui/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"16x16\"}],[\"$\",\"meta\",\"5\",{\"name\":\"next-size-adjust\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
|
@ -1,7 +1,7 @@
|
||||||
2:I[77831,[],""]
|
2:I[77831,[],""]
|
||||||
3:I[88740,["289","static/chunks/289-04be6cb9636840d2.js","931","static/chunks/app/page-2c0827b33aed42d7.js"],""]
|
3:I[21225,["289","static/chunks/289-04be6cb9636840d2.js","931","static/chunks/app/page-cb85da9a307105a0.js"],""]
|
||||||
4:I[5613,[],""]
|
4:I[5613,[],""]
|
||||||
5:I[31778,[],""]
|
5:I[31778,[],""]
|
||||||
0:["TqpzjpOA_s5IXVzgrYZ-F",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/11cfce8bfdf6e8f1.css","precedence":"next","crossOrigin":""}]],"$L6"]]]]
|
0:["y7Wf8hfvd5KooOO87je1n",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/dc347b0d22ffde5d.css","precedence":"next","crossOrigin":""}]],"$L6"]]]]
|
||||||
6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"LiteLLM Dashboard"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]]
|
6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"LiteLLM Dashboard"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]]
|
||||||
1:null
|
1:null
|
||||||
|
|
|
@ -3,7 +3,8 @@ model_list:
|
||||||
litellm_params:
|
litellm_params:
|
||||||
model: openai/my-fake-model
|
model: openai/my-fake-model
|
||||||
api_key: my-fake-key
|
api_key: my-fake-key
|
||||||
api_base: https://openai-function-calling-workers.tasslexyz.workers.dev/
|
# api_base: https://openai-function-calling-workers.tasslexyz.workers.dev/
|
||||||
|
api_base: http://0.0.0.0:8080
|
||||||
stream_timeout: 0.001
|
stream_timeout: 0.001
|
||||||
rpm: 10
|
rpm: 10
|
||||||
- litellm_params:
|
- litellm_params:
|
||||||
|
|
|
@ -800,6 +800,10 @@ class UserAPIKeyAuth(
|
||||||
def check_api_key(cls, values):
|
def check_api_key(cls, values):
|
||||||
if values.get("api_key") is not None:
|
if values.get("api_key") is not None:
|
||||||
values.update({"token": hash_token(values.get("api_key"))})
|
values.update({"token": hash_token(values.get("api_key"))})
|
||||||
|
if isinstance(values.get("api_key"), str) and values.get(
|
||||||
|
"api_key"
|
||||||
|
).startswith("sk-"):
|
||||||
|
values.update({"api_key": hash_token(values.get("api_key"))})
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,17 +10,7 @@ model_list:
|
||||||
api_key: os.environ/OPENAI_API_KEY
|
api_key: os.environ/OPENAI_API_KEY
|
||||||
|
|
||||||
|
|
||||||
litellm_settings:
|
|
||||||
default_team_settings:
|
|
||||||
- team_id: team-1
|
|
||||||
success_callback: ["langfuse"]
|
|
||||||
langfuse_public_key: os.environ/LANGFUSE_PROJECT1_PUBLIC # Project 1
|
|
||||||
langfuse_secret: os.environ/LANGFUSE_PROJECT1_SECRET # Project 1
|
|
||||||
- team_id: team-2
|
|
||||||
success_callback: ["langfuse"]
|
|
||||||
langfuse_public_key: os.environ/LANGFUSE_PROJECT2_PUBLIC # Project 2
|
|
||||||
langfuse_secret: os.environ/LANGFUSE_PROJECT2_SECRET # Project 2
|
|
||||||
|
|
||||||
general_settings:
|
general_settings:
|
||||||
store_model_in_db: true
|
store_model_in_db: true
|
||||||
master_key: sk-1234
|
master_key: sk-1234
|
||||||
|
alerting: ["slack"]
|
|
@ -7199,6 +7199,7 @@ async def model_info_v2(
|
||||||
"/model/metrics",
|
"/model/metrics",
|
||||||
description="View number of requests & avg latency per model on config.yaml",
|
description="View number of requests & avg latency per model on config.yaml",
|
||||||
tags=["model management"],
|
tags=["model management"],
|
||||||
|
include_in_schema=False,
|
||||||
dependencies=[Depends(user_api_key_auth)],
|
dependencies=[Depends(user_api_key_auth)],
|
||||||
)
|
)
|
||||||
async def model_metrics(
|
async def model_metrics(
|
||||||
|
|
|
@ -360,22 +360,25 @@ class ProxyLogging:
|
||||||
f"Budget Alerts: Percent left: {percent_left} for {user_info}"
|
f"Budget Alerts: Percent left: {percent_left} for {user_info}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# check if crossed budget
|
|
||||||
if user_current_spend >= user_max_budget:
|
|
||||||
verbose_proxy_logger.debug("Budget Crossed for %s", user_info)
|
|
||||||
message = "Budget Crossed for" + user_info
|
|
||||||
await self.alerting_handler(
|
|
||||||
message=message,
|
|
||||||
level="High",
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
## PREVENTITIVE ALERTING ## - https://github.com/BerriAI/litellm/issues/2727
|
## PREVENTITIVE ALERTING ## - https://github.com/BerriAI/litellm/issues/2727
|
||||||
# - Alert once within 28d period
|
# - Alert once within 28d period
|
||||||
# - Cache this information
|
# - Cache this information
|
||||||
# - Don't re-alert, if alert already sent
|
# - Don't re-alert, if alert already sent
|
||||||
_cache: DualCache = self.internal_usage_cache
|
_cache: DualCache = self.internal_usage_cache
|
||||||
|
|
||||||
|
# check if crossed budget
|
||||||
|
if user_current_spend >= user_max_budget:
|
||||||
|
verbose_proxy_logger.debug("Budget Crossed for %s", user_info)
|
||||||
|
message = "Budget Crossed for" + user_info
|
||||||
|
result = await _cache.async_get_cache(key=message)
|
||||||
|
if result is None:
|
||||||
|
await self.alerting_handler(
|
||||||
|
message=message,
|
||||||
|
level="High",
|
||||||
|
)
|
||||||
|
await _cache.async_set_cache(key=message, value="SENT", ttl=2419200)
|
||||||
|
return
|
||||||
|
|
||||||
# check if 5% of max budget is left
|
# check if 5% of max budget is left
|
||||||
if percent_left <= 0.05:
|
if percent_left <= 0.05:
|
||||||
message = "5% budget left for" + user_info
|
message = "5% budget left for" + user_info
|
||||||
|
@ -426,9 +429,8 @@ class ProxyLogging:
|
||||||
|
|
||||||
# Get the current timestamp
|
# Get the current timestamp
|
||||||
current_time = datetime.now().strftime("%H:%M:%S")
|
current_time = datetime.now().strftime("%H:%M:%S")
|
||||||
formatted_message = (
|
_proxy_base_url = os.getenv("PROXY_BASE_URL", "None")
|
||||||
f"Level: `{level}`\nTimestamp: `{current_time}`\n\nMessage: {message}"
|
formatted_message = f"Level: `{level}`\nTimestamp: `{current_time}`\n\nMessage: {message} \n\nProxy URL: `{_proxy_base_url}`"
|
||||||
)
|
|
||||||
if self.alerting is None:
|
if self.alerting is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ from litellm.proxy.enterprise.enterprise_hooks.banned_keywords import (
|
||||||
_ENTERPRISE_BannedKeywords,
|
_ENTERPRISE_BannedKeywords,
|
||||||
)
|
)
|
||||||
from litellm import Router, mock_completion
|
from litellm import Router, mock_completion
|
||||||
from litellm.proxy.utils import ProxyLogging
|
from litellm.proxy.utils import ProxyLogging, hash_token
|
||||||
from litellm.proxy._types import UserAPIKeyAuth
|
from litellm.proxy._types import UserAPIKeyAuth
|
||||||
from litellm.caching import DualCache
|
from litellm.caching import DualCache
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ async def test_banned_keywords_check():
|
||||||
banned_keywords_obj = _ENTERPRISE_BannedKeywords()
|
banned_keywords_obj = _ENTERPRISE_BannedKeywords()
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ from litellm.proxy.enterprise.enterprise_hooks.blocked_user_list import (
|
||||||
_ENTERPRISE_BlockedUserList,
|
_ENTERPRISE_BlockedUserList,
|
||||||
)
|
)
|
||||||
from litellm import Router, mock_completion
|
from litellm import Router, mock_completion
|
||||||
from litellm.proxy.utils import ProxyLogging
|
from litellm.proxy.utils import ProxyLogging, hash_token
|
||||||
from litellm.proxy._types import UserAPIKeyAuth
|
from litellm.proxy._types import UserAPIKeyAuth
|
||||||
from litellm.caching import DualCache
|
from litellm.caching import DualCache
|
||||||
from litellm.proxy.utils import PrismaClient, ProxyLogging, hash_token
|
from litellm.proxy.utils import PrismaClient, ProxyLogging, hash_token
|
||||||
|
@ -106,6 +106,7 @@ async def test_block_user_check(prisma_client):
|
||||||
)
|
)
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,22 @@ def reset_callbacks():
|
||||||
litellm.callbacks = []
|
litellm.callbacks = []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip(reason="Local test")
|
||||||
|
def test_response_model_none():
|
||||||
|
"""
|
||||||
|
Addresses - https://github.com/BerriAI/litellm/issues/2972
|
||||||
|
"""
|
||||||
|
x = completion(
|
||||||
|
model="mymodel",
|
||||||
|
custom_llm_provider="openai",
|
||||||
|
messages=[{"role": "user", "content": "Hello!"}],
|
||||||
|
api_base="http://0.0.0.0:8080",
|
||||||
|
api_key="my-api-key",
|
||||||
|
)
|
||||||
|
print(f"x: {x}")
|
||||||
|
assert isinstance(x, litellm.ModelResponse)
|
||||||
|
|
||||||
|
|
||||||
def test_completion_custom_provider_model_name():
|
def test_completion_custom_provider_model_name():
|
||||||
try:
|
try:
|
||||||
litellm.cache = None
|
litellm.cache = None
|
||||||
|
@ -399,6 +415,51 @@ def test_completion_claude_3_function_plus_image():
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_azure_mistral_large_function_calling():
|
||||||
|
"""
|
||||||
|
This primarily tests if the 'Function()' pydantic object correctly handles argument param passed in as a dict vs. string
|
||||||
|
"""
|
||||||
|
litellm.set_verbose = True
|
||||||
|
tools = [
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_current_weather",
|
||||||
|
"description": "Get the current weather in a given location",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The city and state, e.g. San Francisco, CA",
|
||||||
|
},
|
||||||
|
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
|
||||||
|
},
|
||||||
|
"required": ["location"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "What's the weather like in Boston today in Fahrenheit?",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
response = completion(
|
||||||
|
model="azure/mistral-large-latest",
|
||||||
|
api_base=os.getenv("AZURE_MISTRAL_API_BASE"),
|
||||||
|
api_key=os.getenv("AZURE_MISTRAL_API_KEY"),
|
||||||
|
messages=messages,
|
||||||
|
tools=tools,
|
||||||
|
tool_choice="auto",
|
||||||
|
)
|
||||||
|
# Add any assertions, here to check response args
|
||||||
|
print(response)
|
||||||
|
assert isinstance(response.choices[0].message.tool_calls[0].function.name, str)
|
||||||
|
assert isinstance(response.choices[0].message.tool_calls[0].function.arguments, str)
|
||||||
|
|
||||||
|
|
||||||
def test_completion_mistral_api():
|
def test_completion_mistral_api():
|
||||||
try:
|
try:
|
||||||
litellm.set_verbose = True
|
litellm.set_verbose = True
|
||||||
|
|
|
@ -266,47 +266,50 @@ def test_groq_parallel_function_call():
|
||||||
)
|
)
|
||||||
print("Response\n", response)
|
print("Response\n", response)
|
||||||
response_message = response.choices[0].message
|
response_message = response.choices[0].message
|
||||||
tool_calls = response_message.tool_calls
|
if hasattr(response_message, "tool_calls"):
|
||||||
|
tool_calls = response_message.tool_calls
|
||||||
|
|
||||||
assert isinstance(response.choices[0].message.tool_calls[0].function.name, str)
|
assert isinstance(
|
||||||
assert isinstance(
|
response.choices[0].message.tool_calls[0].function.name, str
|
||||||
response.choices[0].message.tool_calls[0].function.arguments, str
|
)
|
||||||
)
|
assert isinstance(
|
||||||
|
response.choices[0].message.tool_calls[0].function.arguments, str
|
||||||
|
)
|
||||||
|
|
||||||
print("length of tool calls", len(tool_calls))
|
print("length of tool calls", len(tool_calls))
|
||||||
|
|
||||||
# Step 2: check if the model wanted to call a function
|
# Step 2: check if the model wanted to call a function
|
||||||
if tool_calls:
|
if tool_calls:
|
||||||
# Step 3: call the function
|
# Step 3: call the function
|
||||||
# Note: the JSON response may not always be valid; be sure to handle errors
|
# Note: the JSON response may not always be valid; be sure to handle errors
|
||||||
available_functions = {
|
available_functions = {
|
||||||
"get_current_weather": get_current_weather,
|
"get_current_weather": get_current_weather,
|
||||||
} # only one function in this example, but you can have multiple
|
} # only one function in this example, but you can have multiple
|
||||||
messages.append(
|
|
||||||
response_message
|
|
||||||
) # extend conversation with assistant's reply
|
|
||||||
print("Response message\n", response_message)
|
|
||||||
# Step 4: send the info for each function call and function response to the model
|
|
||||||
for tool_call in tool_calls:
|
|
||||||
function_name = tool_call.function.name
|
|
||||||
function_to_call = available_functions[function_name]
|
|
||||||
function_args = json.loads(tool_call.function.arguments)
|
|
||||||
function_response = function_to_call(
|
|
||||||
location=function_args.get("location"),
|
|
||||||
unit=function_args.get("unit"),
|
|
||||||
)
|
|
||||||
messages.append(
|
messages.append(
|
||||||
{
|
response_message
|
||||||
"tool_call_id": tool_call.id,
|
) # extend conversation with assistant's reply
|
||||||
"role": "tool",
|
print("Response message\n", response_message)
|
||||||
"name": function_name,
|
# Step 4: send the info for each function call and function response to the model
|
||||||
"content": function_response,
|
for tool_call in tool_calls:
|
||||||
}
|
function_name = tool_call.function.name
|
||||||
) # extend conversation with function response
|
function_to_call = available_functions[function_name]
|
||||||
print(f"messages: {messages}")
|
function_args = json.loads(tool_call.function.arguments)
|
||||||
second_response = litellm.completion(
|
function_response = function_to_call(
|
||||||
model="groq/llama2-70b-4096", messages=messages
|
location=function_args.get("location"),
|
||||||
) # get a new response from the model where it can see the function response
|
unit=function_args.get("unit"),
|
||||||
print("second response\n", second_response)
|
)
|
||||||
|
messages.append(
|
||||||
|
{
|
||||||
|
"tool_call_id": tool_call.id,
|
||||||
|
"role": "tool",
|
||||||
|
"name": function_name,
|
||||||
|
"content": function_response,
|
||||||
|
}
|
||||||
|
) # extend conversation with function response
|
||||||
|
print(f"messages: {messages}")
|
||||||
|
second_response = litellm.completion(
|
||||||
|
model="groq/llama2-70b-4096", messages=messages
|
||||||
|
) # get a new response from the model where it can see the function response
|
||||||
|
print("second response\n", second_response)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pytest.fail(f"Error occurred: {e}")
|
pytest.fail(f"Error occurred: {e}")
|
||||||
|
|
33
litellm/tests/test_function_setup.py
Normal file
33
litellm/tests/test_function_setup.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# What is this?
|
||||||
|
## Unit tests for the 'function_setup()' function
|
||||||
|
import sys, os
|
||||||
|
import traceback
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
import os, io
|
||||||
|
|
||||||
|
sys.path.insert(
|
||||||
|
0, os.path.abspath("../..")
|
||||||
|
) # Adds the parent directory to the, system path
|
||||||
|
import pytest, uuid
|
||||||
|
from litellm.utils import function_setup, Rules
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_content():
|
||||||
|
"""
|
||||||
|
Make a chat completions request with empty content -> expect this to work
|
||||||
|
"""
|
||||||
|
rules_obj = Rules()
|
||||||
|
|
||||||
|
def completion():
|
||||||
|
pass
|
||||||
|
|
||||||
|
function_setup(
|
||||||
|
original_function=completion,
|
||||||
|
rules_obj=rules_obj,
|
||||||
|
start_time=datetime.now(),
|
||||||
|
messages=[],
|
||||||
|
litellm_call_id=str(uuid.uuid4()),
|
||||||
|
)
|
25
litellm/tests/test_get_model_info.py
Normal file
25
litellm/tests/test_get_model_info.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# What is this?
|
||||||
|
## Unit testing for the 'get_model_info()' function
|
||||||
|
import os, sys, traceback
|
||||||
|
|
||||||
|
sys.path.insert(
|
||||||
|
0, os.path.abspath("../..")
|
||||||
|
) # Adds the parent directory to the system path
|
||||||
|
import litellm
|
||||||
|
from litellm import get_model_info
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_model_info_simple_model_name():
|
||||||
|
"""
|
||||||
|
tests if model name given, and model exists in model info - the object is returned
|
||||||
|
"""
|
||||||
|
model = "claude-3-opus-20240229"
|
||||||
|
litellm.get_model_info(model)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_model_info_custom_llm_with_model_name():
|
||||||
|
"""
|
||||||
|
Tests if {custom_llm_provider}/{model_name} name given, and model exists in model info, the object is returned
|
||||||
|
"""
|
||||||
|
model = "anthropic/claude-3-opus-20240229"
|
||||||
|
litellm.get_model_info(model)
|
|
@ -1925,3 +1925,46 @@ async def test_proxy_load_test_db(prisma_client):
|
||||||
raise Exception(f"it worked! key={key.key}")
|
raise Exception(f"it worked! key={key.key}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pytest.fail(f"An exception occurred - {str(e)}")
|
pytest.fail(f"An exception occurred - {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio()
|
||||||
|
async def test_master_key_hashing(prisma_client):
|
||||||
|
try:
|
||||||
|
|
||||||
|
print("prisma client=", prisma_client)
|
||||||
|
|
||||||
|
master_key = "sk-1234"
|
||||||
|
|
||||||
|
setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client)
|
||||||
|
setattr(litellm.proxy.proxy_server, "master_key", master_key)
|
||||||
|
|
||||||
|
await litellm.proxy.proxy_server.prisma_client.connect()
|
||||||
|
from litellm.proxy.proxy_server import user_api_key_cache
|
||||||
|
|
||||||
|
_response = await new_user(
|
||||||
|
data=NewUserRequest(
|
||||||
|
models=["azure-gpt-3.5"],
|
||||||
|
team_id="ishaans-special-team",
|
||||||
|
tpm_limit=20,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(_response)
|
||||||
|
assert _response.models == ["azure-gpt-3.5"]
|
||||||
|
assert _response.team_id == "ishaans-special-team"
|
||||||
|
assert _response.tpm_limit == 20
|
||||||
|
|
||||||
|
bearer_token = "Bearer " + master_key
|
||||||
|
|
||||||
|
request = Request(scope={"type": "http"})
|
||||||
|
request._url = URL(url="/chat/completions")
|
||||||
|
|
||||||
|
# use generated key to auth in
|
||||||
|
result: UserAPIKeyAuth = await user_api_key_auth(
|
||||||
|
request=request, api_key=bearer_token
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.api_key == hash_token(master_key)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("Got Exception", e)
|
||||||
|
pytest.fail(f"Got exception {e}")
|
||||||
|
|
|
@ -18,7 +18,7 @@ import pytest
|
||||||
import litellm
|
import litellm
|
||||||
from litellm.proxy.enterprise.enterprise_hooks.llm_guard import _ENTERPRISE_LLMGuard
|
from litellm.proxy.enterprise.enterprise_hooks.llm_guard import _ENTERPRISE_LLMGuard
|
||||||
from litellm import Router, mock_completion
|
from litellm import Router, mock_completion
|
||||||
from litellm.proxy.utils import ProxyLogging
|
from litellm.proxy.utils import ProxyLogging, hash_token
|
||||||
from litellm.proxy._types import UserAPIKeyAuth
|
from litellm.proxy._types import UserAPIKeyAuth
|
||||||
from litellm.caching import DualCache
|
from litellm.caching import DualCache
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ async def test_llm_guard_valid_response():
|
||||||
)
|
)
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ async def test_llm_guard_error_raising():
|
||||||
)
|
)
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ sys.path.insert(
|
||||||
import pytest
|
import pytest
|
||||||
import litellm
|
import litellm
|
||||||
from litellm import Router
|
from litellm import Router
|
||||||
from litellm.proxy.utils import ProxyLogging
|
from litellm.proxy.utils import ProxyLogging, hash_token
|
||||||
from litellm.proxy._types import UserAPIKeyAuth
|
from litellm.proxy._types import UserAPIKeyAuth
|
||||||
from litellm.caching import DualCache, RedisCache
|
from litellm.caching import DualCache, RedisCache
|
||||||
from litellm.proxy.hooks.tpm_rpm_limiter import _PROXY_MaxTPMRPMLimiter
|
from litellm.proxy.hooks.tpm_rpm_limiter import _PROXY_MaxTPMRPMLimiter
|
||||||
|
@ -29,7 +29,7 @@ async def test_pre_call_hook_rpm_limits():
|
||||||
Test if error raised on hitting rpm limits
|
Test if error raised on hitting rpm limits
|
||||||
"""
|
"""
|
||||||
litellm.set_verbose = True
|
litellm.set_verbose = True
|
||||||
_api_key = "sk-12345"
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, tpm_limit=9, rpm_limit=1)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, tpm_limit=9, rpm_limit=1)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
# redis_usage_cache = RedisCache()
|
# redis_usage_cache = RedisCache()
|
||||||
|
@ -87,6 +87,7 @@ async def test_pre_call_hook_team_rpm_limits(
|
||||||
"team_id": _team_id,
|
"team_id": _team_id,
|
||||||
}
|
}
|
||||||
user_api_key_dict = UserAPIKeyAuth(**_user_api_key_dict) # type: ignore
|
user_api_key_dict = UserAPIKeyAuth(**_user_api_key_dict) # type: ignore
|
||||||
|
_api_key = hash_token(_api_key)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
local_cache.set_cache(key=_api_key, value=_user_api_key_dict)
|
local_cache.set_cache(key=_api_key, value=_user_api_key_dict)
|
||||||
internal_cache = DualCache(redis_cache=_redis_usage_cache)
|
internal_cache = DualCache(redis_cache=_redis_usage_cache)
|
||||||
|
|
|
@ -15,7 +15,7 @@ sys.path.insert(
|
||||||
import pytest
|
import pytest
|
||||||
import litellm
|
import litellm
|
||||||
from litellm import Router
|
from litellm import Router
|
||||||
from litellm.proxy.utils import ProxyLogging
|
from litellm.proxy.utils import ProxyLogging, hash_token
|
||||||
from litellm.proxy._types import UserAPIKeyAuth
|
from litellm.proxy._types import UserAPIKeyAuth
|
||||||
from litellm.caching import DualCache
|
from litellm.caching import DualCache
|
||||||
from litellm.proxy.hooks.parallel_request_limiter import (
|
from litellm.proxy.hooks.parallel_request_limiter import (
|
||||||
|
@ -34,6 +34,7 @@ async def test_pre_call_hook():
|
||||||
Test if cache updated on call being received
|
Test if cache updated on call being received
|
||||||
"""
|
"""
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
parallel_request_handler = MaxParallelRequestsHandler()
|
parallel_request_handler = MaxParallelRequestsHandler()
|
||||||
|
@ -248,6 +249,7 @@ async def test_success_call_hook():
|
||||||
Test if on success, cache correctly decremented
|
Test if on success, cache correctly decremented
|
||||||
"""
|
"""
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
parallel_request_handler = MaxParallelRequestsHandler()
|
parallel_request_handler = MaxParallelRequestsHandler()
|
||||||
|
@ -289,6 +291,7 @@ async def test_failure_call_hook():
|
||||||
Test if on failure, cache correctly decremented
|
Test if on failure, cache correctly decremented
|
||||||
"""
|
"""
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token(_api_key)
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
parallel_request_handler = MaxParallelRequestsHandler()
|
parallel_request_handler = MaxParallelRequestsHandler()
|
||||||
|
@ -366,6 +369,7 @@ async def test_normal_router_call():
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token(_api_key)
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
pl = ProxyLogging(user_api_key_cache=local_cache)
|
pl = ProxyLogging(user_api_key_cache=local_cache)
|
||||||
|
@ -443,6 +447,7 @@ async def test_normal_router_tpm_limit():
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(
|
user_api_key_dict = UserAPIKeyAuth(
|
||||||
api_key=_api_key, max_parallel_requests=10, tpm_limit=10
|
api_key=_api_key, max_parallel_requests=10, tpm_limit=10
|
||||||
)
|
)
|
||||||
|
@ -524,6 +529,7 @@ async def test_streaming_router_call():
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
pl = ProxyLogging(user_api_key_cache=local_cache)
|
pl = ProxyLogging(user_api_key_cache=local_cache)
|
||||||
|
@ -599,6 +605,7 @@ async def test_streaming_router_tpm_limit():
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token("sk-12345")
|
||||||
user_api_key_dict = UserAPIKeyAuth(
|
user_api_key_dict = UserAPIKeyAuth(
|
||||||
api_key=_api_key, max_parallel_requests=10, tpm_limit=10
|
api_key=_api_key, max_parallel_requests=10, tpm_limit=10
|
||||||
)
|
)
|
||||||
|
@ -677,6 +684,7 @@ async def test_bad_router_call():
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token(_api_key)
|
||||||
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=1)
|
||||||
local_cache = DualCache()
|
local_cache = DualCache()
|
||||||
pl = ProxyLogging(user_api_key_cache=local_cache)
|
pl = ProxyLogging(user_api_key_cache=local_cache)
|
||||||
|
@ -750,6 +758,7 @@ async def test_bad_router_tpm_limit():
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
_api_key = "sk-12345"
|
_api_key = "sk-12345"
|
||||||
|
_api_key = hash_token(_api_key)
|
||||||
user_api_key_dict = UserAPIKeyAuth(
|
user_api_key_dict = UserAPIKeyAuth(
|
||||||
api_key=_api_key, max_parallel_requests=10, tpm_limit=10
|
api_key=_api_key, max_parallel_requests=10, tpm_limit=10
|
||||||
)
|
)
|
||||||
|
|
|
@ -220,6 +220,17 @@ tools_schema = [
|
||||||
# test_completion_cohere_stream()
|
# test_completion_cohere_stream()
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_azure_stream_special_char():
|
||||||
|
litellm.set_verbose = True
|
||||||
|
messages = [{"role": "user", "content": "hi. respond with the <xml> tag only"}]
|
||||||
|
response = completion(model="azure/chatgpt-v-2", messages=messages, stream=True)
|
||||||
|
response_str = ""
|
||||||
|
for part in response:
|
||||||
|
response_str += part.choices[0].delta.content or ""
|
||||||
|
print(f"response_str: {response_str}")
|
||||||
|
assert len(response_str) > 0
|
||||||
|
|
||||||
|
|
||||||
def test_completion_cohere_stream_bad_key():
|
def test_completion_cohere_stream_bad_key():
|
||||||
try:
|
try:
|
||||||
litellm.cache = None
|
litellm.cache = None
|
||||||
|
|
497
litellm/utils.py
497
litellm/utils.py
|
@ -228,6 +228,24 @@ class Function(OpenAIObject):
|
||||||
arguments: str
|
arguments: str
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
arguments: Union[Dict, str],
|
||||||
|
name: Optional[str] = None,
|
||||||
|
**params,
|
||||||
|
):
|
||||||
|
if isinstance(arguments, Dict):
|
||||||
|
arguments = json.dumps(arguments)
|
||||||
|
else:
|
||||||
|
arguments = arguments
|
||||||
|
|
||||||
|
name = name
|
||||||
|
|
||||||
|
# Build a dictionary with the structure your BaseModel expects
|
||||||
|
data = {"arguments": arguments, "name": name, **params}
|
||||||
|
|
||||||
|
super(Function, self).__init__(**data)
|
||||||
|
|
||||||
|
|
||||||
class ChatCompletionDeltaToolCall(OpenAIObject):
|
class ChatCompletionDeltaToolCall(OpenAIObject):
|
||||||
id: Optional[str] = None
|
id: Optional[str] = None
|
||||||
|
@ -2392,210 +2410,202 @@ class Rules:
|
||||||
|
|
||||||
####### CLIENT ###################
|
####### CLIENT ###################
|
||||||
# make it easy to log if completion/embedding runs succeeded or failed + see what happened | Non-Blocking
|
# make it easy to log if completion/embedding runs succeeded or failed + see what happened | Non-Blocking
|
||||||
|
def function_setup(
|
||||||
|
original_function, rules_obj, start_time, *args, **kwargs
|
||||||
|
): # just run once to check if user wants to send their data anywhere - PostHog/Sentry/Slack/etc.
|
||||||
|
try:
|
||||||
|
global callback_list, add_breadcrumb, user_logger_fn, Logging
|
||||||
|
function_id = kwargs["id"] if "id" in kwargs else None
|
||||||
|
if len(litellm.callbacks) > 0:
|
||||||
|
for callback in litellm.callbacks:
|
||||||
|
if callback not in litellm.input_callback:
|
||||||
|
litellm.input_callback.append(callback)
|
||||||
|
if callback not in litellm.success_callback:
|
||||||
|
litellm.success_callback.append(callback)
|
||||||
|
if callback not in litellm.failure_callback:
|
||||||
|
litellm.failure_callback.append(callback)
|
||||||
|
if callback not in litellm._async_success_callback:
|
||||||
|
litellm._async_success_callback.append(callback)
|
||||||
|
if callback not in litellm._async_failure_callback:
|
||||||
|
litellm._async_failure_callback.append(callback)
|
||||||
|
print_verbose(
|
||||||
|
f"Initialized litellm callbacks, Async Success Callbacks: {litellm._async_success_callback}"
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
len(litellm.input_callback) > 0
|
||||||
|
or len(litellm.success_callback) > 0
|
||||||
|
or len(litellm.failure_callback) > 0
|
||||||
|
) and len(callback_list) == 0:
|
||||||
|
callback_list = list(
|
||||||
|
set(
|
||||||
|
litellm.input_callback
|
||||||
|
+ litellm.success_callback
|
||||||
|
+ litellm.failure_callback
|
||||||
|
)
|
||||||
|
)
|
||||||
|
set_callbacks(callback_list=callback_list, function_id=function_id)
|
||||||
|
## ASYNC CALLBACKS
|
||||||
|
if len(litellm.input_callback) > 0:
|
||||||
|
removed_async_items = []
|
||||||
|
for index, callback in enumerate(litellm.input_callback):
|
||||||
|
if inspect.iscoroutinefunction(callback):
|
||||||
|
litellm._async_input_callback.append(callback)
|
||||||
|
removed_async_items.append(index)
|
||||||
|
|
||||||
|
# Pop the async items from input_callback in reverse order to avoid index issues
|
||||||
|
for index in reversed(removed_async_items):
|
||||||
|
litellm.input_callback.pop(index)
|
||||||
|
|
||||||
|
if len(litellm.success_callback) > 0:
|
||||||
|
removed_async_items = []
|
||||||
|
for index, callback in enumerate(litellm.success_callback):
|
||||||
|
if inspect.iscoroutinefunction(callback):
|
||||||
|
litellm._async_success_callback.append(callback)
|
||||||
|
removed_async_items.append(index)
|
||||||
|
elif callback == "dynamodb":
|
||||||
|
# dynamo is an async callback, it's used for the proxy and needs to be async
|
||||||
|
# we only support async dynamo db logging for acompletion/aembedding since that's used on proxy
|
||||||
|
litellm._async_success_callback.append(callback)
|
||||||
|
removed_async_items.append(index)
|
||||||
|
|
||||||
|
# Pop the async items from success_callback in reverse order to avoid index issues
|
||||||
|
for index in reversed(removed_async_items):
|
||||||
|
litellm.success_callback.pop(index)
|
||||||
|
|
||||||
|
if len(litellm.failure_callback) > 0:
|
||||||
|
removed_async_items = []
|
||||||
|
for index, callback in enumerate(litellm.failure_callback):
|
||||||
|
if inspect.iscoroutinefunction(callback):
|
||||||
|
litellm._async_failure_callback.append(callback)
|
||||||
|
removed_async_items.append(index)
|
||||||
|
|
||||||
|
# Pop the async items from failure_callback in reverse order to avoid index issues
|
||||||
|
for index in reversed(removed_async_items):
|
||||||
|
litellm.failure_callback.pop(index)
|
||||||
|
### DYNAMIC CALLBACKS ###
|
||||||
|
dynamic_success_callbacks = None
|
||||||
|
dynamic_async_success_callbacks = None
|
||||||
|
if kwargs.get("success_callback", None) is not None and isinstance(
|
||||||
|
kwargs["success_callback"], list
|
||||||
|
):
|
||||||
|
removed_async_items = []
|
||||||
|
for index, callback in enumerate(kwargs["success_callback"]):
|
||||||
|
if (
|
||||||
|
inspect.iscoroutinefunction(callback)
|
||||||
|
or callback == "dynamodb"
|
||||||
|
or callback == "s3"
|
||||||
|
):
|
||||||
|
if dynamic_async_success_callbacks is not None and isinstance(
|
||||||
|
dynamic_async_success_callbacks, list
|
||||||
|
):
|
||||||
|
dynamic_async_success_callbacks.append(callback)
|
||||||
|
else:
|
||||||
|
dynamic_async_success_callbacks = [callback]
|
||||||
|
removed_async_items.append(index)
|
||||||
|
# Pop the async items from success_callback in reverse order to avoid index issues
|
||||||
|
for index in reversed(removed_async_items):
|
||||||
|
kwargs["success_callback"].pop(index)
|
||||||
|
dynamic_success_callbacks = kwargs.pop("success_callback")
|
||||||
|
|
||||||
|
if add_breadcrumb:
|
||||||
|
add_breadcrumb(
|
||||||
|
category="litellm.llm_call",
|
||||||
|
message=f"Positional Args: {args}, Keyword Args: {kwargs}",
|
||||||
|
level="info",
|
||||||
|
)
|
||||||
|
if "logger_fn" in kwargs:
|
||||||
|
user_logger_fn = kwargs["logger_fn"]
|
||||||
|
# INIT LOGGER - for user-specified integrations
|
||||||
|
model = args[0] if len(args) > 0 else kwargs.get("model", None)
|
||||||
|
call_type = original_function.__name__
|
||||||
|
if (
|
||||||
|
call_type == CallTypes.completion.value
|
||||||
|
or call_type == CallTypes.acompletion.value
|
||||||
|
):
|
||||||
|
messages = None
|
||||||
|
if len(args) > 1:
|
||||||
|
messages = args[1]
|
||||||
|
elif kwargs.get("messages", None):
|
||||||
|
messages = kwargs["messages"]
|
||||||
|
### PRE-CALL RULES ###
|
||||||
|
if (
|
||||||
|
isinstance(messages, list)
|
||||||
|
and len(messages) > 0
|
||||||
|
and isinstance(messages[0], dict)
|
||||||
|
and "content" in messages[0]
|
||||||
|
):
|
||||||
|
rules_obj.pre_call_rules(
|
||||||
|
input="".join(
|
||||||
|
m.get("content", "")
|
||||||
|
for m in messages
|
||||||
|
if "content" in m and isinstance(m["content"], str)
|
||||||
|
),
|
||||||
|
model=model,
|
||||||
|
)
|
||||||
|
elif (
|
||||||
|
call_type == CallTypes.embedding.value
|
||||||
|
or call_type == CallTypes.aembedding.value
|
||||||
|
):
|
||||||
|
messages = args[1] if len(args) > 1 else kwargs["input"]
|
||||||
|
elif (
|
||||||
|
call_type == CallTypes.image_generation.value
|
||||||
|
or call_type == CallTypes.aimage_generation.value
|
||||||
|
):
|
||||||
|
messages = args[0] if len(args) > 0 else kwargs["prompt"]
|
||||||
|
elif (
|
||||||
|
call_type == CallTypes.moderation.value
|
||||||
|
or call_type == CallTypes.amoderation.value
|
||||||
|
):
|
||||||
|
messages = args[1] if len(args) > 1 else kwargs["input"]
|
||||||
|
elif (
|
||||||
|
call_type == CallTypes.atext_completion.value
|
||||||
|
or call_type == CallTypes.text_completion.value
|
||||||
|
):
|
||||||
|
messages = args[0] if len(args) > 0 else kwargs["prompt"]
|
||||||
|
elif (
|
||||||
|
call_type == CallTypes.atranscription.value
|
||||||
|
or call_type == CallTypes.transcription.value
|
||||||
|
):
|
||||||
|
_file_name: BinaryIO = args[1] if len(args) > 1 else kwargs["file"]
|
||||||
|
messages = "audio_file"
|
||||||
|
stream = True if "stream" in kwargs and kwargs["stream"] == True else False
|
||||||
|
logging_obj = Logging(
|
||||||
|
model=model,
|
||||||
|
messages=messages,
|
||||||
|
stream=stream,
|
||||||
|
litellm_call_id=kwargs["litellm_call_id"],
|
||||||
|
function_id=function_id,
|
||||||
|
call_type=call_type,
|
||||||
|
start_time=start_time,
|
||||||
|
dynamic_success_callbacks=dynamic_success_callbacks,
|
||||||
|
dynamic_async_success_callbacks=dynamic_async_success_callbacks,
|
||||||
|
langfuse_public_key=kwargs.pop("langfuse_public_key", None),
|
||||||
|
langfuse_secret=kwargs.pop("langfuse_secret", None),
|
||||||
|
)
|
||||||
|
## check if metadata is passed in
|
||||||
|
litellm_params = {"api_base": ""}
|
||||||
|
if "metadata" in kwargs:
|
||||||
|
litellm_params["metadata"] = kwargs["metadata"]
|
||||||
|
logging_obj.update_environment_variables(
|
||||||
|
model=model,
|
||||||
|
user="",
|
||||||
|
optional_params={},
|
||||||
|
litellm_params=litellm_params,
|
||||||
|
)
|
||||||
|
return logging_obj, kwargs
|
||||||
|
except Exception as e:
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.debug(
|
||||||
|
f"[Non-Blocking] {traceback.format_exc()}; args - {args}; kwargs - {kwargs}"
|
||||||
|
)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
def client(original_function):
|
def client(original_function):
|
||||||
global liteDebuggerClient, get_all_keys
|
global liteDebuggerClient, get_all_keys
|
||||||
rules_obj = Rules()
|
rules_obj = Rules()
|
||||||
|
|
||||||
def function_setup(
|
|
||||||
start_time, *args, **kwargs
|
|
||||||
): # just run once to check if user wants to send their data anywhere - PostHog/Sentry/Slack/etc.
|
|
||||||
try:
|
|
||||||
global callback_list, add_breadcrumb, user_logger_fn, Logging
|
|
||||||
function_id = kwargs["id"] if "id" in kwargs else None
|
|
||||||
if litellm.use_client or (
|
|
||||||
"use_client" in kwargs and kwargs["use_client"] == True
|
|
||||||
):
|
|
||||||
if "lite_debugger" not in litellm.input_callback:
|
|
||||||
litellm.input_callback.append("lite_debugger")
|
|
||||||
if "lite_debugger" not in litellm.success_callback:
|
|
||||||
litellm.success_callback.append("lite_debugger")
|
|
||||||
if "lite_debugger" not in litellm.failure_callback:
|
|
||||||
litellm.failure_callback.append("lite_debugger")
|
|
||||||
if len(litellm.callbacks) > 0:
|
|
||||||
for callback in litellm.callbacks:
|
|
||||||
if callback not in litellm.input_callback:
|
|
||||||
litellm.input_callback.append(callback)
|
|
||||||
if callback not in litellm.success_callback:
|
|
||||||
litellm.success_callback.append(callback)
|
|
||||||
if callback not in litellm.failure_callback:
|
|
||||||
litellm.failure_callback.append(callback)
|
|
||||||
if callback not in litellm._async_success_callback:
|
|
||||||
litellm._async_success_callback.append(callback)
|
|
||||||
if callback not in litellm._async_failure_callback:
|
|
||||||
litellm._async_failure_callback.append(callback)
|
|
||||||
print_verbose(
|
|
||||||
f"Initialized litellm callbacks, Async Success Callbacks: {litellm._async_success_callback}"
|
|
||||||
)
|
|
||||||
if (
|
|
||||||
len(litellm.input_callback) > 0
|
|
||||||
or len(litellm.success_callback) > 0
|
|
||||||
or len(litellm.failure_callback) > 0
|
|
||||||
) and len(callback_list) == 0:
|
|
||||||
callback_list = list(
|
|
||||||
set(
|
|
||||||
litellm.input_callback
|
|
||||||
+ litellm.success_callback
|
|
||||||
+ litellm.failure_callback
|
|
||||||
)
|
|
||||||
)
|
|
||||||
set_callbacks(callback_list=callback_list, function_id=function_id)
|
|
||||||
## ASYNC CALLBACKS
|
|
||||||
if len(litellm.input_callback) > 0:
|
|
||||||
removed_async_items = []
|
|
||||||
for index, callback in enumerate(litellm.input_callback):
|
|
||||||
if inspect.iscoroutinefunction(callback):
|
|
||||||
litellm._async_input_callback.append(callback)
|
|
||||||
removed_async_items.append(index)
|
|
||||||
|
|
||||||
# Pop the async items from input_callback in reverse order to avoid index issues
|
|
||||||
for index in reversed(removed_async_items):
|
|
||||||
litellm.input_callback.pop(index)
|
|
||||||
|
|
||||||
if len(litellm.success_callback) > 0:
|
|
||||||
removed_async_items = []
|
|
||||||
for index, callback in enumerate(litellm.success_callback):
|
|
||||||
if inspect.iscoroutinefunction(callback):
|
|
||||||
litellm._async_success_callback.append(callback)
|
|
||||||
removed_async_items.append(index)
|
|
||||||
elif callback == "dynamodb":
|
|
||||||
# dynamo is an async callback, it's used for the proxy and needs to be async
|
|
||||||
# we only support async dynamo db logging for acompletion/aembedding since that's used on proxy
|
|
||||||
litellm._async_success_callback.append(callback)
|
|
||||||
removed_async_items.append(index)
|
|
||||||
|
|
||||||
# Pop the async items from success_callback in reverse order to avoid index issues
|
|
||||||
for index in reversed(removed_async_items):
|
|
||||||
litellm.success_callback.pop(index)
|
|
||||||
|
|
||||||
if len(litellm.failure_callback) > 0:
|
|
||||||
removed_async_items = []
|
|
||||||
for index, callback in enumerate(litellm.failure_callback):
|
|
||||||
if inspect.iscoroutinefunction(callback):
|
|
||||||
litellm._async_failure_callback.append(callback)
|
|
||||||
removed_async_items.append(index)
|
|
||||||
|
|
||||||
# Pop the async items from failure_callback in reverse order to avoid index issues
|
|
||||||
for index in reversed(removed_async_items):
|
|
||||||
litellm.failure_callback.pop(index)
|
|
||||||
### DYNAMIC CALLBACKS ###
|
|
||||||
dynamic_success_callbacks = None
|
|
||||||
dynamic_async_success_callbacks = None
|
|
||||||
if kwargs.get("success_callback", None) is not None and isinstance(
|
|
||||||
kwargs["success_callback"], list
|
|
||||||
):
|
|
||||||
removed_async_items = []
|
|
||||||
for index, callback in enumerate(kwargs["success_callback"]):
|
|
||||||
if (
|
|
||||||
inspect.iscoroutinefunction(callback)
|
|
||||||
or callback == "dynamodb"
|
|
||||||
or callback == "s3"
|
|
||||||
):
|
|
||||||
if dynamic_async_success_callbacks is not None and isinstance(
|
|
||||||
dynamic_async_success_callbacks, list
|
|
||||||
):
|
|
||||||
dynamic_async_success_callbacks.append(callback)
|
|
||||||
else:
|
|
||||||
dynamic_async_success_callbacks = [callback]
|
|
||||||
removed_async_items.append(index)
|
|
||||||
# Pop the async items from success_callback in reverse order to avoid index issues
|
|
||||||
for index in reversed(removed_async_items):
|
|
||||||
kwargs["success_callback"].pop(index)
|
|
||||||
dynamic_success_callbacks = kwargs.pop("success_callback")
|
|
||||||
|
|
||||||
if add_breadcrumb:
|
|
||||||
add_breadcrumb(
|
|
||||||
category="litellm.llm_call",
|
|
||||||
message=f"Positional Args: {args}, Keyword Args: {kwargs}",
|
|
||||||
level="info",
|
|
||||||
)
|
|
||||||
if "logger_fn" in kwargs:
|
|
||||||
user_logger_fn = kwargs["logger_fn"]
|
|
||||||
# INIT LOGGER - for user-specified integrations
|
|
||||||
model = args[0] if len(args) > 0 else kwargs.get("model", None)
|
|
||||||
call_type = original_function.__name__
|
|
||||||
if (
|
|
||||||
call_type == CallTypes.completion.value
|
|
||||||
or call_type == CallTypes.acompletion.value
|
|
||||||
):
|
|
||||||
messages = None
|
|
||||||
if len(args) > 1:
|
|
||||||
messages = args[1]
|
|
||||||
elif kwargs.get("messages", None):
|
|
||||||
messages = kwargs["messages"]
|
|
||||||
### PRE-CALL RULES ###
|
|
||||||
if (
|
|
||||||
isinstance(messages, list)
|
|
||||||
and len(messages) > 0
|
|
||||||
and isinstance(messages[0], dict)
|
|
||||||
and "content" in messages[0]
|
|
||||||
):
|
|
||||||
rules_obj.pre_call_rules(
|
|
||||||
input="".join(
|
|
||||||
m.get("content", "")
|
|
||||||
for m in messages
|
|
||||||
if isinstance(m["content"], str)
|
|
||||||
),
|
|
||||||
model=model,
|
|
||||||
)
|
|
||||||
elif (
|
|
||||||
call_type == CallTypes.embedding.value
|
|
||||||
or call_type == CallTypes.aembedding.value
|
|
||||||
):
|
|
||||||
messages = args[1] if len(args) > 1 else kwargs["input"]
|
|
||||||
elif (
|
|
||||||
call_type == CallTypes.image_generation.value
|
|
||||||
or call_type == CallTypes.aimage_generation.value
|
|
||||||
):
|
|
||||||
messages = args[0] if len(args) > 0 else kwargs["prompt"]
|
|
||||||
elif (
|
|
||||||
call_type == CallTypes.moderation.value
|
|
||||||
or call_type == CallTypes.amoderation.value
|
|
||||||
):
|
|
||||||
messages = args[1] if len(args) > 1 else kwargs["input"]
|
|
||||||
elif (
|
|
||||||
call_type == CallTypes.atext_completion.value
|
|
||||||
or call_type == CallTypes.text_completion.value
|
|
||||||
):
|
|
||||||
messages = args[0] if len(args) > 0 else kwargs["prompt"]
|
|
||||||
elif (
|
|
||||||
call_type == CallTypes.atranscription.value
|
|
||||||
or call_type == CallTypes.transcription.value
|
|
||||||
):
|
|
||||||
_file_name: BinaryIO = args[1] if len(args) > 1 else kwargs["file"]
|
|
||||||
messages = "audio_file"
|
|
||||||
stream = True if "stream" in kwargs and kwargs["stream"] == True else False
|
|
||||||
logging_obj = Logging(
|
|
||||||
model=model,
|
|
||||||
messages=messages,
|
|
||||||
stream=stream,
|
|
||||||
litellm_call_id=kwargs["litellm_call_id"],
|
|
||||||
function_id=function_id,
|
|
||||||
call_type=call_type,
|
|
||||||
start_time=start_time,
|
|
||||||
dynamic_success_callbacks=dynamic_success_callbacks,
|
|
||||||
dynamic_async_success_callbacks=dynamic_async_success_callbacks,
|
|
||||||
langfuse_public_key=kwargs.pop("langfuse_public_key", None),
|
|
||||||
langfuse_secret=kwargs.pop("langfuse_secret", None),
|
|
||||||
)
|
|
||||||
## check if metadata is passed in
|
|
||||||
litellm_params = {"api_base": ""}
|
|
||||||
if "metadata" in kwargs:
|
|
||||||
litellm_params["metadata"] = kwargs["metadata"]
|
|
||||||
logging_obj.update_environment_variables(
|
|
||||||
model=model,
|
|
||||||
user="",
|
|
||||||
optional_params={},
|
|
||||||
litellm_params=litellm_params,
|
|
||||||
)
|
|
||||||
return logging_obj, kwargs
|
|
||||||
except Exception as e:
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logging.debug(
|
|
||||||
f"[Non-Blocking] {traceback.format_exc()}; args - {args}; kwargs - {kwargs}"
|
|
||||||
)
|
|
||||||
raise e
|
|
||||||
|
|
||||||
def check_coroutine(value) -> bool:
|
def check_coroutine(value) -> bool:
|
||||||
if inspect.iscoroutine(value):
|
if inspect.iscoroutine(value):
|
||||||
return True
|
return True
|
||||||
|
@ -2688,7 +2698,9 @@ def client(original_function):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if logging_obj is None:
|
if logging_obj is None:
|
||||||
logging_obj, kwargs = function_setup(start_time, *args, **kwargs)
|
logging_obj, kwargs = function_setup(
|
||||||
|
original_function, rules_obj, start_time, *args, **kwargs
|
||||||
|
)
|
||||||
kwargs["litellm_logging_obj"] = logging_obj
|
kwargs["litellm_logging_obj"] = logging_obj
|
||||||
|
|
||||||
# CHECK FOR 'os.environ/' in kwargs
|
# CHECK FOR 'os.environ/' in kwargs
|
||||||
|
@ -2996,7 +3008,9 @@ def client(original_function):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if logging_obj is None:
|
if logging_obj is None:
|
||||||
logging_obj, kwargs = function_setup(start_time, *args, **kwargs)
|
logging_obj, kwargs = function_setup(
|
||||||
|
original_function, rules_obj, start_time, *args, **kwargs
|
||||||
|
)
|
||||||
kwargs["litellm_logging_obj"] = logging_obj
|
kwargs["litellm_logging_obj"] = logging_obj
|
||||||
|
|
||||||
# [OPTIONAL] CHECK BUDGET
|
# [OPTIONAL] CHECK BUDGET
|
||||||
|
@ -4907,37 +4921,11 @@ def get_optional_params(
|
||||||
)
|
)
|
||||||
_check_valid_arg(supported_params=supported_params)
|
_check_valid_arg(supported_params=supported_params)
|
||||||
|
|
||||||
if temperature is not None:
|
optional_params = litellm.VertexAIConfig().map_openai_params(
|
||||||
optional_params["temperature"] = temperature
|
non_default_params=non_default_params,
|
||||||
if top_p is not None:
|
optional_params=optional_params,
|
||||||
optional_params["top_p"] = top_p
|
)
|
||||||
if stream:
|
|
||||||
optional_params["stream"] = stream
|
|
||||||
if n is not None:
|
|
||||||
optional_params["candidate_count"] = n
|
|
||||||
if stop is not None:
|
|
||||||
if isinstance(stop, str):
|
|
||||||
optional_params["stop_sequences"] = [stop]
|
|
||||||
elif isinstance(stop, list):
|
|
||||||
optional_params["stop_sequences"] = stop
|
|
||||||
if max_tokens is not None:
|
|
||||||
optional_params["max_output_tokens"] = max_tokens
|
|
||||||
if response_format is not None and response_format["type"] == "json_object":
|
|
||||||
optional_params["response_mime_type"] = "application/json"
|
|
||||||
if tools is not None and isinstance(tools, list):
|
|
||||||
from vertexai.preview import generative_models
|
|
||||||
|
|
||||||
gtool_func_declarations = []
|
|
||||||
for tool in tools:
|
|
||||||
gtool_func_declaration = generative_models.FunctionDeclaration(
|
|
||||||
name=tool["function"]["name"],
|
|
||||||
description=tool["function"].get("description", ""),
|
|
||||||
parameters=tool["function"].get("parameters", {}),
|
|
||||||
)
|
|
||||||
gtool_func_declarations.append(gtool_func_declaration)
|
|
||||||
optional_params["tools"] = [
|
|
||||||
generative_models.Tool(function_declarations=gtool_func_declarations)
|
|
||||||
]
|
|
||||||
print_verbose(
|
print_verbose(
|
||||||
f"(end) INSIDE THE VERTEX AI OPTIONAL PARAM BLOCK - optional_params: {optional_params}"
|
f"(end) INSIDE THE VERTEX AI OPTIONAL PARAM BLOCK - optional_params: {optional_params}"
|
||||||
)
|
)
|
||||||
|
@ -5639,17 +5627,7 @@ def get_supported_openai_params(model: str, custom_llm_provider: str):
|
||||||
elif custom_llm_provider == "palm" or custom_llm_provider == "gemini":
|
elif custom_llm_provider == "palm" or custom_llm_provider == "gemini":
|
||||||
return ["temperature", "top_p", "stream", "n", "stop", "max_tokens"]
|
return ["temperature", "top_p", "stream", "n", "stop", "max_tokens"]
|
||||||
elif custom_llm_provider == "vertex_ai":
|
elif custom_llm_provider == "vertex_ai":
|
||||||
return [
|
return litellm.VertexAIConfig().get_supported_openai_params()
|
||||||
"temperature",
|
|
||||||
"top_p",
|
|
||||||
"max_tokens",
|
|
||||||
"stream",
|
|
||||||
"tools",
|
|
||||||
"tool_choice",
|
|
||||||
"response_format",
|
|
||||||
"n",
|
|
||||||
"stop",
|
|
||||||
]
|
|
||||||
elif custom_llm_provider == "sagemaker":
|
elif custom_llm_provider == "sagemaker":
|
||||||
return ["stream", "temperature", "max_tokens", "top_p", "stop", "n"]
|
return ["stream", "temperature", "max_tokens", "top_p", "stop", "n"]
|
||||||
elif custom_llm_provider == "aleph_alpha":
|
elif custom_llm_provider == "aleph_alpha":
|
||||||
|
@ -6163,7 +6141,13 @@ def get_model_info(model: str):
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
raise Exception()
|
"""
|
||||||
|
Check if model in model cost map
|
||||||
|
"""
|
||||||
|
if model in litellm.model_cost:
|
||||||
|
return litellm.model_cost[model]
|
||||||
|
else:
|
||||||
|
raise Exception()
|
||||||
except:
|
except:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"This model isn't mapped yet. Add it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json"
|
"This model isn't mapped yet. Add it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json"
|
||||||
|
@ -7868,6 +7852,15 @@ def exception_type(
|
||||||
llm_provider="vertex_ai",
|
llm_provider="vertex_ai",
|
||||||
response=original_exception.response,
|
response=original_exception.response,
|
||||||
)
|
)
|
||||||
|
elif "None Unknown Error." in error_str:
|
||||||
|
exception_mapping_worked = True
|
||||||
|
raise APIError(
|
||||||
|
message=f"VertexAIException - {error_str}",
|
||||||
|
status_code=500,
|
||||||
|
model=model,
|
||||||
|
llm_provider="vertex_ai",
|
||||||
|
request=original_exception.request,
|
||||||
|
)
|
||||||
elif "403" in error_str:
|
elif "403" in error_str:
|
||||||
exception_mapping_worked = True
|
exception_mapping_worked = True
|
||||||
raise BadRequestError(
|
raise BadRequestError(
|
||||||
|
@ -8882,7 +8875,16 @@ class CustomStreamWrapper:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
def check_special_tokens(self, chunk: str, finish_reason: Optional[str]):
|
def check_special_tokens(self, chunk: str, finish_reason: Optional[str]):
|
||||||
|
"""
|
||||||
|
Output parse <s> / </s> special tokens for sagemaker + hf streaming.
|
||||||
|
"""
|
||||||
hold = False
|
hold = False
|
||||||
|
if (
|
||||||
|
self.custom_llm_provider != "huggingface"
|
||||||
|
and self.custom_llm_provider != "sagemaker"
|
||||||
|
):
|
||||||
|
return hold, chunk
|
||||||
|
|
||||||
if finish_reason:
|
if finish_reason:
|
||||||
for token in self.special_tokens:
|
for token in self.special_tokens:
|
||||||
if token in chunk:
|
if token in chunk:
|
||||||
|
@ -8898,6 +8900,7 @@ class CustomStreamWrapper:
|
||||||
for token in self.special_tokens:
|
for token in self.special_tokens:
|
||||||
if len(curr_chunk) < len(token) and curr_chunk in token:
|
if len(curr_chunk) < len(token) and curr_chunk in token:
|
||||||
hold = True
|
hold = True
|
||||||
|
self.holding_chunk = curr_chunk
|
||||||
elif len(curr_chunk) >= len(token):
|
elif len(curr_chunk) >= len(token):
|
||||||
if token in curr_chunk:
|
if token in curr_chunk:
|
||||||
self.holding_chunk = curr_chunk.replace(token, "")
|
self.holding_chunk = curr_chunk.replace(token, "")
|
||||||
|
@ -9979,6 +9982,7 @@ class CustomStreamWrapper:
|
||||||
f"model_response.choices[0].delta: {model_response.choices[0].delta}; completion_obj: {completion_obj}"
|
f"model_response.choices[0].delta: {model_response.choices[0].delta}; completion_obj: {completion_obj}"
|
||||||
)
|
)
|
||||||
print_verbose(f"self.sent_first_chunk: {self.sent_first_chunk}")
|
print_verbose(f"self.sent_first_chunk: {self.sent_first_chunk}")
|
||||||
|
|
||||||
## RETURN ARG
|
## RETURN ARG
|
||||||
if (
|
if (
|
||||||
"content" in completion_obj
|
"content" in completion_obj
|
||||||
|
@ -10051,7 +10055,6 @@ class CustomStreamWrapper:
|
||||||
elif self.received_finish_reason is not None:
|
elif self.received_finish_reason is not None:
|
||||||
if self.sent_last_chunk == True:
|
if self.sent_last_chunk == True:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
# flush any remaining holding chunk
|
# flush any remaining holding chunk
|
||||||
if len(self.holding_chunk) > 0:
|
if len(self.holding_chunk) > 0:
|
||||||
if model_response.choices[0].delta.content is None:
|
if model_response.choices[0].delta.content is None:
|
||||||
|
@ -10627,7 +10630,9 @@ def trim_messages(
|
||||||
if max_tokens is None:
|
if max_tokens is None:
|
||||||
# Check if model is valid
|
# Check if model is valid
|
||||||
if model in litellm.model_cost:
|
if model in litellm.model_cost:
|
||||||
max_tokens_for_model = litellm.model_cost[model].get("max_input_tokens", litellm.model_cost[model]["max_tokens"])
|
max_tokens_for_model = litellm.model_cost[model].get(
|
||||||
|
"max_input_tokens", litellm.model_cost[model]["max_tokens"]
|
||||||
|
)
|
||||||
max_tokens = int(max_tokens_for_model * trim_ratio)
|
max_tokens = int(max_tokens_for_model * trim_ratio)
|
||||||
else:
|
else:
|
||||||
# if user did not specify max (input) tokens
|
# if user did not specify max (input) tokens
|
||||||
|
|
|
@ -708,6 +708,16 @@
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true
|
"supports_function_calling": true
|
||||||
},
|
},
|
||||||
|
"mistral/open-mixtral-8x7b": {
|
||||||
|
"max_tokens": 8191,
|
||||||
|
"max_input_tokens": 32000,
|
||||||
|
"max_output_tokens": 8191,
|
||||||
|
"input_cost_per_token": 0.000002,
|
||||||
|
"output_cost_per_token": 0.000006,
|
||||||
|
"litellm_provider": "mistral",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true
|
||||||
|
},
|
||||||
"mistral/mistral-embed": {
|
"mistral/mistral-embed": {
|
||||||
"max_tokens": 8192,
|
"max_tokens": 8192,
|
||||||
"max_input_tokens": 8192,
|
"max_input_tokens": 8192,
|
||||||
|
@ -1012,6 +1022,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-1.5-pro-preview-0215": {
|
"gemini-1.5-pro-preview-0215": {
|
||||||
|
@ -1023,6 +1034,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-1.5-pro-preview-0409": {
|
"gemini-1.5-pro-preview-0409": {
|
||||||
|
@ -1034,6 +1046,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-experimental": {
|
"gemini-experimental": {
|
||||||
|
@ -1045,6 +1058,7 @@
|
||||||
"litellm_provider": "vertex_ai-language-models",
|
"litellm_provider": "vertex_ai-language-models",
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": false,
|
"supports_function_calling": false,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini-pro-vision": {
|
"gemini-pro-vision": {
|
||||||
|
@ -1271,6 +1285,7 @@
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
"supports_vision": true,
|
"supports_vision": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models#foundation_models"
|
||||||
},
|
},
|
||||||
"gemini/gemini-1.5-pro-latest": {
|
"gemini/gemini-1.5-pro-latest": {
|
||||||
|
@ -1283,6 +1298,7 @@
|
||||||
"mode": "chat",
|
"mode": "chat",
|
||||||
"supports_function_calling": true,
|
"supports_function_calling": true,
|
||||||
"supports_vision": true,
|
"supports_vision": true,
|
||||||
|
"supports_tool_choice": true,
|
||||||
"source": "https://ai.google.dev/models/gemini"
|
"source": "https://ai.google.dev/models/gemini"
|
||||||
},
|
},
|
||||||
"gemini/gemini-pro-vision": {
|
"gemini/gemini-pro-vision": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "litellm"
|
name = "litellm"
|
||||||
version = "1.35.10"
|
version = "1.35.13"
|
||||||
description = "Library to easily interface with LLM API providers"
|
description = "Library to easily interface with LLM API providers"
|
||||||
authors = ["BerriAI"]
|
authors = ["BerriAI"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
@ -80,7 +80,7 @@ requires = ["poetry-core", "wheel"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
||||||
[tool.commitizen]
|
[tool.commitizen]
|
||||||
version = "1.35.10"
|
version = "1.35.13"
|
||||||
version_files = [
|
version_files = [
|
||||||
"pyproject.toml:^version"
|
"pyproject.toml:^version"
|
||||||
]
|
]
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{87421:function(n,e,t){Promise.resolve().then(t.t.bind(t,99646,23)),Promise.resolve().then(t.t.bind(t,63385,23))},63385:function(){},99646:function(n){n.exports={style:{fontFamily:"'__Inter_c23dc8', '__Inter_Fallback_c23dc8'",fontStyle:"normal"},className:"__className_c23dc8"}}},function(n){n.O(0,[971,69,744],function(){return n(n.s=87421)}),_N_E=n.O()}]);
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{32028:function(e,n,t){Promise.resolve().then(t.t.bind(t,47690,23)),Promise.resolve().then(t.t.bind(t,48955,23)),Promise.resolve().then(t.t.bind(t,5613,23)),Promise.resolve().then(t.t.bind(t,11902,23)),Promise.resolve().then(t.t.bind(t,31778,23)),Promise.resolve().then(t.t.bind(t,77831,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,69],function(){return n(35317),n(32028)}),_N_E=e.O()}]);
|
|
@ -1 +1 @@
|
||||||
!function(){"use strict";var e,t,n,r,o,u,i,c,f,a={},l={};function d(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={id:e,loaded:!1,exports:{}},r=!0;try{a[e](n,n.exports,d),r=!1}finally{r&&delete l[e]}return n.loaded=!0,n.exports}d.m=a,e=[],d.O=function(t,n,r,o){if(n){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u<e.length;u++){for(var n=e[u][0],r=e[u][1],o=e[u][2],c=!0,f=0;f<n.length;f++)i>=o&&Object.keys(d.O).every(function(e){return d.O[e](n[f])})?n.splice(f--,1):(c=!1,o<i&&(i=o));if(c){e.splice(u--,1);var a=r();void 0!==a&&(t=a)}}return t},d.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,r){if(1&r&&(e=this(e)),8&r||"object"==typeof e&&e&&(4&r&&e.__esModule||16&r&&"function"==typeof e.then))return e;var o=Object.create(null);d.r(o);var u={};t=t||[null,n({}),n([]),n(n)];for(var i=2&r&&e;"object"==typeof i&&!~t.indexOf(i);i=n(i))Object.getOwnPropertyNames(i).forEach(function(t){u[t]=function(){return e[t]}});return u.default=function(){return e},d.d(o,u),o},d.d=function(e,t){for(var n in t)d.o(t,n)&&!d.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce(function(t,n){return d.f[n](e,t),t},[]))},d.u=function(e){},d.miniCssF=function(e){return"static/css/11cfce8bfdf6e8f1.css"},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r={},o="_N_E:",d.l=function(e,t,n,u){if(r[e]){r[e].push(t);return}if(void 0!==n)for(var i,c,f=document.getElementsByTagName("script"),a=0;a<f.length;a++){var l=f[a];if(l.getAttribute("src")==e||l.getAttribute("data-webpack")==o+n){i=l;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,d.nc&&i.setAttribute("nonce",d.nc),i.setAttribute("data-webpack",o+n),i.src=d.tu(e)),r[e]=[t];var s=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=s.bind(null,i.onerror),i.onload=s.bind(null,i.onload),c&&document.head.appendChild(i)},d.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e},d.tt=function(){return void 0===u&&(u={createScriptURL:function(e){return e}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(u=trustedTypes.createPolicy("nextjs#bundler",u))),u},d.tu=function(e){return d.tt().createScriptURL(e)},d.p="/ui/_next/",i={272:0},d.f.j=function(e,t){var n=d.o(i,e)?i[e]:void 0;if(0!==n){if(n)t.push(n[2]);else if(272!=e){var r=new Promise(function(t,r){n=i[e]=[t,r]});t.push(n[2]=r);var o=d.p+d.u(e),u=Error();d.l(o,function(t){if(d.o(i,e)&&(0!==(n=i[e])&&(i[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",u.name="ChunkLoadError",u.type=r,u.request=o,n[1](u)}},"chunk-"+e,e)}else i[e]=0}},d.O.j=function(e){return 0===i[e]},c=function(e,t){var n,r,o=t[0],u=t[1],c=t[2],f=0;if(o.some(function(e){return 0!==i[e]})){for(n in u)d.o(u,n)&&(d.m[n]=u[n]);if(c)var a=c(d)}for(e&&e(t);f<o.length;f++)r=o[f],d.o(i,r)&&i[r]&&i[r][0](),i[r]=0;return d.O(a)},(f=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(c.bind(null,0)),f.push=c.bind(null,f.push.bind(f))}();
|
!function(){"use strict";var e,t,n,r,o,u,i,c,f,a={},l={};function d(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={id:e,loaded:!1,exports:{}},r=!0;try{a[e](n,n.exports,d),r=!1}finally{r&&delete l[e]}return n.loaded=!0,n.exports}d.m=a,e=[],d.O=function(t,n,r,o){if(n){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u<e.length;u++){for(var n=e[u][0],r=e[u][1],o=e[u][2],c=!0,f=0;f<n.length;f++)i>=o&&Object.keys(d.O).every(function(e){return d.O[e](n[f])})?n.splice(f--,1):(c=!1,o<i&&(i=o));if(c){e.splice(u--,1);var a=r();void 0!==a&&(t=a)}}return t},d.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,r){if(1&r&&(e=this(e)),8&r||"object"==typeof e&&e&&(4&r&&e.__esModule||16&r&&"function"==typeof e.then))return e;var o=Object.create(null);d.r(o);var u={};t=t||[null,n({}),n([]),n(n)];for(var i=2&r&&e;"object"==typeof i&&!~t.indexOf(i);i=n(i))Object.getOwnPropertyNames(i).forEach(function(t){u[t]=function(){return e[t]}});return u.default=function(){return e},d.d(o,u),o},d.d=function(e,t){for(var n in t)d.o(t,n)&&!d.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce(function(t,n){return d.f[n](e,t),t},[]))},d.u=function(e){},d.miniCssF=function(e){return"static/css/dc347b0d22ffde5d.css"},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r={},o="_N_E:",d.l=function(e,t,n,u){if(r[e]){r[e].push(t);return}if(void 0!==n)for(var i,c,f=document.getElementsByTagName("script"),a=0;a<f.length;a++){var l=f[a];if(l.getAttribute("src")==e||l.getAttribute("data-webpack")==o+n){i=l;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,d.nc&&i.setAttribute("nonce",d.nc),i.setAttribute("data-webpack",o+n),i.src=d.tu(e)),r[e]=[t];var s=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=s.bind(null,i.onerror),i.onload=s.bind(null,i.onload),c&&document.head.appendChild(i)},d.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e},d.tt=function(){return void 0===u&&(u={createScriptURL:function(e){return e}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(u=trustedTypes.createPolicy("nextjs#bundler",u))),u},d.tu=function(e){return d.tt().createScriptURL(e)},d.p="/ui/_next/",i={272:0},d.f.j=function(e,t){var n=d.o(i,e)?i[e]:void 0;if(0!==n){if(n)t.push(n[2]);else if(272!=e){var r=new Promise(function(t,r){n=i[e]=[t,r]});t.push(n[2]=r);var o=d.p+d.u(e),u=Error();d.l(o,function(t){if(d.o(i,e)&&(0!==(n=i[e])&&(i[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",u.name="ChunkLoadError",u.type=r,u.request=o,n[1](u)}},"chunk-"+e,e)}else i[e]=0}},d.O.j=function(e){return 0===i[e]},c=function(e,t){var n,r,o=t[0],u=t[1],c=t[2],f=0;if(o.some(function(e){return 0!==i[e]})){for(n in u)d.o(u,n)&&(d.m[n]=u[n]);if(c)var a=c(d)}for(e&&e(t);f<o.length;f++)r=o[f],d.o(i,r)&&i[r]&&i[r][0](),i[r]=0;return d.O(a)},(f=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(c.bind(null,0)),f.push=c.bind(null,f.push.bind(f))}();
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-d6107f1aac0c574c.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
|
@ -0,0 +1 @@
|
||||||
|
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-59f93936973f5f5a.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-bcf69420342937de.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-442a9c01c3fd20f9.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-096338c8e1915716.js" async="" crossorigin=""></script><title>LiteLLM Dashboard</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-59f93936973f5f5a.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/11cfce8bfdf6e8f1.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[88740,[\"289\",\"static/chunks/289-04be6cb9636840d2.js\",\"931\",\"static/chunks/app/page-2c0827b33aed42d7.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/11cfce8bfdf6e8f1.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"TqpzjpOA_s5IXVzgrYZ-F\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[],\"styles\":null}]}]}],null]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"LiteLLM Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"LiteLLM Proxy Admin UI\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/ui/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"16x16\"}],[\"$\",\"meta\",\"5\",{\"name\":\"next-size-adjust\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-75b5d58291566cf9.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-bcf69420342937de.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-442a9c01c3fd20f9.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-9b4fb13a7db53edf.js" async="" crossorigin=""></script><title>LiteLLM Dashboard</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-75b5d58291566cf9.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/dc347b0d22ffde5d.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[21225,[\"289\",\"static/chunks/289-04be6cb9636840d2.js\",\"931\",\"static/chunks/app/page-cb85da9a307105a0.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/dc347b0d22ffde5d.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"y7Wf8hfvd5KooOO87je1n\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[],\"styles\":null}]}]}],null]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"LiteLLM Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"LiteLLM Proxy Admin UI\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/ui/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"16x16\"}],[\"$\",\"meta\",\"5\",{\"name\":\"next-size-adjust\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
|
@ -1,7 +1,7 @@
|
||||||
2:I[77831,[],""]
|
2:I[77831,[],""]
|
||||||
3:I[88740,["289","static/chunks/289-04be6cb9636840d2.js","931","static/chunks/app/page-2c0827b33aed42d7.js"],""]
|
3:I[21225,["289","static/chunks/289-04be6cb9636840d2.js","931","static/chunks/app/page-cb85da9a307105a0.js"],""]
|
||||||
4:I[5613,[],""]
|
4:I[5613,[],""]
|
||||||
5:I[31778,[],""]
|
5:I[31778,[],""]
|
||||||
0:["TqpzjpOA_s5IXVzgrYZ-F",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/11cfce8bfdf6e8f1.css","precedence":"next","crossOrigin":""}]],"$L6"]]]]
|
0:["y7Wf8hfvd5KooOO87je1n",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/dc347b0d22ffde5d.css","precedence":"next","crossOrigin":""}]],"$L6"]]]]
|
||||||
6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"LiteLLM Dashboard"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]]
|
6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"LiteLLM Dashboard"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]]
|
||||||
1:null
|
1:null
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { TabPanel, TabPanels, TabGroup, TabList, Tab, TextInput, Icon } from "@tremor/react";
|
import { TabPanel, TabPanels, TabGroup, TabList, Tab, TextInput, Icon } from "@tremor/react";
|
||||||
import { Select, SelectItem, MultiSelect, MultiSelectItem } from "@tremor/react";
|
import { Select, SelectItem, MultiSelect, MultiSelectItem } from "@tremor/react";
|
||||||
import { modelInfoCall, userGetRequesedtModelsCall, modelMetricsCall, modelCreateCall, Model, modelCostMap, modelDeleteCall, healthCheckCall } from "./networking";
|
import { modelInfoCall, userGetRequesedtModelsCall, modelCreateCall, Model, modelCostMap, modelDeleteCall, healthCheckCall } from "./networking";
|
||||||
import { BarChart } from "@tremor/react";
|
import { BarChart } from "@tremor/react";
|
||||||
import {
|
import {
|
||||||
Button as Button2,
|
Button as Button2,
|
||||||
|
@ -78,7 +78,6 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
userID,
|
userID,
|
||||||
}) => {
|
}) => {
|
||||||
const [modelData, setModelData] = useState<any>({ data: [] });
|
const [modelData, setModelData] = useState<any>({ data: [] });
|
||||||
const [modelMetrics, setModelMetrics] = useState<any[]>([]);
|
|
||||||
const [pendingRequests, setPendingRequests] = useState<any[]>([]);
|
const [pendingRequests, setPendingRequests] = useState<any[]>([]);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [modelMap, setModelMap] = useState<any>(null);
|
const [modelMap, setModelMap] = useState<any>(null);
|
||||||
|
@ -136,14 +135,7 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
console.log("Model data response:", modelDataResponse.data);
|
console.log("Model data response:", modelDataResponse.data);
|
||||||
setModelData(modelDataResponse);
|
setModelData(modelDataResponse);
|
||||||
|
|
||||||
const modelMetricsResponse = await modelMetricsCall(
|
|
||||||
accessToken,
|
|
||||||
userID,
|
|
||||||
userRole
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("Model metrics response:", modelMetricsResponse);
|
|
||||||
setModelMetrics(modelMetricsResponse);
|
|
||||||
|
|
||||||
// if userRole is Admin, show the pending requests
|
// if userRole is Admin, show the pending requests
|
||||||
if (userRole === "Admin" && accessToken) {
|
if (userRole === "Admin" && accessToken) {
|
||||||
|
@ -484,30 +476,7 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</Card>
|
</Card>
|
||||||
<Card>
|
|
||||||
<Title>Model Statistics (Number Requests)</Title>
|
|
||||||
<BarChart
|
|
||||||
data={modelMetrics}
|
|
||||||
index="model"
|
|
||||||
categories={["num_requests"]}
|
|
||||||
colors={["blue"]}
|
|
||||||
yAxisWidth={400}
|
|
||||||
layout="vertical"
|
|
||||||
tickGap={5}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
<Card>
|
|
||||||
<Title>Model Statistics (Latency)</Title>
|
|
||||||
<BarChart
|
|
||||||
data={modelMetrics}
|
|
||||||
index="model"
|
|
||||||
categories={["avg_latency_seconds"]}
|
|
||||||
colors={["red"]}
|
|
||||||
yAxisWidth={400}
|
|
||||||
layout="vertical"
|
|
||||||
tickGap={5}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel className="h-full">
|
<TabPanel className="h-full">
|
||||||
|
|
|
@ -11,7 +11,8 @@ import {
|
||||||
adminTopKeysCall,
|
adminTopKeysCall,
|
||||||
adminTopModelsCall,
|
adminTopModelsCall,
|
||||||
teamSpendLogsCall,
|
teamSpendLogsCall,
|
||||||
tagsSpendLogsCall
|
tagsSpendLogsCall,
|
||||||
|
modelMetricsCall,
|
||||||
} from "./networking";
|
} from "./networking";
|
||||||
import { start } from "repl";
|
import { start } from "repl";
|
||||||
|
|
||||||
|
@ -143,6 +144,8 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
const [topTagsData, setTopTagsData] = useState<any[]>([]);
|
const [topTagsData, setTopTagsData] = useState<any[]>([]);
|
||||||
const [uniqueTeamIds, setUniqueTeamIds] = useState<any[]>([]);
|
const [uniqueTeamIds, setUniqueTeamIds] = useState<any[]>([]);
|
||||||
const [totalSpendPerTeam, setTotalSpendPerTeam] = useState<any[]>([]);
|
const [totalSpendPerTeam, setTotalSpendPerTeam] = useState<any[]>([]);
|
||||||
|
const [modelMetrics, setModelMetrics] = useState<any[]>([]);
|
||||||
|
const [modelLatencyMetrics, setModelLatencyMetrics] = useState<any[]>([]);
|
||||||
|
|
||||||
const firstDay = new Date(
|
const firstDay = new Date(
|
||||||
currentDate.getFullYear(),
|
currentDate.getFullYear(),
|
||||||
|
@ -223,6 +226,8 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
//get top tags
|
//get top tags
|
||||||
const top_tags = await tagsSpendLogsCall(accessToken);
|
const top_tags = await tagsSpendLogsCall(accessToken);
|
||||||
setTopTagsData(top_tags.top_10_tags);
|
setTopTagsData(top_tags.top_10_tags);
|
||||||
|
|
||||||
|
|
||||||
} else if (userRole == "App Owner") {
|
} else if (userRole == "App Owner") {
|
||||||
await userSpendLogsCall(
|
await userSpendLogsCall(
|
||||||
accessToken,
|
accessToken,
|
||||||
|
@ -259,6 +264,21 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const modelMetricsResponse = await modelMetricsCall(
|
||||||
|
accessToken,
|
||||||
|
userID,
|
||||||
|
userRole
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Model metrics response:", modelMetricsResponse);
|
||||||
|
// Sort by latency (avg_latency_seconds)
|
||||||
|
const sortedByLatency = [...modelMetricsResponse].sort((a, b) => b.avg_latency_seconds - a.avg_latency_seconds);
|
||||||
|
console.log("Sorted by latency:", sortedByLatency);
|
||||||
|
|
||||||
|
setModelMetrics(modelMetricsResponse);
|
||||||
|
setModelLatencyMetrics(sortedByLatency);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("There was an error fetching the data", error);
|
console.error("There was an error fetching the data", error);
|
||||||
// Optionally, update your UI to reflect the error state here as well
|
// Optionally, update your UI to reflect the error state here as well
|
||||||
|
@ -281,6 +301,7 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
<Tab>All Up</Tab>
|
<Tab>All Up</Tab>
|
||||||
<Tab>Team Based Usage</Tab>
|
<Tab>Team Based Usage</Tab>
|
||||||
<Tab>Tag Based Usage</Tab>
|
<Tab>Tag Based Usage</Tab>
|
||||||
|
<Tab>Model Based Usage</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
|
@ -420,6 +441,36 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
</Col>
|
</Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
||||||
|
<TabPanel>
|
||||||
|
<Card>
|
||||||
|
<Title>Number Requests per Model</Title>
|
||||||
|
<BarChart
|
||||||
|
data={modelMetrics}
|
||||||
|
className="h-[50vh]"
|
||||||
|
index="model"
|
||||||
|
categories={["num_requests"]}
|
||||||
|
colors={["blue"]}
|
||||||
|
yAxisWidth={400}
|
||||||
|
layout="vertical"
|
||||||
|
tickGap={5}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
<Card className="mt-4">
|
||||||
|
<Title>Latency Per Model</Title>
|
||||||
|
<BarChart
|
||||||
|
data={modelLatencyMetrics}
|
||||||
|
className="h-[50vh]"
|
||||||
|
index="model"
|
||||||
|
categories={["avg_latency_seconds"]}
|
||||||
|
colors={["red"]}
|
||||||
|
yAxisWidth={400}
|
||||||
|
layout="vertical"
|
||||||
|
tickGap={5}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</TabGroup>
|
</TabGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue