Skip to content

Commit 990d833

Browse files
authored
Merge pull request #2069 from Giskard-AI/feature/litellm
[GSK-3846] Add support to LiteLLM
2 parents d0cc7e4 + a571312 commit 990d833

File tree

25 files changed

+774
-463
lines changed

25 files changed

+774
-463
lines changed

docs/open_source/scan/scan_llm/index.md

+75-134
Original file line numberDiff line numberDiff line change
@@ -38,220 +38,161 @@ processed.
3838

3939
## Before starting
4040

41-
In the following example, we illustrate the procedure using **OpenAI** and **Azure OpenAI**; however, please note that
42-
our platform supports a variety of language models. For details on configuring different models, visit
43-
our [🤖 Setting up the LLM Client page](../../setting_up/index.md)
44-
45-
Before starting, make sure you have installed the LLM flavor of Giskard:
41+
First of all, make sure you have installed the LLM flavor of Giskard:
4642

4743
```bash
4844
pip install "giskard[llm]"
4945
```
5046

51-
For the LLM-assisted detectors to work, you need to have an OpenAI API key. You can set it in your notebook
52-
like this:
47+
For the LLM-assisted detectors to work, you need to set up a LLM client. Our platform supports a variety of language models, and you can find the details on configuring different models in our [🤖 Setting up the LLM Client page](../../setting_up/index.md) or follow the instructions below for each provider:
5348

5449
:::::::{tab-set}
5550
::::::{tab-item} OpenAI
5651

5752
```python
5853
import os
5954
import giskard
60-
from giskard.llm.client.openai import OpenAIClient
6155

62-
# Set the OpenAI API key
63-
os.environ["OPENAI_API_KEY"] = "sk-…"
56+
os.environ["OPENAI_API_KEY"] = "" # "my-openai-api-key"
6457

65-
# Create a giskard OpenAI client
66-
openai_client = OpenAIClient(model="gpt-4o")
58+
# Optional, setup a model (default LLM is gpt-4o, default embedding model is text-embedding-3-small)
59+
giskard.llm.set_llm_model("gpt-4o")
60+
giskard.llm.set_embedding_model("text-embedding-3-small")
6761

68-
# Set the default client
69-
giskard.llm.set_llm_api("openai")
70-
giskard.llm.set_default_client(openai_client)
62+
# Optional Keys - OpenAI Organization, OpenAI API Base
63+
os.environ["OPENAI_ORGANIZATION"] = "" # "my-openai-organization"
64+
os.environ["OPENAI_API_BASE"] = "" # "https://api.openai.com"
7165
```
7266

