Open ayurk opened 1 week ago
I am also struggling to understand how to get Azure OpenAI API to work in 2.0.0
I actually got Azure OpenAI it to work 🎉. Not the cleanest solution but here for whom it might be interesting:
AzureOpenAIGenerator.py
, containing the following code (replace placeholders with your URL/key):import os
from dotenv import load_dotenv
from goldenverba.components.interfaces import Generator
from goldenverba.components.types import InputConfig
from goldenverba.components.util import get_environment
import httpx
import json
load_dotenv()
class AzureOpenAIGenerator(Generator):
"""
Azure OpenAI Generator.
"""
def __init__(self):
super().__init__()
self.name = "AzureOpenAI"
self.description = "Using Azure OpenAI LLM models to generate answers to queries"
self.context_window = 10000
models = ["gpt-4o", "gpt-3.5-turbo"]
self.config["Model"] = InputConfig(
type="dropdown",
value=models[0],
description="Select an Azure OpenAI Model",
values=models,
)
if os.getenv("AZURE_OPENAI_API_KEY") is None:
self.config["API Key"] = InputConfig(
type="password",
value="<ADD YOUR AZURE API KEY HERE>_",
description="You can set your Azure OpenAI API Key here or set it as environment variable `AZURE_OPENAI_API_KEY`",
values=[],
)
if os.getenv("AZURE_OPENAI_BASE_URL") is None:
self.config["URL"] = InputConfig(
type="text",
value="https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME",
description="You can change the Base URL here if needed",
values=[],
)
async def generate_stream(
self,
config: dict,
query: str,
context: str,
conversation: list[dict] = [],
):
system_message = config.get("System Message").value
print(system_message)
model = config.get("Model", {"value": "gpt-3.5-turbo"}).value
print(model)
azure_key = get_environment(
config, "API Key", "AZURE_OPENAI_API_KEY", "No Azure OpenAI API Key found"
)
print(azure_key)
azure_url = get_environment(
config, "URL", "AZURE_OPENAI_BASE_URL", "https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME"
)
print(azure_url)
messages = self.prepare_messages(query, context, conversation, system_message)
print(messages)
headers = {
"Content-Type": "application/json",
"api-key": azure_key,
}
data = {
"messages": messages,
"model": model,
"stream": True,
}
async with httpx.AsyncClient() as client2:
async with client2.stream(
"POST",
f"{azure_url}/chat/completions?api-version=2023-03-15-preview",
json=data,
headers=headers,
timeout=None,
) as response:
async for line in response.aiter_lines():
if line.startswith("data: "):
if line.strip() == "data: [DONE]":
break
json_line = json.loads(line[6:])
choice = json_line["choices"][0]
if "delta" in choice and "content" in choice["delta"]:
yield {
"message": choice["delta"]["content"],
"finish_reason": choice.get("finish_reason"),
}
elif "finish_reason" in choice:
yield {
"message": "",
"finish_reason": choice["finish_reason"],
}
else: print(response)
def prepare_messages(
self, query: str, context: str, conversation: list[dict], system_message: str
) -> list[dict]:
messages = [
{
"role": "system",
"content": system_message,
}
]
for message in conversation:
messages.append({"role": message.type, "content": message.content})
messages.append(
{
"role": "user",
"content": f"Answer this query: '{query}' with this provided context: {context}",
}
)
return messages
add to line 68: from goldenverba.components.generation.AzureOpenAIGenerator import AzureOpenAIGenerator
also to line 110:
generators = [
OllamaGenerator(),
OpenAIGenerator(),
AnthropicGenerator(),
CohereGenerator(),
AzureOpenAIGenerator(),
]
and to line 137:
generators = [
OpenAIGenerator(),
AnthropicGenerator(),
CohereGenerator(),
AzureOpenAIGenerator(),
]
import httpx
async with httpx.AsyncClient(proxy="http://YOUR_PROXYSERVER:YOUR_PORT") as client:
async for result in self.generators[generator].generate_stream(
generator_config, query, context, conversation
):
yield result
Don't ask me how exactly this works. I tried adding the proxy in the AsyncClient() in AzureOpenAIGenerator.py
but only the solution above finally worked for me.
Description
Verba generates an incorrect URL when sending requests to Azure, resulting in a 404 Not Found error. When the URL is manually corrected to the appropriate format, the response changes to a 401 Unauthorized error. Despite having the correct URL and authorization data in the headers, Verba is unable to pass authorization when connecting to Azure OpenAI.
The default (generated by Verba) URL used is:
https://resource_name.openai.azure.com/chat/completions
, response is a 404 Not Found error.After manually correcting the URL to the appropriate format:
https://resource_name.openai.azure.com/openai/deployments/openai_model/chat/completions?api-version=2023-05-15
, the response changes to 401 Unauthorized error..env file: OPENAI_API_TYPE= 'azure'
OPENAI_API_KEY = 'api_key'
OPENAI_BASE_URL = 'https://resource_name.openai.azure.com'
AZURE_OPENAI_RESOURCE_NAME = 'resource_name'
AZURE_OPENAI_EMBEDDING_MODEL = 'text-embedding-3-large'
OPENAI_MODEL = 'openai_model'
HuggingFace_Api_Key = 'api_key_hf'
WEAVIATE_URL_VERBA = 'http://localhost:8080/'
Below is manually changed function in
components -> generation -> OpenAIGenerator.py
with hardcoded URL (changed lines are in bold):Below on the bolded line, I have a breakpoint where I receive the responses - 404 or 401. Both in case with the default URL and manually prepared URL (when the response contains error 401),
auth
parameter is empty. But authorization data already is in the headers - "Bearer {openai_key}". It seems to me that theauth
parameter should not be empty.httpx -> _client.py -> AsyncClient
lines 1577-1626Installation
If you installed via pip, please specify the version: goldenverba v2.0.0
Weaviate Deployment
Configuration
Reader: Default Chunker: Token Embedder: sentence-transformers/all-MiniLM-L6-v2 Retriever: Generator:
Steps to Reproduce
https://resource_name.openai.azure.com/chat/completions
.https://resource_name.openai.azure.com/openai/deployments/openai_model/chat/completions?api-version=2023-05-15
.Note: In
components -> embedding -> OpenAIEmbedder.py
lines 25-44, I commented out the code becauseself.get_models()
also operates on the wrong URL. I generally don't need Azure Embedded, as I use an embedding model from sentence-transformers. However, Verba still checked the possibility of connecting to the embedding model on Azure, not considering the configuration in the .env file. Due to this checking, the Verba interface (homepage) didn't even start. After commenting out these lines, Verba started, and I was able to import some documents and retrieve chunks, but without using the Generator due to the problem with connection described above.Additional context
Note: goldenverba v1.0.4 can connect to Azure with the same .env file and configuration (that version used openai lib for communication with Azure. As far as I can see, version 2.0.0 has a different logic).