Merge branch 'main' into main

This commit is contained in:
Vince Lwt 2023-08-23 18:39:09 +02:00 committed by GitHub
commit dcbf5e2444
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 9611 additions and 239 deletions

View file

@ -3,3 +3,4 @@ openai
python-dotenv python-dotenv
openai openai
tiktoken tiktoken
importlib_metadata

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
.env .env
litellm_uuid.txt litellm_uuid.txt
__pycache__/ __pycache__/
bun.lockb

View file

@ -3,7 +3,6 @@
[![PyPI Version](https://img.shields.io/badge/stable%20version-v0.1.424-blue?color=green&link=https://pypi.org/project/litellm/0.1.1/)](https://pypi.org/project/litellm/0.1.1/) [![PyPI Version](https://img.shields.io/badge/stable%20version-v0.1.424-blue?color=green&link=https://pypi.org/project/litellm/0.1.1/)](https://pypi.org/project/litellm/0.1.1/)
[![CircleCI](https://dl.circleci.com/status-badge/img/gh/BerriAI/litellm/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/BerriAI/litellm/tree/main) [![CircleCI](https://dl.circleci.com/status-badge/img/gh/BerriAI/litellm/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/BerriAI/litellm/tree/main)
![Downloads](https://img.shields.io/pypi/dm/litellm) ![Downloads](https://img.shields.io/pypi/dm/litellm)
[![litellm](https://img.shields.io/badge/%20%F0%9F%9A%85%20liteLLM-OpenAI%7CAzure%7CAnthropic%7CPalm%7CCohere%7CReplicate%7CHugging%20Face-blue?color=green)](https://github.com/BerriAI/litellm)
[![](https://dcbadge.vercel.app/api/server/wuPM9dRgDw)](https://discord.gg/wuPM9dRgDw) [![](https://dcbadge.vercel.app/api/server/wuPM9dRgDw)](https://discord.gg/wuPM9dRgDw)
@ -12,10 +11,11 @@ a light package to simplify calling OpenAI, Azure, Cohere, Anthropic, Huggingfac
- guarantees [consistent output](https://litellm.readthedocs.io/en/latest/output/), text responses will always be available at `['choices'][0]['message']['content']` - guarantees [consistent output](https://litellm.readthedocs.io/en/latest/output/), text responses will always be available at `['choices'][0]['message']['content']`
- exception mapping - common exceptions across providers are mapped to the [OpenAI exception types](https://help.openai.com/en/articles/6897213-openai-library-error-types-guidance) - exception mapping - common exceptions across providers are mapped to the [OpenAI exception types](https://help.openai.com/en/articles/6897213-openai-library-error-types-guidance)
# usage # usage
<a href='https://docs.litellm.ai/docs/completion/supported' target="_blank"><img alt='None' src='https://img.shields.io/badge/Supported_LLMs-100000?style=for-the-badge&logo=None&logoColor=000000&labelColor=000000&color=8400EA'/></a> <a href='https://docs.litellm.ai/docs/completion/supported' target="_blank"><img alt='None' src='https://img.shields.io/badge/100+_Supported_LLMs_liteLLM-100000?style=for-the-badge&logo=None&logoColor=000000&labelColor=000000&color=8400EA'/></a>
Demo - https://litellm.ai/playground \ Demo - https://litellm.ai/playground
Read the docs - https://docs.litellm.ai/docs/ Docs - https://docs.litellm.ai/docs/
**Free** Dashboard - https://docs.litellm.ai/docs/debugging/hosted_debugging
## quick start ## quick start
``` ```

View file

@ -0,0 +1,251 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"# LiteLLM A121 Tutorial\n",
"\n",
"This walks through using A121 Jurassic models\n",
"* j2-light\n",
"* j2-mid\n",
"* j2-ultra"
],
"metadata": {
"id": "LeFYo8iqcn5g"
}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "GslPQFmaZsp-"
},
"outputs": [],
"source": [
"!pip install litellm"
]
},
{
"cell_type": "code",
"source": [
"from litellm import completion\n",
"import os"
],
"metadata": {
"id": "P3cKiqURZx7P"
},
"execution_count": 2,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Set A121 Keys\n",
"You can get a free key from https://studio.ai21.com/account/api-key"
],
"metadata": {
"id": "tmTvA1_GaNU4"
}
},
{
"cell_type": "code",
"source": [
"os.environ[\"AI21_API_KEY\"] = \"\""
],
"metadata": {
"id": "_xX8LmxAZ2vp"
},
"execution_count": 5,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# A121 Supported Models:\n",
"https://studio.ai21.com/foundation-models"
],
"metadata": {
"id": "Fx5ZfJTLbF0A"
}
},
{
"cell_type": "markdown",
"source": [
"## J2-light Call"
],
"metadata": {
"id": "H0tl-0Z3bDaL"
}
},
{
"cell_type": "code",
"source": [
"messages = [{ \"content\": \"Hello, how are you?\",\"role\": \"user\"}]\n",
"response = completion(model=\"j2-light\", messages=messages)\n",
"response"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "DZnApsJUZ_I2",
"outputId": "b5707cbe-f67c-47f7-bac5-a7b8af1ba815"
},
"execution_count": 6,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<ModelResponse at 0x7b2c2902e610> JSON: {\n",
" \"choices\": [\n",
" {\n",
" \"finish_reason\": \"stop\",\n",
" \"index\": 0,\n",
" \"message\": {\n",
" \"content\": \" However, I have an important question to ask you\\nMy name is X, and I was wondering if you would be willing to help me.\",\n",
" \"role\": \"assistant\"\n",
" }\n",
" }\n",
" ],\n",
" \"created\": 1692761063.5189915,\n",
" \"model\": \"j2-light\",\n",
" \"usage\": {\n",
" \"prompt_tokens\": null,\n",
" \"completion_tokens\": null,\n",
" \"total_tokens\": null\n",
" }\n",
"}"
]
},
"metadata": {},
"execution_count": 6
}
]
},
{
"cell_type": "markdown",
"source": [
"# J2-Mid"
],
"metadata": {
"id": "wCcnrYnnbMQA"
}
},
{
"cell_type": "code",
"source": [
"messages = [{ \"content\": \"what model are you\",\"role\": \"user\"}]\n",
"response = completion(model=\"j2-mid\", messages=messages)\n",
"response"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "-5Sxf4blaeEl",
"outputId": "6264a5e8-16d6-44a3-e167-9e0c59b6dbc4"
},
"execution_count": 7,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<ModelResponse at 0x7b2c2902f6a0> JSON: {\n",
" \"choices\": [\n",
" {\n",
" \"finish_reason\": \"stop\",\n",
" \"index\": 0,\n",
" \"message\": {\n",
" \"content\": \"\\nplease choose the model from the list below\\nModel view in Tekla Structures\",\n",
" \"role\": \"assistant\"\n",
" }\n",
" }\n",
" ],\n",
" \"created\": 1692761140.0017524,\n",
" \"model\": \"j2-mid\",\n",
" \"usage\": {\n",
" \"prompt_tokens\": null,\n",
" \"completion_tokens\": null,\n",
" \"total_tokens\": null\n",
" }\n",
"}"
]
},
"metadata": {},
"execution_count": 7
}
]
},
{
"cell_type": "markdown",
"source": [
"# J2-Ultra"
],
"metadata": {
"id": "wDARpjxtbUcg"
}
},
{
"cell_type": "code",
"source": [
"messages = [{ \"content\": \"what model are you\",\"role\": \"user\"}]\n",
"response = completion(model=\"j2-ultra\", messages=messages)\n",
"response"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "i228xwsYbSYo",
"outputId": "3765ac56-5a9b-442e-b357-2e346d02e1df"
},
"execution_count": 8,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<ModelResponse at 0x7b2c28fd4090> JSON: {\n",
" \"choices\": [\n",
" {\n",
" \"finish_reason\": \"stop\",\n",
" \"index\": 0,\n",
" \"message\": {\n",
" \"content\": \"\\nI am not a specific model, but I can provide information and assistance based on my training data. Please let me know if there is anything you\",\n",
" \"role\": \"assistant\"\n",
" }\n",
" }\n",
" ],\n",
" \"created\": 1692761157.8675153,\n",
" \"model\": \"j2-ultra\",\n",
" \"usage\": {\n",
" \"prompt_tokens\": null,\n",
" \"completion_tokens\": null,\n",
" \"total_tokens\": null\n",
" }\n",
"}"
]
},
"metadata": {},
"execution_count": 8
}
]
}
]
}

BIN
dist/litellm-0.1.446-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
dist/litellm-0.1.446.tar.gz vendored Normal file

Binary file not shown.

BIN
dist/litellm-0.1.452-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
dist/litellm-0.1.452.tar.gz vendored Normal file

Binary file not shown.

BIN
dist/litellm-0.1.455-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
dist/litellm-0.1.455.tar.gz vendored Normal file

Binary file not shown.

BIN
dist/litellm-0.1.456-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
dist/litellm-0.1.456.tar.gz vendored Normal file

Binary file not shown.

View file