67+
More information on [OpenAI LiteLLM documentation](https://docs.litellm.ai/docs/providers/openai)
68+
7369
::::::
7470
::::::{tab-item} Azure OpenAI
7571

76-
Require `openai>=1.0.0`
77-
7872
```python
7973
import os
8074
import giskard
8175

82-
# Set the Azure OpenAI API key and endpoint
83-
os.environ['AZURE_OPENAI_API_KEY'] = '...'
84-
os.environ['AZURE_OPENAI_ENDPOINT'] = 'https://xxx.openai.azure.com'
85-
os.environ['OPENAI_API_VERSION'] = '2023-07-01-preview'
76+
os.environ["AZURE_API_KEY"] = "" # "my-azure-api-key"
77+
os.environ["AZURE_API_BASE"] = "" # "https://example-endpoint.openai.azure.com"
78+
os.environ["AZURE_API_VERSION"] = "" # "2023-05-15"
79+
80+
giskard.llm.set_llm_model("azure/<your_llm_name>")
81+
giskard.llm.set_embedding_model("azure/<your_embed_model_name>")
8682

87-
# You'll need to provide the name of the model that you've deployed
88-
# Beware, the model provided must be capable of using function calls
89-
giskard.llm.set_llm_model('my-gpt-4-model')
90-
giskard.llm.embeddings.openai.set_embedding_model('my-embedding-model')
83+
# Optional Keys - Azure AD Token, Azure API Type
84+
os.environ["AZURE_AD_TOKEN"] = ""
85+
os.environ["AZURE_API_TYPE"] = ""
9186
```
9287

88+
More information on [Azure LiteLLM documentation](https://docs.litellm.ai/docs/providers/azure)
89+
9390
::::::
9491
::::::{tab-item} Mistral
9592

9693
```python
9794
import os
9895
import giskard
99-
from giskard.llm.client.mistral import MistralClient
100-
101-
# Set the Mistral API key
102-
os.environ["MISTRAL_API_KEY"] = ""
103-
104-
# Create a giskard Mistral client
105-
mistral_client = MistralClient()
10696

107-
# Set the default client
108-
giskard.llm.set_default_client(mistral_client)
97+
os.environ["MISTRAL_API_KEY"] = "" # "my-mistral-api-key"
10998

110-
# You may also want to set the default embedding model
111-
# Check the Custom Client code snippet for more details
99+
giskard.llm.set_llm_model("mistral/mistral-large-latest")
100+
giskard.llm.set_embedding_model("mistral/mistral-embed")
112101
```
113102

103+
More information on [Mistral LiteLLM documentation](https://docs.litellm.ai/docs/providers/mistral)
104+
114105
::::::
115106
::::::{tab-item} Ollama
116107

117108
```python
118109
import giskard
119-
from openai import OpenAI
120-
from giskard.llm.client.openai import OpenAIClient
121-
from giskard.llm.embeddings.openai import OpenAIEmbedding
122-
123-
# Setup the OpenAI client with API key and base URL for Ollama
124-
_client = OpenAI(base_url="http://localhost:11434/v1/", api_key="ollama")
125110

126-
# Wrap the original OpenAI client with giskard OpenAI client and embedding
127-
llm_client = OpenAIClient(model="llama3.2", client=_client)
128-
embed_client = OpenAIEmbedding(model="nomic-embed-text", client=_client)
111+
api_base = "http://localhost:11434" # default api_base for local Ollama
129112

130-
# Set the default client and embedding
131-
giskard.llm.set_default_client(llm_client)
132-
giskard.llm.embeddings.set_default_embedding(embed_client)
113+
# See supported models here: https://docs.litellm.ai/docs/providers/ollama#ollama-models
114+
giskard.llm.set_llm_model("ollama/llama3.1", disable_structured_output=True, api_base=api_base)
115+
giskard.llm.set_embedding_model("ollama/nomic-embed-text", api_base=api_base)
133116
```
134117

118+
More information on [Ollama LiteLLM documentation](https://docs.litellm.ai/docs/providers/ollama)
119+
135120
::::::
136-
::::::{tab-item} Claude 3
121+
::::::{tab-item} AWS Bedrock
122+
123+
More information on [Bedrock LiteLLM documentation](https://docs.litellm.ai/docs/providers/bedrock)
137124

138125
```python
139126
import os
140-
import boto3
141127
import giskard
142128

143-
from giskard.llm.client.bedrock import ClaudeBedrockClient
144-
from giskard.llm.embeddings.bedrock import BedrockEmbedding
145-
146-
# Create a Bedrock client
147-
bedrock_runtime = boto3.client("bedrock-runtime", region_name=os.environ["AWS_DEFAULT_REGION"])
148-
149-
# Wrap the Beddock client with giskard Bedrock client and embedding
150-
claude_client = ClaudeBedrockClient(bedrock_runtime, model="anthropic.claude-3-haiku-20240307-v1:0")
151-
embed_client = BedrockEmbedding(bedrock_runtime, model="amazon.titan-embed-text-v1")
129+
os.environ["AWS_ACCESS_KEY_ID"] = "" # "my-aws-access-key"
130+
os.environ["AWS_SECRET_ACCESS_KEY"] = "" # "my-aws-secret-access-key"
131+
os.environ["AWS_REGION_NAME"] = "" # "us-west-2"
152132

153-
# Set the default client and embedding
154-
giskard.llm.set_default_client(claude_client)
155-
giskard.llm.embeddings.set_default_embedding(embed_client)
133+
giskard.llm.set_llm_model("bedrock/anthropic.claude-3-sonnet-20240229-v1:0", disable_structured_output=True)
134+
giskard.llm.set_embedding_model("bedrock/amazon.titan-embed-image-v1")
156135
```
157136

158137
::::::
159138
::::::{tab-item} Gemini
160139

140+
More information on [Gemini LiteLLM documentation](https://docs.litellm.ai/docs/providers/gemini)
141+
161142
```python
162143
import os
163144
import giskard
164-
import google.generativeai as genai
165-
from giskard.llm.client.gemini import GeminiClient
166-
167-
# Set the Gemini API key
168-
os.environ["GEMINI_API_KEY"] = ""
169-
170-
# Configure the Gemini API
171-
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
172-
173-
# Create a giskard Gemini client
174-
gemini_client = GeminiClient()
175145

176-
# Set the default client
177-
giskard.llm.set_default_client(gemini_client)
146+
os.environ["GEMINI_API_KEY"] = "" # "my-gemini-api-key"
178147

179-
# You may also want to set the default embedding model
180-
# Check the Custom Client code snippet for more details
148+
giskard.llm.set_llm_model("gemini/gemini-1.5-pro")
149+
giskard.llm.set_embedding_model("gemini/text-embedding-004")
181150
```
182151

183152
::::::
184153
::::::{tab-item} Custom Client
185154

155+
More information on [Custom Format LiteLLM documentation](https://docs.litellm.ai/docs/providers/custom_llm_server)
156+
186157
```python
158+
import os
159+
import requests
160+
from typing import Optional
161+
162+
import litellm
187163
import giskard
188-
from typing import Sequence, Optional
189-
from giskard.llm.client import set_default_client
190-
from giskard.llm.client.base import LLMClient, ChatMessage
191-
192-
# Create a custom client by extending the LLMClient class
193-
class MyLLMClient(LLMClient):
194-
def __init__(self, my_client):
195-
self._client = my_client
196-
197-
def complete(
198-
self,
199-
messages: Sequence[ChatMessage],
200-
temperature: float = 1,
201-
max_tokens: Optional[int] = None,
202-
caller_id: Optional[str] = None,
203-
seed: Optional[int] = None,
204-
format=None,
205-
) -> ChatMessage:
206-
# Create the prompt
207-
prompt = ""
208-
for msg in messages:
209-
if msg.role.lower() == "assistant":
210-
prefix = "\n\nAssistant: "
211-
else:
212-
prefix = "\n\nHuman: "
213-
214-
prompt += prefix + msg.content
215-
216-
prompt += "\n\nAssistant: "
217-
218-
# Create the body
219-
params = {
220-
"prompt": prompt,
221-
"max_tokens_to_sample": max_tokens or 1000,
222-
"temperature": temperature,
223-
"top_p": 0.9,
224-
}
225-
body = json.dumps(params)
226-
227-
response = self._client.invoke_model(
228-
body=body,
229-
modelId=self._model_id,
230-
accept="application/json",
231-
contentType="application/json",
164+
165+
166+
class MyCustomLLM(litellm.CustomLLM):
167+
def completion(self, messages: str, api_key: Optional[str] = None, **kwargs) -> litellm.ModelResponse:
168+
api_key = api_key or os.environ.get("MY_SECRET_KEY")
169+
if api_key is None:
170+
raise litellm.AuthenticationError("`api_key` was not provided")
171+
172+
response = requests.post(
173+
"https://www.my-custom-llm.ai/chat/completion",
174+
json={"messages": messages},
175+
headers={"Authorization": api_key},
232176
)
233-
data = json.loads(response.get("body").read())
234177

235-
return ChatMessage(role="assistant", message=data["completion"])
178+
return litellm.ModelResponse(**response.json())
236179

237-
# Create an instance of the custom client
238-
llm_client = MyLLMClient()
180+
os.eviron["MY_SECRET_KEY"] = "" # "my-secret-key"
239181

240-
# Set the default client
241-
set_default_client(llm_client)
182+
my_custom_llm = MyCustomLLM()
242183

243-
# It's also possible to create a custom embedding class extending BaseEmbedding
244-
# Or you can use FastEmbed for a pre-built embedding model:
245-
from giskard.llm.embeddings.fastembed import try_get_fastembed_embeddings
246-
embed_client = try_get_fastembed_embeddings()
247-
giskard.llm.embeddings.set_default_embedding(embed_client)
184+
litellm.custom_provider_map = [ # 👈 KEY STEP - REGISTER HANDLER
185+
{"provider": "my-custom-llm-endpoint", "custom_handler": my_custom_llm}
186+
]
187+
188+
api_key = os.environ["MY_SECRET_KEY"]
189+
190+
giskard.llm.set_llm_model("my-custom-llm-endpoint/my-custom-model", api_key=api_key)
248191
```
249192

250193
::::::
251194
:::::::
252195

253-
We are now ready to start.
254-
255196
(model-wrapping)=
256197

257198
## Step 1: Wrap your model

0 commit comments

Comments
 (0)