@ -77,6 +77,22 @@ Here are some examples of supported models:
| [bigcode/starcoder](https://huggingface.co/bigcode/starcoder) | `completion(model="bigcode/starcoder", messages=messages, custom_llm_provider="huggingface")` | `os.environ['HUGGINGFACE_API_KEY']` | | [bigcode/starcoder](https://huggingface.co/bigcode/starcoder) | `completion(model="bigcode/starcoder", messages=messages, custom_llm_provider="huggingface")` | `os.environ['HUGGINGFACE_API_KEY']` |
| [google/flan-t5-xxl](https://huggingface.co/google/flan-t5-xxl) | `completion(model="google/flan-t5-xxl", messages=messages, custom_llm_provider="huggingface")` | `os.environ['HUGGINGFACE_API_KEY']` | | [google/flan-t5-xxl](https://huggingface.co/google/flan-t5-xxl) | `completion(model="google/flan-t5-xxl", messages=messages, custom_llm_provider="huggingface")` | `os.environ['HUGGINGFACE_API_KEY']` |
| [google/flan-t5-large](https://huggingface.co/google/flan-t5-large) | `completion(model="google/flan-t5-large", messages=messages, custom_llm_provider="huggingface")` | `os.environ['HUGGINGFACE_API_KEY']` | | [google/flan-t5-large](https://huggingface.co/google/flan-t5-large) | `completion(model="google/flan-t5-large", messages=messages, custom_llm_provider="huggingface")` | `os.environ['HUGGINGFACE_API_KEY']` |
### Replicate Models
liteLLM supports all replicate LLMs. For replicate models ensure to add a `replicate` prefix to the `model` arg. liteLLM detects it using this arg.
Below are examples on how to call replicate LLMs using liteLLM
Model Name | Function Call | Required OS Variables |
-----------------------------|----------------------------------------------------------------|--------------------------------------|
replicate/llama-2-70b-chat | `completion('replicate/replicate/llama-2-70b-chat', messages)` | `os.environ['REPLICATE_API_KEY']` |
a16z-infra/llama-2-13b-chat| `completion('replicate/a16z-infra/llama-2-13b-chat', messages)`| `os.environ['REPLICATE_API_KEY']` |
joehoover/instructblip-vicuna13b | `completion('replicate/joehoover/instructblip-vicuna13b', messages)` | `os.environ['REPLICATE_API_KEY']` |
replicate/dolly-v2-12b | `completion('replicate/replicate/dolly-v2-12b', messages)` | `os.environ['REPLICATE_API_KEY']` |
a16z-infra/llama-2-7b-chat | `completion('replicate/a16z-infra/llama-2-7b-chat', messages)` | `os.environ['REPLICATE_API_KEY']` |
replicate/vicuna-13b | `completion('replicate/replicate/vicuna-13b', messages)` | `os.environ['REPLICATE_API_KEY']` |
daanelson/flan-t5-large | `completion('replicate/daanelson/flan-t5-large', messages)` | `os.environ['REPLICATE_API_KEY']` |
replit/replit-code-v1-3b | `completion('replicate/replit/replit-code-v1-3b', messages)` | `os.environ['REPLICATE_API_KEY']` |
### AI21 Models ### AI21 Models
| Model Name | Function Call | Required OS Variables | | Model Name | Function Call | Required OS Variables |
@ -112,9 +128,9 @@ Example Baseten Usage - Note: liteLLM supports all models deployed on Basten
| Model Name | Function Call | Required OS Variables | | Model Name | Function Call | Required OS Variables |
|------------------|--------------------------------------------|------------------------------------| |------------------|--------------------------------------------|------------------------------------|
| Falcon 7B | `completion(model='<your model version id>', messages=messages, custom_llm_provider="baseten")` | `os.environ['BASETEN_API_KEY']` | | Falcon 7B | `completion(model='baseten/qvv0xeq', messages=messages)` | `os.environ['BASETEN_API_KEY']` |
| Wizard LM | `completion(model='<your model version id>', messages=messages, custom_llm_provider="baseten")` | `os.environ['BASETEN_API_KEY']` | | Wizard LM | `completion(model='baseten/q841o8w', messages=messages)` | `os.environ['BASETEN_API_KEY']` |
| MPT 7B Base | `completion(model='<your model version id>', messages=messages, custom_llm_provider="baseten")` | `os.environ['BASETEN_API_KEY']` | | MPT 7B Base | `completion(model='baseten/31dxrj3', messages=messages)` | `os.environ['BASETEN_API_KEY']` |
### OpenRouter Completion Models ### OpenRouter Completion Models

View file

@ -0,0 +1,40 @@
import Image from '@theme/IdealImage';
# Debugging Dashboard
LiteLLM offers a free UI to debug your calls + add new models at (https://admin.litellm.ai/). This is useful if you're testing your LiteLLM server and need to see if the API calls were made successfully **or** want to add new models without going into code.
**Needs litellm>=0.1.438***
## Setup
Once created, your dashboard is viewable at - `admin.litellm.ai/<your_email>` [👋 Tell us if you need better privacy controls](https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version?month=2023-08)
You can set your user email in 2 ways.
- By setting it on the module - `litellm.email=<your_email>`.
- By setting it as an environment variable - `os.environ["LITELLM_EMAIL"] = "your_email"`.
<Image img={require('../../img/dashboard.png')} alt="Dashboard" />
See our live dashboard 👉 [admin.litellm.ai](https://admin.litellm.ai/)
## Example Usage
```
import litellm
from litellm import embedding, completion
## Set your email
litellm.email = "test_email@test.com"
user_message = "Hello, how are you?"
messages = [{ "content": user_message,"role": "user"}]
# openai call
response = completion(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}])
# bad request call
response = completion(model="chatgpt-test", messages=[{"role": "user", "content": "Hi 👋 - i'm a bad request"}])
```

View file

@ -55,3 +55,9 @@ response = completion(model="gpt-3.5-turbo", messages=messages, logger_fn=my_cus
# cohere call # cohere call
response = completion("command-nightly", messages, logger_fn=my_custom_logging_fn) response = completion("command-nightly", messages, logger_fn=my_custom_logging_fn)
``` ```
## Still Seeing Issues?
Text us @ +17708783106 or Join the [Discord](https://discord.com/invite/wuPM9dRgDw).
We promise to help you in `lite`ning speed ❤️

View file

@ -1,4 +1,4 @@
## liteLLM Together AI Tutorial # liteLLM Together AI Tutorial
https://together.ai/ https://together.ai/

View file

@ -1,32 +0,0 @@
# Debugging UI Tutorial
LiteLLM offers a free hosted debugger UI for your api calls. Useful if you're testing your LiteLLM server and need to see if the API calls were made successfully.
You can enable this setting `lite_debugger` as a callback.
## Example Usage
```
import litellm
from litellm import embedding, completion
litellm.input_callback = ["lite_debugger"]
litellm.success_callback = ["lite_debugger"]
litellm.failure_callback = ["lite_debugger"]
litellm.set_verbose = True
user_message = "Hello, how are you?"
messages = [{ "content": user_message,"role": "user"}]
# openai call
response = completion(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}])
# bad request call
response = completion(model="chatgpt-test", messages=[{"role": "user", "content": "Hi 👋 - i'm a bad request"}])
```
## Requirements
## How to see the UI

View file

@ -0,0 +1,41 @@
# Using completion() with Fallbacks for Reliability
This tutorial demonstrates how to employ the `completion()` function with model fallbacks to ensure reliability. LLM APIs can be unstable, completion() with fallbacks ensures you'll always get a response from your calls
## Usage
To use fallback models with `completion()`, specify a list of models in the `fallbacks` parameter.
```python
response = completion(model="bad-model", messages=messages, fallbacks=["gpt-3.5-turbo" "command-nightly"])
```
### Output from calls
```
Completion with 'bad-model': got exception Unable to map your input to a model. Check your input - {'model': 'bad-model'
completion call gpt-3.5-turbo
{
"id": "chatcmpl-7qTmVRuO3m3gIBg4aTmAumV1TmQhB",
"object": "chat.completion",
"created": 1692741891,
"model": "gpt-3.5-turbo-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "I apologize, but as an AI, I do not have the capability to provide real-time weather updates. However, you can easily check the current weather in San Francisco by using a search engine or checking a weather website or app."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 16,
"completion_tokens": 46,
"total_tokens": 62
}
}
```

View file

@ -0,0 +1,22 @@
# Using Fine-Tuned gpt-3.5-turbo
LiteLLM allows you to call `completion` with your fine-tuned gpt-3.5-turbo models
If you're trying to create your custom finetuned gpt-3.5-turbo model following along on this tutorial: https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset
Once you've created your fine tuned model, you can call it with `completion()`
## Usage
```python
import os
from litellm import completion
# set your OPENAI key in your .env as "OPENAI_API_KEY"
response = completion(
model="ft:gpt-3.5-turbo:my-org:custom_suffix:id",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
)
print(response.choices[0].message)
```

View file

@ -1,21 +0,0 @@
import React from 'react';
import Layout from '@theme/Layout';
export default function Hello() {
return (
<Layout title="Hello" description="Hello React Page">
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50vh',
fontSize: '20px',
}}>
<p>
Edit <code>pages/helloReact.js</code> and save to reload.
</p>
</div>
</Layout>
);
}

View file

@ -27,6 +27,22 @@ const config = {
locales: ['en'], locales: ['en'],
}, },
plugins: [
[
'@docusaurus/plugin-ideal-image',
{
quality: 70,
max: 1030, // max resized image's size.
min: 640, // min resized image's size. if original is lower, use that size.
steps: 2, // the max number of images generated between min and max (inclusive)
disableInDev: false,
},
],
[ require.resolve('docusaurus-lunr-search'), {
languages: ['en'] // language codes
}]
],
presets: [ presets: [
[ [
'classic', 'classic',
@ -72,7 +88,7 @@ const config = {
items: [ items: [
{ {
label: 'Tutorial', label: 'Tutorial',
to: '/docs/intro', to: '/docs/index',
}, },
], ],
}, },

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -9,12 +9,14 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@docusaurus/core": "2.4.1", "@docusaurus/core": "2.4.1",
"@docusaurus/plugin-ideal-image": "^2.4.1",
"@docusaurus/preset-classic": "2.4.1", "@docusaurus/preset-classic": "2.4.1",
"@mdx-js/react": "^1.6.22", "@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1", "clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5", "prism-react-renderer": "^1.3.5",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2" "react-dom": "^17.0.2",
"uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "2.4.1" "@docusaurus/module-type-aliases": "2.4.1"
@ -2268,6 +2270,21 @@
"node": ">=16.14" "node": ">=16.14"
} }
}, },
"node_modules/@docusaurus/lqip-loader": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-2.4.1.tgz",
"integrity": "sha512-XJ0z/xSx5HtAQ+/xBoAiRZ7DY9zEP6IImAKlAk6RxuFzyB4HT8eINWN+LwLnOsTh5boIj37JCX+T76bH0ieULA==",
"dependencies": {
"@docusaurus/logger": "2.4.1",
"file-loader": "^6.2.0",
"lodash": "^4.17.21",
"sharp": "^0.30.7",
"tslib": "^2.4.0"
},
"engines": {
"node": ">=16.14"
}
},
"node_modules/@docusaurus/mdx-loader": { "node_modules/@docusaurus/mdx-loader": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.1.tgz",
@ -2474,6 +2491,37 @@
"react-dom": "^16.8.4 || ^17.0.0" "react-dom": "^16.8.4 || ^17.0.0"
} }
}, },
"node_modules/@docusaurus/plugin-ideal-image": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-2.4.1.tgz",
"integrity": "sha512-jxvgCGPmHxdae2Y2uskzxIbMCA4WLTfzkufsLbD4mEAjCRIkt6yzux6q5kqKTrO+AxzpANVcJNGmaBtKZGv5aw==",
"dependencies": {
"@docusaurus/core": "2.4.1",
"@docusaurus/lqip-loader": "2.4.1",
"@docusaurus/responsive-loader": "^1.7.0",
"@docusaurus/theme-translations": "2.4.1",
"@docusaurus/types": "2.4.1",
"@docusaurus/utils-validation": "2.4.1",
"@endiliey/react-ideal-image": "^0.0.11",
"react-waypoint": "^10.3.0",
"sharp": "^0.30.7",
"tslib": "^2.4.0",
"webpack": "^5.73.0"
},
"engines": {
"node": ">=16.14"
},
"peerDependencies": {
"jimp": "*",
"react": "^16.8.4 || ^17.0.0",
"react-dom": "^16.8.4 || ^17.0.0"
},
"peerDependenciesMeta": {
"jimp": {
"optional": true
}
}
},
"node_modules/@docusaurus/plugin-sitemap": { "node_modules/@docusaurus/plugin-sitemap": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.1.tgz",
@ -2536,6 +2584,29 @@
"react": "*" "react": "*"
} }
}, },
"node_modules/@docusaurus/responsive-loader": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.7.0.tgz",
"integrity": "sha512-N0cWuVqTRXRvkBxeMQcy/OF2l7GN8rmni5EzR3HpwR+iU2ckYPnziceojcxvvxQ5NqZg1QfEW0tycQgHp+e+Nw==",
"dependencies": {
"loader-utils": "^2.0.0"
},
"engines": {
"node": ">=12"
},
"peerDependencies": {
"jimp": "*",
"sharp": "*"
},
"peerDependenciesMeta": {
"jimp": {
"optional": true
},
"sharp": {
"optional": true
}
}
},
"node_modules/@docusaurus/theme-classic": { "node_modules/@docusaurus/theme-classic": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.1.tgz",
@ -2734,6 +2805,20 @@
"node": ">=16.14" "node": ">=16.14"
} }
}, },
"node_modules/@endiliey/react-ideal-image": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/@endiliey/react-ideal-image/-/react-ideal-image-0.0.11.tgz",
"integrity": "sha512-QxMjt/Gvur/gLxSoCy7VIyGGGrGmDN+VHcXkN3R2ApoWX0EYUE+hMgPHSW/PV6VVebZ1Nd4t2UnGRBDihu16JQ==",
"engines": {
"node": ">= 8.9.0",
"npm": "> 3"
},
"peerDependencies": {
"prop-types": ">=15",
"react": ">=0.14.x",
"react-waypoint": ">=9.0.2"
}
},
"node_modules/@hapi/hoek": { "node_modules/@hapi/hoek": {
"version": "9.3.0", "version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
@ -4180,6 +4265,25 @@
"resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
"integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==" "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
}, },
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/batch": { "node_modules/batch": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@ -4201,6 +4305,16 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/body-parser": { "node_modules/body-parser": {
"version": "1.20.1", "version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@ -4333,6 +4447,29 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
} }
}, },
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@ -4584,6 +4721,11 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/chownr": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
},
"node_modules/chrome-trace-event": { "node_modules/chrome-trace-event": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
@ -4709,6 +4851,18 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/color-convert": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -4725,6 +4879,15 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}, },
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/colord": { "node_modules/colord": {
"version": "2.9.3", "version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
@ -4853,6 +5016,11 @@
"resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz",
"integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw=="
}, },
"node_modules/consolidated-events": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz",
"integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ=="
},
"node_modules/content-disposition": { "node_modules/content-disposition": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
@ -5508,6 +5676,14 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/detect-libc": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
"integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
"engines": {
"node": ">=8"
}
},
"node_modules/detect-node": { "node_modules/detect-node": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
@ -5936,6 +6112,14 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
"engines": {
"node": ">=6"
}
},
"node_modules/express": { "node_modules/express": {
"version": "4.18.2", "version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
@ -6389,6 +6573,11 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"node_modules/fs-extra": { "node_modules/fs-extra": {
"version": "10.1.0", "version": "10.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
@ -6468,6 +6657,11 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
},
"node_modules/github-slugger": { "node_modules/github-slugger": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz",
@ -7115,6 +7309,25 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.4", "version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@ -8133,6 +8346,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
},
"node_modules/mrmime": { "node_modules/mrmime": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
@ -8175,6 +8393,11 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
} }
}, },
"node_modules/napi-build-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
},
"node_modules/negotiator": { "node_modules/negotiator": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@ -8197,6 +8420,22 @@
"tslib": "^2.0.3" "tslib": "^2.0.3"
} }
}, },
"node_modules/node-abi": {
"version": "3.47.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.47.0.tgz",
"integrity": "sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==",
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
"node": ">=10"
}
},
"node_modules/node-addon-api": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz",
"integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="
},
"node_modules/node-emoji": { "node_modules/node-emoji": {
"version": "1.11.0", "version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@ -9303,6 +9542,31 @@
"postcss": "^8.2.15" "postcss": "^8.2.15"
} }
}, },
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
"integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
"dependencies": {
"detect-libc": "^2.0.0",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1",
"node-abi": "^3.3.0",
"pump": "^3.0.0",
"rc": "^1.2.7",
"simple-get": "^4.0.0",
"tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0"
},
"bin": {
"prebuild-install": "bin.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/prepend-http": { "node_modules/prepend-http": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
@ -9820,6 +10084,25 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0" "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
} }
}, },
"node_modules/react-waypoint": {
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/react-waypoint/-/react-waypoint-10.3.0.tgz",
"integrity": "sha512-iF1y2c1BsoXuEGz08NoahaLFIGI9gTUAAOKip96HUmylRT6DUtpgoBPjk/Y8dfcFVmfVDvUzWjNXpZyKTOV0SQ==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"consolidated-events": "^1.1.0 || ^2.0.0",
"prop-types": "^15.0.0",
"react-is": "^17.0.1 || ^18.0.0"
},
"peerDependencies": {
"react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-waypoint/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/readable-stream": { "node_modules/readable-stream": {
"version": "3.6.2", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -10745,6 +11028,28 @@
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
}, },
"node_modules/sharp": {
"version": "0.30.7",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.30.7.tgz",
"integrity": "sha512-G+MY2YW33jgflKPTXXptVO28HvNOo9G3j0MybYAHeEmby+QuD2U98dT6ueht9cv/XDqZspSpIhoSW+BAKJ7Hig==",
"hasInstallScript": true,
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.1",
"node-addon-api": "^5.0.0",
"prebuild-install": "^7.1.1",
"semver": "^7.3.7",
"simple-get": "^4.0.1",
"tar-fs": "^2.1.1",
"tunnel-agent": "^0.6.0"
},
"engines": {
"node": ">=12.13.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -10806,6 +11111,87 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
}, },
"node_modules/simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/simple-get": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"decompress-response": "^6.0.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/simple-get/node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"dependencies": {
"mimic-response": "^3.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/simple-get/node_modules/mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/simple-swizzle/node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"node_modules/sirv": { "node_modules/sirv": {
"version": "1.0.19", "version": "1.0.19",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz",
@ -10865,6 +11251,14 @@
"websocket-driver": "^0.7.4" "websocket-driver": "^0.7.4"
} }
}, },
"node_modules/sockjs/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/sort-css-media-queries": { "node_modules/sort-css-media-queries": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz", "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz",
@ -11217,6 +11611,32 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/tar-fs": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
"dependencies": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
"pump": "^3.0.0",
"tar-stream": "^2.1.4"
}
},
"node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"dependencies": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/terser": { "node_modules/terser": {
"version": "5.19.2", "version": "5.19.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz",
@ -11413,6 +11833,17 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
}, },
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/type-fest": { "node_modules/type-fest": {
"version": "2.19.0", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
@ -11991,9 +12422,9 @@
} }
}, },
"node_modules/uuid": { "node_modules/uuid": {
"version": "8.3.2", "version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
"bin": { "bin": {
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }

View file

@ -15,12 +15,16 @@
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "2.4.1", "@docusaurus/core": "2.4.1",
"@docusaurus/plugin-ideal-image": "^2.4.1",
"@docusaurus/preset-classic": "2.4.1", "@docusaurus/preset-classic": "2.4.1",
"@mdx-js/react": "^1.6.22", "@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1", "clsx": "^1.2.1",
"docusaurus-lunr-search": "^2.4.1",
"prism-react-renderer": "^1.3.5", "prism-react-renderer": "^1.3.5",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2" "react-dom": "^17.0.2",
"sharp": "^0.32.5",
"uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "2.4.1" "@docusaurus/module-type-aliases": "2.4.1"

View file

@ -28,16 +28,13 @@ const sidebars = {
label: "Embedding()", label: "Embedding()",
items: ["embedding/supported_embedding"], items: ["embedding/supported_embedding"],
}, },
"debugging/local_debugging", 'completion/supported',
"completion/supported", 'debugging/local_debugging',
'debugging/hosted_debugging',
{ {
type: "category", type: 'category',
label: "Tutorials", label: 'Tutorials',
items: [ items: ['tutorials/huggingface_tutorial', 'tutorials/TogetherAI_liteLLM', 'tutorials/fallbacks', 'tutorials/finetuned_chat_gpt'],
"tutorials/huggingface_tutorial",
"tutorials/TogetherAI_liteLLM",
"tutorials/debugging_tutorial",
],
}, },
"token_usage", "token_usage",
"stream", "stream",

8161
docs/my-website/yarn.lock Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,11 @@
import threading import threading
from typing import Callable, List, Optional from typing import Callable, List, Optional
input_callback: List[str] = [] input_callback: List[str] = []
success_callback: List[str] = [] success_callback: List[str] = []
failure_callback: List[str] = [] failure_callback: List[str] = []
set_verbose = False set_verbose = False
email: Optional[str] = None # for hosted dashboard. Learn more - https://docs.litellm.ai/docs/debugging/hosted_debugging
telemetry = True telemetry = True
max_tokens = 256 # OpenAI Defaults max_tokens = 256 # OpenAI Defaults
retry = True retry = True
@ -17,10 +19,10 @@ openrouter_key: Optional[str] = None
huggingface_key: Optional[str] = None huggingface_key: Optional[str] = None
vertex_project: Optional[str] = None vertex_project: Optional[str] = None
vertex_location: Optional[str] = None vertex_location: Optional[str] = None
hugging_api_token: Optional[str] = None
togetherai_api_key: Optional[str] = None togetherai_api_key: Optional[str] = None
caching = False caching = False
caching_with_models = False # if you want the caching key to be model + prompt caching_with_models = False # if you want the caching key to be model + prompt
debugger = False
model_cost = { model_cost = {
"gpt-3.5-turbo": { "gpt-3.5-turbo": {
"max_tokens": 4000, "max_tokens": 4000,
@ -148,7 +150,15 @@ cohere_models = [
anthropic_models = ["claude-2", "claude-instant-1", "claude-instant-1.2"] anthropic_models = ["claude-2", "claude-instant-1", "claude-instant-1.2"]
replicate_models = [ replicate_models = [
"replicate/" "replicate/",
"replicate/llama-2-70b-chat:58d078176e02c219e11eb4da5a02a7830a283b14cf8f94537af893ccff5ee781",
"a16z-infra/llama-2-13b-chat:2a7f981751ec7fdf87b5b91ad4db53683a98082e9ff7bfd12c8cd5ea85980a52",
"joehoover/instructblip-vicuna13b:c4c54e3c8c97cd50c2d2fec9be3b6065563ccf7d43787fb99f84151b867178fe"
"replicate/dolly-v2-12b:ef0e1aefc61f8e096ebe4db6b2bacc297daf2ef6899f0f7e001ec445893500e5",
"a16z-infra/llama-2-7b-chat:7b0bfc9aff140d5b75bacbed23e91fd3c34b01a1e958d32132de6e0a19796e2c",
"replicate/vicuna-13b:6282abe6a492de4145d7bb601023762212f9ddbbe78278bd6771c8b3b2f2a13b",
"daanelson/flan-t5-large:ce962b3f6792a57074a601d3979db5839697add2e4e02696b3ced4c022d4767f",
"replit/replit-code-v1-3b:b84f4c074b807211cd75e3e8b1589b6399052125b4c27106e43d47189e8415ad",
] # placeholder, to make sure we accept any replicate model in our model_list ] # placeholder, to make sure we accept any replicate model in our model_list
openrouter_models = [ openrouter_models = [
@ -185,6 +195,14 @@ huggingface_models = [
ai21_models = ["j2-ultra", "j2-mid", "j2-light"] ai21_models = ["j2-ultra", "j2-mid", "j2-light"]
together_ai_models = [
"togethercomputer/llama-2-70b-chat",
"togethercomputer/Llama-2-7B-32K-Instruct",
"togethercomputer/llama-2-7b",
]
baseten_models = ["qvv0xeq", "q841o8w", "31dxrj3"] # FALCON 7B # WizardLM # Mosaic ML
model_list = ( model_list = (
open_ai_chat_completion_models open_ai_chat_completion_models
+ open_ai_text_completion_models + open_ai_text_completion_models
@ -196,10 +214,13 @@ model_list = (
+ vertex_chat_models + vertex_chat_models
+ vertex_text_models + vertex_text_models
+ ai21_models + ai21_models
+ together_ai_models
+ baseten_models
) )
provider_list = [ provider_list = [
"openai", "openai",
"azure",
"cohere", "cohere",
"anthropic", "anthropic",
"replicate", "replicate",
@ -208,7 +229,22 @@ provider_list = [
"openrouter", "openrouter",
"vertex_ai", "vertex_ai",
"ai21", "ai21",
"baseten",
] ]
models_by_provider = {
"openai": open_ai_chat_completion_models + open_ai_text_completion_models,
"cohere": cohere_models,
"anthropic": anthropic_models,
"replicate": replicate_models,
"huggingface": huggingface_models,
"together_ai": together_ai_models,
"baseten": baseten_models,
"openrouter": openrouter_models,
"vertex_ai": vertex_chat_models + vertex_text_models,
"ai21": ai21_models,
}
####### EMBEDDING MODELS ################### ####### EMBEDDING MODELS ###################
open_ai_embedding_models = ["text-embedding-ada-002"] open_ai_embedding_models = ["text-embedding-ada-002"]
@ -223,7 +259,9 @@ from .utils import (
cost_per_token, cost_per_token,
completion_cost, completion_cost,
get_litellm_params, get_litellm_params,
Logging Logging,
acreate,
get_model_list,
) )
from .main import * # type: ignore from .main import * # type: ignore
from .integrations import * from .integrations import *

5
litellm/_version.py Normal file
View file

@ -0,0 +1,5 @@
import importlib_metadata
try:
version = importlib_metadata.version("litellm")
except:
pass

View file

@ -1,10 +1,32 @@
import requests, traceback, json import requests, traceback, json, os
class LiteDebugger: class LiteDebugger:
def __init__(self): user_email = None
dashboard_url = None
def __init__(self, email=None):
self.api_url = "https://api.litellm.ai/debugger" self.api_url = "https://api.litellm.ai/debugger"
self.validate_environment(email)
pass pass
def input_log_event(self, model, messages, end_user, litellm_call_id, print_verbose): def validate_environment(self, email):
try:
self.user_email = os.getenv("LITELLM_EMAIL") or email
self.dashboard_url = "https://admin.litellm.ai/" + self.user_email
print(f"Here's your free Dashboard 👉 {self.dashboard_url}")
if self.user_email == None:
raise Exception(
"[Non-Blocking Error] LiteLLMDebugger: Missing LITELLM_EMAIL. Set it in your environment. Eg.: os.environ['LITELLM_EMAIL']= <your_email>"
)
except Exception as e:
raise ValueError(
"[Non-Blocking Error] LiteLLMDebugger: Missing LITELLM_EMAIL. Set it in your environment. Eg.: os.environ['LITELLM_EMAIL']= <your_email>"
)
def input_log_event(
self, model, messages, end_user, litellm_call_id, print_verbose
):
try: try:
print_verbose( print_verbose(
f"LiteLLMDebugger: Logging - Enters input logging function for model {model}" f"LiteLLMDebugger: Logging - Enters input logging function for model {model}"
@ -14,27 +36,37 @@ class LiteDebugger:
"messages": messages, "messages": messages,
"end_user": end_user, "end_user": end_user,
"status": "initiated", "status": "initiated",
"litellm_call_id": litellm_call_id "litellm_call_id": litellm_call_id,
"user_email": self.user_email,
} }
response = requests.post(url=self.api_url, headers={"content-type": "application/json"}, data=json.dumps(litellm_data_obj)) response = requests.post(
url=self.api_url,
headers={"content-type": "application/json"},
data=json.dumps(litellm_data_obj),
)
print_verbose(f"LiteDebugger: api response - {response.text}") print_verbose(f"LiteDebugger: api response - {response.text}")
except: except:
print_verbose(f"LiteDebugger: Logging Error - {traceback.format_exc()}") print_verbose(
f"[Non-Blocking Error] LiteDebugger: Logging Error - {traceback.format_exc()}"
)
pass pass
def log_event(self, model, def log_event(
self,
model,
messages, messages,
end_user, end_user,
response_obj, response_obj,
start_time, start_time,
end_time, end_time,
litellm_call_id, litellm_call_id,
print_verbose,): print_verbose,
):
try: try:
print_verbose( print_verbose(
f"LiteLLMDebugger: Logging - Enters input logging function for model {model}" f"LiteLLMDebugger: Logging - Enters input logging function for model {model}"
) )
total_cost = 0 # [TODO] implement cost tracking total_cost = 0 # [TODO] implement cost tracking
response_time = (end_time - start_time).total_seconds() response_time = (end_time - start_time).total_seconds()
if "choices" in response_obj: if "choices" in response_obj:
litellm_data_obj = { litellm_data_obj = {
@ -45,12 +77,17 @@ class LiteDebugger:
"response": response_obj["choices"][0]["message"]["content"], "response": response_obj["choices"][0]["message"]["content"],
"end_user": end_user, "end_user": end_user,
"litellm_call_id": litellm_call_id, "litellm_call_id": litellm_call_id,
"status": "success" "status": "success",
"user_email": self.user_email,
} }
print_verbose( print_verbose(
f"LiteDebugger: Logging - final data object: {litellm_data_obj}" f"LiteDebugger: Logging - final data object: {litellm_data_obj}"
) )
response = requests.post(url=self.api_url, headers={"content-type": "application/json"}, data=json.dumps(litellm_data_obj)) response = requests.post(
url=self.api_url,
headers={"content-type": "application/json"},
data=json.dumps(litellm_data_obj),
)
elif "error" in response_obj: elif "error" in response_obj:
if "Unable to map your input to a model." in response_obj["error"]: if "Unable to map your input to a model." in response_obj["error"]:
total_cost = 0 total_cost = 0
@ -62,13 +99,20 @@ class LiteDebugger:
"error": response_obj["error"], "error": response_obj["error"],
"end_user": end_user, "end_user": end_user,
"litellm_call_id": litellm_call_id, "litellm_call_id": litellm_call_id,
"status": "failure" "status": "failure",
"user_email": self.user_email,
} }
print_verbose( print_verbose(
f"LiteDebugger: Logging - final data object: {litellm_data_obj}" f"LiteDebugger: Logging - final data object: {litellm_data_obj}"
) )
response = requests.post(url=self.api_url, headers={"content-type": "application/json"}, data=json.dumps(litellm_data_obj)) response = requests.post(
url=self.api_url,
headers={"content-type": "application/json"},
data=json.dumps(litellm_data_obj),
)
print_verbose(f"LiteDebugger: api response - {response.text}") print_verbose(f"LiteDebugger: api response - {response.text}")
except: except:
print_verbose(f"LiteDebugger: Logging Error - {traceback.format_exc()}") print_verbose(
f"[Non-Blocking Error] LiteDebugger: Logging Error - {traceback.format_exc()}"
)
pass pass

View file

@ -144,7 +144,9 @@ class Supabase:
) )
return prompt_tokens_cost_usd_dollar, completion_tokens_cost_usd_dollar return prompt_tokens_cost_usd_dollar, completion_tokens_cost_usd_dollar
def input_log_event(self, model, messages, end_user, litellm_call_id, print_verbose): def input_log_event(
self, model, messages, end_user, litellm_call_id, print_verbose
):
try: try:
print_verbose( print_verbose(
f"Supabase Logging - Enters input logging function for model {model}" f"Supabase Logging - Enters input logging function for model {model}"
@ -154,13 +156,13 @@ class Supabase:
"messages": messages, "messages": messages,
"end_user": end_user, "end_user": end_user,
"status": "initiated", "status": "initiated",
"litellm_call_id": litellm_call_id "litellm_call_id": litellm_call_id,
} }
data, count = ( data, count = (
self.supabase_client.table(self.supabase_table_name) self.supabase_client.table(self.supabase_table_name)
.insert(supabase_data_obj) .insert(supabase_data_obj)
.execute() .execute()
) )
print(f"data: {data}") print(f"data: {data}")
except: except:
print_verbose(f"Supabase Logging Error - {traceback.format_exc()}") print_verbose(f"Supabase Logging Error - {traceback.format_exc()}")
@ -200,7 +202,7 @@ class Supabase:
"response": response_obj["choices"][0]["message"]["content"], "response": response_obj["choices"][0]["message"]["content"],
"end_user": end_user, "end_user": end_user,
"litellm_call_id": litellm_call_id, "litellm_call_id": litellm_call_id,
"status": "success" "status": "success",
} }
print_verbose( print_verbose(
f"Supabase Logging - final data object: {supabase_data_obj}" f"Supabase Logging - final data object: {supabase_data_obj}"
@ -221,7 +223,7 @@ class Supabase:
"error": response_obj["error"], "error": response_obj["error"],
"end_user": end_user, "end_user": end_user,
"litellm_call_id": litellm_call_id, "litellm_call_id": litellm_call_id,
"status": "failure" "status": "failure",
} }
print_verbose( print_verbose(
f"Supabase Logging - final data object: {supabase_data_obj}" f"Supabase Logging - final data object: {supabase_data_obj}"

View file

@ -21,7 +21,9 @@ class AnthropicError(Exception):
class AnthropicLLM: class AnthropicLLM:
def __init__(self, encoding, default_max_tokens_to_sample, logging_obj, api_key=None): def __init__(
self, encoding, default_max_tokens_to_sample, logging_obj, api_key=None
):
self.encoding = encoding self.encoding = encoding
self.default_max_tokens_to_sample = default_max_tokens_to_sample self.default_max_tokens_to_sample = default_max_tokens_to_sample
self.completion_url = "https://api.anthropic.com/v1/complete" self.completion_url = "https://api.anthropic.com/v1/complete"
@ -84,7 +86,11 @@ class AnthropicLLM:
} }
## LOGGING ## LOGGING
self.logging_obj.pre_call(input=prompt, api_key=self.api_key, additional_args={"complete_input_dict": data}) self.logging_obj.pre_call(
input=prompt,
api_key=self.api_key,
additional_args={"complete_input_dict": data},
)
## COMPLETION CALL ## COMPLETION CALL
response = requests.post( response = requests.post(
self.completion_url, headers=self.headers, data=json.dumps(data) self.completion_url, headers=self.headers, data=json.dumps(data)
@ -93,7 +99,12 @@ class AnthropicLLM:
return response.iter_lines() return response.iter_lines()
else: else:
## LOGGING ## LOGGING
self.logging_obj.post_call(input=prompt, api_key=self.api_key, original_response=response.text, additional_args={"complete_input_dict": data}) self.logging_obj.post_call(
input=prompt,
api_key=self.api_key,
original_response=response.text,
additional_args={"complete_input_dict": data},
)
print_verbose(f"raw model_response: {response.text}") print_verbose(f"raw model_response: {response.text}")
## RESPONSE OBJECT ## RESPONSE OBJECT
completion_response = response.json() completion_response = response.json()

View file

@ -72,12 +72,13 @@ class HuggingfaceRestAPILLM:
if "max_tokens" in optional_params: if "max_tokens" in optional_params:
value = optional_params.pop("max_tokens") value = optional_params.pop("max_tokens")
optional_params["max_new_tokens"] = value optional_params["max_new_tokens"] = value
data = { data = {"inputs": prompt, "parameters": optional_params}
"inputs": prompt,
"parameters": optional_params
}
## LOGGING ## LOGGING
self.logging_obj.pre_call(input=prompt, api_key=self.api_key, additional_args={"complete_input_dict": data}) self.logging_obj.pre_call(
input=prompt,
api_key=self.api_key,
additional_args={"complete_input_dict": data},
)
## COMPLETION CALL ## COMPLETION CALL
response = requests.post( response = requests.post(
completion_url, headers=self.headers, data=json.dumps(data) completion_url, headers=self.headers, data=json.dumps(data)
@ -86,7 +87,12 @@ class HuggingfaceRestAPILLM:
return response.iter_lines() return response.iter_lines()
else: else:
## LOGGING ## LOGGING
self.logging_obj.post_call(input=prompt, api_key=self.api_key, original_response=response.text, additional_args={"complete_input_dict": data}) self.logging_obj.post_call(
input=prompt,
api_key=self.api_key,
original_response=response.text,
additional_args={"complete_input_dict": data},
)
## RESPONSE OBJECT ## RESPONSE OBJECT
completion_response = response.json() completion_response = response.json()
print_verbose(f"response: {completion_response}") print_verbose(f"response: {completion_response}")

View file

@ -10,13 +10,14 @@ from litellm import ( # type: ignore
timeout, timeout,
get_optional_params, get_optional_params,
get_litellm_params, get_litellm_params,
Logging Logging,
) )
from litellm.utils import ( from litellm.utils import (
get_secret, get_secret,
install_and_import, install_and_import,
CustomStreamWrapper, CustomStreamWrapper,
read_config_args, read_config_args,
completion_with_fallbacks,
) )
from .llms.anthropic import AnthropicLLM from .llms.anthropic import AnthropicLLM
from .llms.huggingface_restapi import HuggingfaceRestAPILLM from .llms.huggingface_restapi import HuggingfaceRestAPILLM
@ -90,17 +91,24 @@ def completion(
# used by text-bison only # used by text-bison only
top_k=40, top_k=40,
request_timeout=0, # unused var for old version of OpenAI API request_timeout=0, # unused var for old version of OpenAI API
fallbacks=[],
) -> ModelResponse: ) -> ModelResponse:
args = locals()
try: try:
if fallbacks != []:
return completion_with_fallbacks(**args)
model_response = ModelResponse() model_response = ModelResponse()
if azure: # this flag is deprecated, remove once notebooks are also updated. if azure: # this flag is deprecated, remove once notebooks are also updated.
custom_llm_provider = "azure" custom_llm_provider = "azure"
elif model.split("/", 1)[0] in litellm.provider_list: # allow custom provider to be passed in via the model name "azure/chatgpt-test" elif (
model.split("/", 1)[0] in litellm.provider_list
): # allow custom provider to be passed in via the model name "azure/chatgpt-test"
custom_llm_provider = model.split("/", 1)[0] custom_llm_provider = model.split("/", 1)[0]
model = model.split("/", 1)[1] model = model.split("/", 1)[1]
if "replicate" == custom_llm_provider and "/" not in model: # handle the "replicate/llama2..." edge-case if (
"replicate" == custom_llm_provider and "/" not in model
): # handle the "replicate/llama2..." edge-case
model = custom_llm_provider + "/" + model model = custom_llm_provider + "/" + model
args = locals()
# check if user passed in any of the OpenAI optional params # check if user passed in any of the OpenAI optional params
optional_params = get_optional_params( optional_params = get_optional_params(
functions=functions, functions=functions,
@ -130,9 +138,14 @@ def completion(
verbose=verbose, verbose=verbose,
custom_llm_provider=custom_llm_provider, custom_llm_provider=custom_llm_provider,
custom_api_base=custom_api_base, custom_api_base=custom_api_base,
litellm_call_id=litellm_call_id litellm_call_id=litellm_call_id,
)
logging = Logging(
model=model,
messages=messages,
optional_params=optional_params,
litellm_params=litellm_params,
) )
logging = Logging(model=model, messages=messages, optional_params=optional_params, litellm_params=litellm_params)
if custom_llm_provider == "azure": if custom_llm_provider == "azure":
# azure configs # azure configs
openai.api_type = "azure" openai.api_type = "azure"
@ -153,7 +166,15 @@ def completion(
# set key # set key
openai.api_key = api_key openai.api_key = api_key
## LOGGING ## LOGGING
logging.pre_call(input=messages, api_key=openai.api_key, additional_args={"headers": litellm.headers, "api_version": openai.api_version, "api_base": openai.api_base}) logging.pre_call(
input=messages,
api_key=openai.api_key,
additional_args={
"headers": litellm.headers,
"api_version": openai.api_version,
"api_base": openai.api_base,
},
)
## COMPLETION CALL ## COMPLETION CALL
if litellm.headers: if litellm.headers:
response = openai.ChatCompletion.create( response = openai.ChatCompletion.create(
@ -164,13 +185,24 @@ def completion(
) )
else: else:
response = openai.ChatCompletion.create( response = openai.ChatCompletion.create(
model=model, messages=messages, **optional_params engine=model, messages=messages, **optional_params
) )
## LOGGING ## LOGGING
logging.post_call(input=messages, api_key=openai.api_key, original_response=response, additional_args={"headers": litellm.headers, "api_version": openai.api_version, "api_base": openai.api_base}) logging.post_call(
input=messages,
api_key=openai.api_key,
original_response=response,
additional_args={
"headers": litellm.headers,
"api_version": openai.api_version,
"api_base": openai.api_base,
},
)
elif ( elif (
model in litellm.open_ai_chat_completion_models model in litellm.open_ai_chat_completion_models
or custom_llm_provider == "custom_openai" or custom_llm_provider == "custom_openai"
or "ft:gpt-3.5-turbo" in model # finetuned gpt-3.5-turbo
): # allow user to make an openai call with a custom base ): # allow user to make an openai call with a custom base
openai.api_type = "openai" openai.api_type = "openai"
# note: if a user sets a custom base - we should ensure this works # note: if a user sets a custom base - we should ensure this works
@ -192,7 +224,11 @@ def completion(
openai.api_key = api_key openai.api_key = api_key
## LOGGING ## LOGGING
logging.pre_call(input=messages, api_key=api_key, additional_args={"headers": litellm.headers, "api_base": api_base}) logging.pre_call(
input=messages,
api_key=api_key,
additional_args={"headers": litellm.headers, "api_base": api_base},
)
## COMPLETION CALL ## COMPLETION CALL
if litellm.headers: if litellm.headers:
response = openai.ChatCompletion.create( response = openai.ChatCompletion.create(
@ -206,7 +242,12 @@ def completion(
model=model, messages=messages, **optional_params model=model, messages=messages, **optional_params
) )
## LOGGING ## LOGGING
logging.post_call(input=messages, api_key=api_key, original_response=response, additional_args={"headers": litellm.headers}) logging.post_call(
input=messages,
api_key=api_key,
original_response=response,
additional_args={"headers": litellm.headers},
)
elif model in litellm.open_ai_text_completion_models: elif model in litellm.open_ai_text_completion_models:
openai.api_type = "openai" openai.api_type = "openai"
openai.api_base = ( openai.api_base = (
@ -227,7 +268,16 @@ def completion(
openai.organization = litellm.organization openai.organization = litellm.organization
prompt = " ".join([message["content"] for message in messages]) prompt = " ".join([message["content"] for message in messages])
## LOGGING ## LOGGING
logging.pre_call(input=prompt, api_key=api_key, additional_args={"openai_organization": litellm.organization, "headers": litellm.headers, "api_base": openai.api_base, "api_type": openai.api_type}) logging.pre_call(
input=prompt,
api_key=api_key,
additional_args={
"openai_organization": litellm.organization,
"headers": litellm.headers,
"api_base": openai.api_base,
"api_type": openai.api_type,
},
)
## COMPLETION CALL ## COMPLETION CALL
if litellm.headers: if litellm.headers:
response = openai.Completion.create( response = openai.Completion.create(
@ -238,7 +288,17 @@ def completion(
else: else:
response = openai.Completion.create(model=model, prompt=prompt) response = openai.Completion.create(model=model, prompt=prompt)
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=api_key, original_response=response, additional_args={"openai_organization": litellm.organization, "headers": litellm.headers, "api_base": openai.api_base, "api_type": openai.api_type}) logging.post_call(
input=prompt,
api_key=api_key,
original_response=response,
additional_args={
"openai_organization": litellm.organization,
"headers": litellm.headers,
"api_base": openai.api_base,
"api_type": openai.api_type,
},
)
## RESPONSE OBJECT ## RESPONSE OBJECT
completion_response = response["choices"][0]["text"] completion_response = response["choices"][0]["text"]
model_response["choices"][0]["message"]["content"] = completion_response model_response["choices"][0]["message"]["content"] = completion_response
@ -269,7 +329,14 @@ def completion(
input["max_length"] = max_tokens # for t5 models input["max_length"] = max_tokens # for t5 models
input["max_new_tokens"] = max_tokens # for llama2 models input["max_new_tokens"] = max_tokens # for llama2 models
## LOGGING ## LOGGING
logging.pre_call(input=prompt, api_key=replicate_key, additional_args={"complete_input_dict": input, "max_tokens": max_tokens}) logging.pre_call(
input=prompt,
api_key=replicate_key,
additional_args={
"complete_input_dict": input,
"max_tokens": max_tokens,
},
)
## COMPLETION CALL ## COMPLETION CALL
output = replicate.run(model, input=input) output = replicate.run(model, input=input)
if "stream" in optional_params and optional_params["stream"] == True: if "stream" in optional_params and optional_params["stream"] == True:
@ -282,7 +349,15 @@ def completion(
response += item response += item
completion_response = response completion_response = response
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=replicate_key, original_response=completion_response, additional_args={"complete_input_dict": input, "max_tokens": max_tokens}) logging.post_call(
input=prompt,
api_key=replicate_key,
original_response=completion_response,
additional_args={
"complete_input_dict": input,
"max_tokens": max_tokens,
},
)
## USAGE ## USAGE
prompt_tokens = len(encoding.encode(prompt)) prompt_tokens = len(encoding.encode(prompt))
completion_tokens = len(encoding.encode(completion_response)) completion_tokens = len(encoding.encode(completion_response))
@ -304,7 +379,7 @@ def completion(
encoding=encoding, encoding=encoding,
default_max_tokens_to_sample=litellm.max_tokens, default_max_tokens_to_sample=litellm.max_tokens,
api_key=anthropic_key, api_key=anthropic_key,
logging_obj = logging # model call logging done inside the class as we make need to modify I/O to fit anthropic's requirements logging_obj=logging, # model call logging done inside the class as we make need to modify I/O to fit anthropic's requirements
) )
model_response = anthropic_client.completion( model_response = anthropic_client.completion(
model=model, model=model,
@ -368,7 +443,9 @@ def completion(
**optional_params, **optional_params,
) )
## LOGGING ## LOGGING
logging.post_call(input=messages, api_key=openai.api_key, original_response=response) logging.post_call(
input=messages, api_key=openai.api_key, original_response=response
)
elif model in litellm.cohere_models: elif model in litellm.cohere_models:
# import cohere/if it fails then pip install cohere # import cohere/if it fails then pip install cohere
install_and_import("cohere") install_and_import("cohere")
@ -391,7 +468,9 @@ def completion(
response = CustomStreamWrapper(response, model) response = CustomStreamWrapper(response, model)
return response return response
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=cohere_key, original_response=response) logging.post_call(
input=prompt, api_key=cohere_key, original_response=response
)
## USAGE ## USAGE
completion_response = response[0].text completion_response = response[0].text
prompt_tokens = len(encoding.encode(prompt)) prompt_tokens = len(encoding.encode(prompt))
@ -474,7 +553,9 @@ def completion(
headers=headers, headers=headers,
) )
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=TOGETHER_AI_TOKEN, original_response=res.text) logging.post_call(
input=prompt, api_key=TOGETHER_AI_TOKEN, original_response=res.text
)
# make this safe for reading, if output does not exist raise an error # make this safe for reading, if output does not exist raise an error
json_response = res.json() json_response = res.json()
if "output" not in json_response: if "output" not in json_response:
@ -515,7 +596,9 @@ def completion(
completion_response = chat.send_message(prompt, **optional_params) completion_response = chat.send_message(prompt, **optional_params)
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=None, original_response=completion_response) logging.post_call(
input=prompt, api_key=None, original_response=completion_response
)
## RESPONSE OBJECT ## RESPONSE OBJECT
model_response["choices"][0]["message"]["content"] = completion_response model_response["choices"][0]["message"]["content"] = completion_response
@ -540,7 +623,9 @@ def completion(
completion_response = vertex_model.predict(prompt, **optional_params) completion_response = vertex_model.predict(prompt, **optional_params)
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=None, original_response=completion_response) logging.post_call(
input=prompt, api_key=None, original_response=completion_response
)
## RESPONSE OBJECT ## RESPONSE OBJECT
model_response["choices"][0]["message"]["content"] = completion_response model_response["choices"][0]["message"]["content"] = completion_response
model_response["created"] = time.time() model_response["created"] = time.time()
@ -563,7 +648,11 @@ def completion(
completion_response = ai21_response["completions"][0]["data"]["text"] completion_response = ai21_response["completions"][0]["data"]["text"]
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=ai21.api_key, original_response=completion_response) logging.post_call(
input=prompt,
api_key=ai21.api_key,
original_response=completion_response,
)
## RESPONSE OBJECT ## RESPONSE OBJECT
model_response["choices"][0]["message"]["content"] = completion_response model_response["choices"][0]["message"]["content"] = completion_response
@ -577,7 +666,9 @@ def completion(
prompt = " ".join([message["content"] for message in messages]) prompt = " ".join([message["content"] for message in messages])
## LOGGING ## LOGGING
logging.pre_call(input=prompt, api_key=None, additional_args={"endpoint": endpoint}) logging.pre_call(
input=prompt, api_key=None, additional_args={"endpoint": endpoint}
)
generator = get_ollama_response_stream(endpoint, model, prompt) generator = get_ollama_response_stream(endpoint, model, prompt)
# assume all responses are streamed # assume all responses are streamed
@ -604,7 +695,11 @@ def completion(
completion_response = completion_response["generated_text"] completion_response = completion_response["generated_text"]
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=base_ten_key, original_response=completion_response) logging.post_call(
input=prompt,
api_key=base_ten_key,
original_response=completion_response,
)
## RESPONSE OBJECT ## RESPONSE OBJECT
model_response["choices"][0]["message"]["content"] = completion_response model_response["choices"][0]["message"]["content"] = completion_response
@ -621,13 +716,22 @@ def completion(
prompt = " ".join([message["content"] for message in messages]) prompt = " ".join([message["content"] for message in messages])
## LOGGING ## LOGGING
logging.pre_call(input=prompt, api_key=None, additional_args={"url": url, "max_new_tokens": 100}) logging.pre_call(
input=prompt,
api_key=None,
additional_args={"url": url, "max_new_tokens": 100},
)
response = requests.post( response = requests.post(
url, data={"inputs": prompt, "max_new_tokens": 100, "model": model} url, data={"inputs": prompt, "max_new_tokens": 100, "model": model}
) )
## LOGGING ## LOGGING
logging.post_call(input=prompt, api_key=None, original_response=response.text, additional_args={"url": url, "max_new_tokens": 100}) logging.post_call(
input=prompt,
api_key=None,
original_response=response.text,
additional_args={"url": url, "max_new_tokens": 100},
)
completion_response = response.json()["outputs"] completion_response = response.json()["outputs"]
@ -637,7 +741,6 @@ def completion(
model_response["model"] = model model_response["model"] = model
response = model_response response = model_response
else: else:
args = locals()
raise ValueError( raise ValueError(
f"Unable to map your input to a model. Check your input - {args}" f"Unable to map your input to a model. Check your input - {args}"
) )
@ -676,10 +779,22 @@ def batch_completion(*args, **kwargs):
@timeout( # type: ignore @timeout( # type: ignore
60 60
) ## set timeouts, in case calls hang (e.g. Azure) - default is 60s, override with `force_timeout` ) ## set timeouts, in case calls hang (e.g. Azure) - default is 60s, override with `force_timeout`
def embedding(model, input=[], azure=False, force_timeout=60, litellm_call_id=None, logger_fn=None): def embedding(
model, input=[], azure=False, force_timeout=60, litellm_call_id=None, logger_fn=None
):
try: try:
response = None response = None
logging = Logging(model=model, messages=input, optional_params={}, litellm_params={"azure": azure, "force_timeout": force_timeout, "logger_fn": logger_fn, "litellm_call_id": litellm_call_id}) logging = Logging(
model=model,
messages=input,
optional_params={},
litellm_params={
"azure": azure,
"force_timeout": force_timeout,
"logger_fn": logger_fn,
"litellm_call_id": litellm_call_id,
},
)
if azure == True: if azure == True:
# azure configs # azure configs
openai.api_type = "azure" openai.api_type = "azure"
@ -687,7 +802,15 @@ def embedding(model, input=[], azure=False, force_timeout=60, litellm_call_id=No
openai.api_version = get_secret("AZURE_API_VERSION") openai.api_version = get_secret("AZURE_API_VERSION")
openai.api_key = get_secret("AZURE_API_KEY") openai.api_key = get_secret("AZURE_API_KEY")
## LOGGING ## LOGGING
logging.pre_call(input=input, api_key=openai.api_key, additional_args={"api_type": openai.api_type, "api_base": openai.api_base, "api_version": openai.api_version}) logging.pre_call(
input=input,
api_key=openai.api_key,
additional_args={
"api_type": openai.api_type,
"api_base": openai.api_base,
"api_version": openai.api_version,
},
)
## EMBEDDING CALL ## EMBEDDING CALL
response = openai.Embedding.create(input=input, engine=model) response = openai.Embedding.create(input=input, engine=model)
print_verbose(f"response_value: {str(response)[:50]}") print_verbose(f"response_value: {str(response)[:50]}")
@ -697,7 +820,15 @@ def embedding(model, input=[], azure=False, force_timeout=60, litellm_call_id=No
openai.api_version = None openai.api_version = None
openai.api_key = get_secret("OPENAI_API_KEY") openai.api_key = get_secret("OPENAI_API_KEY")
## LOGGING ## LOGGING
logging.pre_call(input=input, api_key=openai.api_key, additional_args={"api_type": openai.api_type, "api_base": openai.api_base, "api_version": openai.api_version}) logging.pre_call(
input=input,
api_key=openai.api_key,
additional_args={
"api_type": openai.api_type,
"api_base": openai.api_base,
"api_version": openai.api_version,
},
)
## EMBEDDING CALL ## EMBEDDING CALL
response = openai.Embedding.create(input=input, model=model) response = openai.Embedding.create(input=input, model=model)
print_verbose(f"response_value: {str(response)[:50]}") print_verbose(f"response_value: {str(response)[:50]}")
@ -710,7 +841,11 @@ def embedding(model, input=[], azure=False, force_timeout=60, litellm_call_id=No
## LOGGING ## LOGGING
logging.post_call(input=input, api_key=openai.api_key, original_response=e) logging.post_call(input=input, api_key=openai.api_key, original_response=e)
## Map to OpenAI Exception ## Map to OpenAI Exception
raise exception_type(model=model, original_exception=e, custom_llm_provider="azure" if azure==True else None) raise exception_type(
model=model,
original_exception=e,
custom_llm_provider="azure" if azure == True else None,
)
####### HELPER FUNCTIONS ################ ####### HELPER FUNCTIONS ################

View file

@ -9,7 +9,7 @@ import asyncio
sys.path.insert( sys.path.insert(
0, os.path.abspath("../..") 0, os.path.abspath("../..")
) # Adds the parent directory to the system path ) # Adds the parent directory to the system path
from litellm import acompletion from litellm import acompletion, acreate
async def test_get_response(): async def test_get_response():
@ -24,3 +24,16 @@ async def test_get_response():
response = asyncio.run(test_get_response()) response = asyncio.run(test_get_response())
print(response) print(response)
# async def test_get_response():
# user_message = "Hello, how are you?"
# messages = [{"content": user_message, "role": "user"}]
# try:
# response = await acreate(model="gpt-3.5-turbo", messages=messages)
# except Exception as e:
# pytest.fail(f"error occurred: {e}")
# return response
# response = asyncio.run(test_get_response())
# print(response)

View file

@ -34,7 +34,6 @@ def test_caching():
pytest.fail(f"Error occurred: {e}") pytest.fail(f"Error occurred: {e}")
def test_caching_with_models(): def test_caching_with_models():
litellm.caching_with_models = True litellm.caching_with_models = True
response2 = completion(model="gpt-3.5-turbo", messages=messages) response2 = completion(model="gpt-3.5-turbo", messages=messages)
@ -47,6 +46,3 @@ def test_caching_with_models():
print(f"response2: {response2}") print(f"response2: {response2}")
print(f"response3: {response3}") print(f"response3: {response3}")
pytest.fail(f"Error occurred: {e}") pytest.fail(f"Error occurred: {e}")

View file

@ -12,6 +12,8 @@ import pytest
import litellm import litellm
from litellm import embedding, completion from litellm import embedding, completion
litellm.debugger = True
# from infisical import InfisicalClient # from infisical import InfisicalClient
# litellm.set_verbose = True # litellm.set_verbose = True
@ -28,14 +30,18 @@ def logger_fn(user_model_dict):
def test_completion_custom_provider_model_name(): def test_completion_custom_provider_model_name():
try: try:
response = completion( response = completion(
model="together_ai/togethercomputer/llama-2-70b-chat", messages=messages, logger_fn=logger_fn model="together_ai/togethercomputer/llama-2-70b-chat",
messages=messages,
logger_fn=logger_fn,
) )
# Add any assertions here to check the response # Add any assertions here to check the response
print(response) print(response)
except Exception as e: except Exception as e:
pytest.fail(f"Error occurred: {e}") pytest.fail(f"Error occurred: {e}")
test_completion_custom_provider_model_name()
# test_completion_custom_provider_model_name()
def test_completion_claude(): def test_completion_claude():
try: try:
@ -89,7 +95,10 @@ def test_completion_claude_stream():
def test_completion_cohere(): def test_completion_cohere():
try: try:
response = completion( response = completion(
model="command-nightly", messages=messages, max_tokens=100, logit_bias={40: 10} model="command-nightly",
messages=messages,
max_tokens=100,
logit_bias={40: 10},
) )
# Add any assertions here to check the response # Add any assertions here to check the response
print(response) print(response)
@ -103,6 +112,7 @@ def test_completion_cohere():
except Exception as e: except Exception as e:
pytest.fail(f"Error occurred: {e}") pytest.fail(f"Error occurred: {e}")
def test_completion_cohere_stream(): def test_completion_cohere_stream():
try: try:
messages = [ messages = [
@ -254,8 +264,7 @@ def test_completion_openai_with_functions():
def test_completion_azure(): def test_completion_azure():
try: try:
response = completion( response = completion(
model="gpt-3.5-turbo", model="chatgpt-test",
deployment_id="chatgpt-test",
messages=messages, messages=messages,
custom_llm_provider="azure", custom_llm_provider="azure",
) )
@ -340,6 +349,18 @@ def test_petals():
pytest.fail(f"Error occurred: {e}") pytest.fail(f"Error occurred: {e}")
def test_completion_with_fallbacks():
fallbacks = ["gpt-3.5-turb", "gpt-3.5-turbo", "command-nightly"]
try:
response = completion(
model="bad-model", messages=messages, force_timeout=120, fallbacks=fallbacks
)
# Add any assertions here to check the response
print(response)
except Exception as e:
pytest.fail(f"Error occurred: {e}")
# def test_baseten_falcon_7bcompletion(): # def test_baseten_falcon_7bcompletion():
# model_name = "qvv0xeq" # model_name = "qvv0xeq"
# try: # try:

View file

@ -0,0 +1,11 @@
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_list
print(get_model_list())
print(get_model_list())
# print(litellm.model_list)

View file

@ -9,18 +9,16 @@
# import litellm # import litellm
# from litellm import embedding, completion # from litellm import embedding, completion
# litellm.input_callback = ["lite_debugger"]
# litellm.success_callback = ["lite_debugger"]
# litellm.failure_callback = ["lite_debugger"]
# litellm.set_verbose = True # litellm.set_verbose = True
# litellm.email = "krrish@berri.ai"
# user_message = "Hello, how are you?" # user_message = "Hello, how are you?"
# messages = [{ "content": user_message,"role": "user"}] # messages = [{ "content": user_message,"role": "user"}]
# #openai call # #openai call
# response = completion(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}]) # response = completion(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}])
# print(f"response: {response}")
# #bad request call # #bad request call
# response = completion(model="chatgpt-test", messages=[{"role": "user", "content": "Hi 👋 - i'm a bad request"}]) # # response = completion(model="chatgpt-test", messages=[{"role": "user", "content": "Hi 👋 - i'm a bad request"}])

View file

@ -22,6 +22,32 @@ def logger_fn(model_call_object: dict):
user_message = "Hello, how are you?" user_message = "Hello, how are you?"
messages = [{"content": user_message, "role": "user"}] messages = [{"content": user_message, "role": "user"}]
# test on openai completion call
try:
response = completion(
model="gpt-3.5-turbo", messages=messages, stream=True, logger_fn=logger_fn
)
for chunk in response:
print(chunk["choices"][0]["delta"])
score += 1
except:
print(f"error occurred: {traceback.format_exc()}")
pass
# test on azure completion call
try:
response = completion(
model="azure/chatgpt-test", messages=messages, stream=True, logger_fn=logger_fn
)
for chunk in response:
print(chunk["choices"][0]["delta"])
score += 1
except:
print(f"error occurred: {traceback.format_exc()}")
pass
# test on anthropic completion call # test on anthropic completion call
try: try:
response = completion( response = completion(
@ -35,19 +61,19 @@ except:
pass pass
# test on anthropic completion call # # test on huggingface completion call
try: # try:
response = completion( # response = completion(
model="meta-llama/Llama-2-7b-chat-hf", # model="meta-llama/Llama-2-7b-chat-hf",
messages=messages, # messages=messages,
custom_llm_provider="huggingface", # custom_llm_provider="huggingface",
custom_api_base="https://s7c7gytn18vnu4tw.us-east-1.aws.endpoints.huggingface.cloud", # custom_api_base="https://s7c7gytn18vnu4tw.us-east-1.aws.endpoints.huggingface.cloud",
stream=True, # stream=True,
logger_fn=logger_fn, # logger_fn=logger_fn,
) # )
for chunk in response: # for chunk in response:
print(chunk["choices"][0]["delta"]) # print(chunk["choices"][0]["delta"])
score += 1 # score += 1
except: # except:
print(f"error occurred: {traceback.format_exc()}") # print(f"error occurred: {traceback.format_exc()}")
pass # pass

View file

@ -24,5 +24,6 @@
# #openai call # #openai call
# response = completion(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}]) # response = completion(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hi 👋 - i'm openai"}])
# fix
# #bad request call # #bad request call
# response = completion(model="chatgpt-test", messages=[{"role": "user", "content": "Hi 👋 - i'm a bad request"}]) # response = completion(model="chatgpt-test", messages=[{"role": "user", "content": "Hi 👋 - i'm a bad request"}])

View file

@ -1,7 +1,20 @@
import aiohttp import sys
import subprocess import dotenv, json, traceback, threading
import importlib import subprocess, os
from typing import List, Dict, Union, Optional import litellm, openai
import random, uuid, requests
import datetime, time
import tiktoken
encoding = tiktoken.get_encoding("cl100k_base")
import importlib.metadata
from .integrations.helicone import HeliconeLogger
from .integrations.aispend import AISpendLogger
from .integrations.berrispend import BerriSpendLogger
from .integrations.supabase import Supabase
from .integrations.litedebugger import LiteDebugger
from openai.error import OpenAIError as OriginalError
from openai.openai_object import OpenAIObject
from .exceptions import ( from .exceptions import (
AuthenticationError, AuthenticationError,
InvalidRequestError, InvalidRequestError,
@ -9,34 +22,10 @@ from .exceptions import (
ServiceUnavailableError, ServiceUnavailableError,
OpenAIError, OpenAIError,
) )
from openai.openai_object import OpenAIObject from typing import List, Dict, Union, Optional
from openai.error import OpenAIError as OriginalError
from .integrations.llmonitor import LLMonitorLogger
from .integrations.litedebugger import LiteDebugger
from .integrations.supabase import Supabase
from .integrations.berrispend import BerriSpendLogger
from .integrations.aispend import AISpendLogger
from .integrations.helicone import HeliconeLogger
import pkg_resources
import sys
import dotenv
import json
import traceback
import threading
import subprocess
import os
import litellm
import openai
import random
import uuid
import requests
import datetime
import time
import tiktoken
encoding = tiktoken.get_encoding("cl100k_base")
####### ENVIRONMENT VARIABLES ################### ####### ENVIRONMENT VARIABLES ####################
dotenv.load_dotenv() # Loading env variables using dotenv dotenv.load_dotenv() # Loading env variables using dotenv
sentry_sdk_instance = None sentry_sdk_instance = None
capture_exception = None capture_exception = None
@ -49,12 +38,11 @@ aispendLogger = None
berrispendLogger = None berrispendLogger = None
supabaseClient = None supabaseClient = None
liteDebuggerClient = None liteDebuggerClient = None
llmonitorLogger = None
callback_list: Optional[List[str]] = [] callback_list: Optional[List[str]] = []
user_logger_fn = None user_logger_fn = None
additional_details: Optional[Dict[str, str]] = {} additional_details: Optional[Dict[str, str]] = {}
local_cache: Optional[Dict[str, str]] = {} local_cache: Optional[Dict[str, str]] = {}
last_fetched_at = None
######## Model Response ######################### ######## Model Response #########################
# All liteLLM Model responses will be in this format, Follows the OpenAI Format # All liteLLM Model responses will be in this format, Follows the OpenAI Format
# https://docs.litellm.ai/docs/completion/output # https://docs.litellm.ai/docs/completion/output
@ -174,7 +162,7 @@ class Logging:
def pre_call(self, input, api_key, additional_args={}): def pre_call(self, input, api_key, additional_args={}):
try: try:
print(f"logging pre call for model: {self.model}") print_verbose(f"logging pre call for model: {self.model}")
self.model_call_details["input"] = input self.model_call_details["input"] = input
self.model_call_details["api_key"] = api_key self.model_call_details["api_key"] = api_key
self.model_call_details["additional_args"] = additional_args self.model_call_details["additional_args"] = additional_args
@ -214,7 +202,7 @@ class Logging:
print_verbose("reaches litedebugger for logging!") print_verbose("reaches litedebugger for logging!")
model = self.model model = self.model
messages = self.messages messages = self.messages
print(f"liteDebuggerClient: {liteDebuggerClient}") print_verbose(f"liteDebuggerClient: {liteDebuggerClient}")
liteDebuggerClient.input_log_event( liteDebuggerClient.input_log_event(
model=model, model=model,
messages=messages, messages=messages,
@ -271,7 +259,6 @@ class Logging:
# Add more methods as needed # Add more methods as needed
def exception_logging( def exception_logging(
additional_args={}, additional_args={},
logger_fn=None, logger_fn=None,
@ -305,20 +292,34 @@ def exception_logging(
####### 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 client(original_function): def client(original_function):
global liteDebuggerClient, get_all_keys
def function_setup( def function_setup(
*args, **kwargs *args, **kwargs
): # just run once to check if user wants to send their data anywhere - PostHog/Sentry/Slack/etc. ): # just run once to check if user wants to send their data anywhere - PostHog/Sentry/Slack/etc.
try: try:
global callback_list, add_breadcrumb, user_logger_fn global callback_list, add_breadcrumb, user_logger_fn
if (len(litellm.input_callback) > 0 if litellm.email is not None or os.getenv("LITELLM_EMAIL", None) is not None: # add to input, success and failure callbacks if user is using hosted product
or len(litellm.success_callback) > 0 get_all_keys()
or len(litellm.failure_callback) if "lite_debugger" not in callback_list:
> 0) and len(callback_list) == 0: litellm.input_callback.append("lite_debugger")
litellm.success_callback.append("lite_debugger")
litellm.failure_callback.append("lite_debugger")
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( callback_list = list(
set(litellm.input_callback + litellm.success_callback + set(
litellm.failure_callback)) litellm.input_callback
set_callbacks(callback_list=callback_list, ) + litellm.success_callback
+ litellm.failure_callback
)
)
set_callbacks(
callback_list=callback_list,
)
if add_breadcrumb: if add_breadcrumb:
add_breadcrumb( add_breadcrumb(
category="litellm.llm_call", category="litellm.llm_call",
@ -432,6 +433,11 @@ def client(original_function):
kwargs), kwargs),
) # don't interrupt execution of main thread ) # don't interrupt execution of main thread
my_thread.start() my_thread.start()
if hasattr(e, "message"):
if (
liteDebuggerClient and liteDebuggerClient.dashboard_url != None
): # make it easy to get to the debugger logs if you've initialized it
e.message += f"\n Check the log in your dashboard - {liteDebuggerClient.dashboard_url}"
raise e raise e
return wrapper return wrapper
@ -515,7 +521,7 @@ def get_litellm_params(
"verbose": verbose, "verbose": verbose,
"custom_llm_provider": custom_llm_provider, "custom_llm_provider": custom_llm_provider,
"custom_api_base": custom_api_base, "custom_api_base": custom_api_base,
"litellm_call_id": litellm_call_id "litellm_call_id": litellm_call_id,
} }
return litellm_params return litellm_params
@ -738,7 +744,7 @@ def set_callbacks(callback_list):
supabaseClient = Supabase() supabaseClient = Supabase()
elif callback == "lite_debugger": elif callback == "lite_debugger":
print(f"instantiating lite_debugger") print(f"instantiating lite_debugger")
liteDebuggerClient = LiteDebugger() liteDebuggerClient = LiteDebugger(email=litellm.email)
except Exception as e: except Exception as e:
raise e raise e
@ -1036,7 +1042,7 @@ def handle_success(args, kwargs, result, start_time, end_time):
print_verbose("reaches lite_debugger for logging!") print_verbose("reaches lite_debugger for logging!")
model = args[0] if len(args) > 0 else kwargs["model"] model = args[0] if len(args) > 0 else kwargs["model"]
messages = args[1] if len(args) > 1 else kwargs["messages"] messages = args[1] if len(args) > 1 else kwargs["messages"]
print(f"liteDebuggerClient: {liteDebuggerClient}") print_verbose(f"liteDebuggerClient: {liteDebuggerClient}")
liteDebuggerClient.log_event( liteDebuggerClient.log_event(
model=model, model=model,
messages=messages, messages=messages,
@ -1066,6 +1072,9 @@ def handle_success(args, kwargs, result, start_time, end_time):
) )
pass pass
def acreate(*args, **kwargs): ## Thin client to handle the acreate langchain call
return litellm.acompletion(*args, **kwargs)
def prompt_token_calculator(model, messages): def prompt_token_calculator(model, messages):
# use tiktoken or anthropic's tokenizer depending on the model # use tiktoken or anthropic's tokenizer depending on the model
@ -1082,6 +1091,21 @@ def prompt_token_calculator(model, messages):
return num_tokens return num_tokens
def valid_model(model):
try:
# for a given model name, check if the user has the right permissions to access the model
if (
model in litellm.open_ai_chat_completion_models
or model in litellm.open_ai_text_completion_models
):
openai.Model.retrieve(model)
else:
messages = [{"role": "user", "content": "Hello World"}]
litellm.completion(model=model, messages=messages)
except:
raise InvalidRequestError(message="", model=model, llm_provider="")
# integration helper function # integration helper function
def modify_integration(integration_name, integration_params): def modify_integration(integration_name, integration_params):
global supabaseClient global supabaseClient
@ -1089,9 +1113,65 @@ def modify_integration(integration_name, integration_params):
if "table_name" in integration_params: if "table_name" in integration_params:
Supabase.supabase_table_name = integration_params["table_name"] Supabase.supabase_table_name = integration_params["table_name"]
####### [BETA] HOSTED PRODUCT ################ - https://docs.litellm.ai/docs/debugging/hosted_debugging
def get_all_keys(llm_provider=None):
try:
global last_fetched_at
# if user is using hosted product -> instantiate their env with their hosted api keys - refresh every 5 minutes
user_email = os.getenv("LITELLM_EMAIL") or litellm.email
if user_email:
time_delta = 0
if last_fetched_at != None:
current_time = time.time()
time_delta = current_time - last_fetched_at
if time_delta > 300 or last_fetched_at == None or llm_provider: # if the llm provider is passed in , assume this happening due to an AuthError for that provider
# make the api call
last_fetched_at = time.time()
print(f"last_fetched_at: {last_fetched_at}")
response = requests.post(url="http://api.litellm.ai/get_all_keys", headers={"content-type": "application/json"}, data=json.dumps({"user_email": user_email}))
print_verbose(f"get model key response: {response.text}")
data = response.json()
# update model list
for key, value in data["model_keys"].items(): # follows the LITELLM API KEY format - <UPPERCASE_PROVIDER_NAME>_API_KEY - e.g. HUGGINGFACE_API_KEY
os.environ[key] = value
return "it worked!"
return None
# return None by default
return None
except:
print_verbose(f"[Non-Blocking Error] get_all_keys error - {traceback.format_exc()}")
pass
def get_model_list():
global last_fetched_at
try:
# if user is using hosted product -> get their updated model list - refresh every 5 minutes
user_email = os.getenv("LITELLM_EMAIL") or litellm.email
if user_email:
time_delta = 0
if last_fetched_at != None:
current_time = time.time()
time_delta = current_time - last_fetched_at
if time_delta > 300 or last_fetched_at == None:
# make the api call
last_fetched_at = time.time()
print(f"last_fetched_at: {last_fetched_at}")
response = requests.post(url="http://api.litellm.ai/get_model_list", headers={"content-type": "application/json"}, data=json.dumps({"user_email": user_email}))
print_verbose(f"get_model_list response: {response.text}")
data = response.json()
# update model list
model_list = data["model_list"]
return model_list
return None
return None # return None by default
except:
print_verbose(f"[Non-Blocking Error] get_all_keys error - {traceback.format_exc()}")
####### EXCEPTION MAPPING ################
def exception_type(model, original_exception, custom_llm_provider): def exception_type(model, original_exception, custom_llm_provider):
global user_logger_fn global user_logger_fn, liteDebuggerClient
exception_mapping_worked = False exception_mapping_worked = False
try: try:
if isinstance(original_exception, OriginalError): if isinstance(original_exception, OriginalError):
@ -1232,12 +1312,16 @@ def exception_type(model, original_exception, custom_llm_provider):
}, },
exception=e, exception=e,
) )
## AUTH ERROR
if isinstance(e, AuthenticationError) and (litellm.email or "LITELLM_EMAIL" in os.environ):
threading.Thread(target=get_all_keys, args=(e.llm_provider,)).start()
if exception_mapping_worked: if exception_mapping_worked:
raise e raise e
else: # don't let an error with mapping interrupt the user from receiving an error from the llm api calls else: # don't let an error with mapping interrupt the user from receiving an error from the llm api calls
raise original_exception raise original_exception
####### CRASH REPORTING ################
def safe_crash_reporting(model=None, exception=None, custom_llm_provider=None): def safe_crash_reporting(model=None, exception=None, custom_llm_provider=None):
data = { data = {
"model": model, "model": model,
@ -1273,7 +1357,7 @@ def litellm_telemetry(data):
payload = { payload = {
"uuid": uuid_value, "uuid": uuid_value,
"data": data, "data": data,
"version": pkg_resources.get_distribution("litellm").version, "version:": importlib.metadata.version("litellm"),
} }
# Make the POST request to litellm logging api # Make the POST request to litellm logging api
response = requests.post( response = requests.post(
@ -1443,7 +1527,7 @@ async def stream_to_string(generator):
return response return response
########## Together AI streaming ############################# ########## Together AI streaming ############################# [TODO] move together ai to it's own llm class
async def together_ai_completion_streaming(json_data, headers): async def together_ai_completion_streaming(json_data, headers):
session = aiohttp.ClientSession() session = aiohttp.ClientSession()
url = "https://api.together.xyz/inference" url = "https://api.together.xyz/inference"
@ -1480,3 +1564,49 @@ async def together_ai_completion_streaming(json_data, headers):
pass pass
finally: finally:
await session.close() await session.close()
def completion_with_fallbacks(**kwargs):
response = None
rate_limited_models = set()
model_expiration_times = {}
start_time = time.time()
fallbacks = [kwargs["model"]] + kwargs["fallbacks"]
del kwargs["fallbacks"] # remove fallbacks so it's not recursive
while response == None and time.time() - start_time < 45:
for model in fallbacks:
# loop thru all models
try:
if (
model in rate_limited_models
): # check if model is currently cooling down
if (
model_expiration_times.get(model)
and time.time() >= model_expiration_times[model]
):
rate_limited_models.remove(
model
) # check if it's been 60s of cool down and remove model
else:
continue # skip model
# delete model from kwargs if it exists
if kwargs.get("model"):
del kwargs["model"]
print("making completion call", model)
response = litellm.completion(**kwargs, model=model)
if response != None:
return response
except Exception as e:
print(f"got exception {e} for model {model}")
rate_limited_models.add(model)
model_expiration_times[model] = (
time.time() + 60
) # cool down this selected model
# print(f"rate_limited_models {rate_limited_models}")
pass
return response

6
poetry.lock generated
View file

@ -423,13 +423,13 @@ files = [
[[package]] [[package]]
name = "openai" name = "openai"
version = "0.27.8" version = "0.27.9"
description = "Python client library for the OpenAI API" description = "Python client library for the OpenAI API"
optional = false optional = false
python-versions = ">=3.7.1" python-versions = ">=3.7.1"
files = [ files = [
{file = "openai-0.27.8-py3-none-any.whl", hash = "sha256:e0a7c2f7da26bdbe5354b03c6d4b82a2f34bd4458c7a17ae1a7092c3e397e03c"}, {file = "openai-0.27.9-py3-none-any.whl", hash = "sha256:6a3cf8e276d1a6262b50562fbc0cba7967cfebb78ed827d375986b48fdad6475"},
{file = "openai-0.27.8.tar.gz", hash = "sha256:2483095c7db1eee274cebac79e315a986c4e55207bb4fa7b82d185b3a2ed9536"}, {file = "openai-0.27.9.tar.gz", hash = "sha256:b687761c82f5ebb6f61efc791b2083d2d068277b94802d4d1369efe39851813d"},
] ]
[package.dependencies] [package.dependencies]

View file

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "litellm" name = "litellm"
version = "0.1.437" version = "0.1.457"
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" license = "MIT License"
@ -11,6 +11,7 @@ python = "^3.8"
openai = "^0.27.8" openai = "^0.27.8"
python-dotenv = "^1.0.0" python-dotenv = "^1.0.0"
tiktoken = "^0.4.0" tiktoken = "^0.4.0"
importlib-metadata = "^6.8.0"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]