Add Azure OpenAI LLM (#395)

Hi!  This PR adds support for the Azure OpenAI service to LangChain.

I've tried to follow the contributing guidelines.

Co-authored-by: Keiji Kanazawa <{ID}+{username}@users.noreply.github.com>
fork-chains
Keiji Kanazawa 1 year ago committed by GitHub
parent bb76440bfa
commit 543db9c2df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,159 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9e9b7651",
"metadata": {},
"source": [
"# Azure OpenAI LLM Example\n",
"\n",
"This notebook goes over how to use Langchain with [Azure OpenAI](https://aka.ms/azure-openai).\n",
"\n",
"The Azure OpenAI API is compatible with OpenAI's API. The `openai` Python package makes it easy to use both OpenAI and Azure OpenAI. You can call Azure OpenAI the same way you call OpenAI with the exceptions noted below.\n",
"\n",
"### API configuration\n",
"You can configure the `openai` package to use Azure OpenAI using environment variables. The following is for `bash`:\n",
"\n",
"```bash\n",
"# Set this to `azure`\n",
"export OPENAI_API_TYPE=azure\n",
"# The API version you want to use: set this to `2022-12-01` for the released version.\n",
"export OPENAI_API_VERSION=2022-12-01\n",
"# The base URL for your Azure OpenAI resource. You can find this in the Azure portal under your Azure OpenAI resource.\n",
"export OPENAI_API_BASE_URL=https://your-resource-name.openai.azure.com\n",
"# The API key for your Azure OpenAI resource. You can find this in the Azure portal under your Azure OpenAI resource.\n",
"export OPENAI_API_KEY=<your Azure OpenAI API key>\n",
"```\n",
"\n",
"Alternatively, you can configure the API right within your running Python environment:\n",
"\n",
"```python\n",
"import os\n",
"os.environ[\"OPENAI_API_TYPE\"] = \"azure\"\n",
"...\n",
"```\n",
"\n",
"### Deployments\n",
"With Azure OpenAI, you set up your own deployments of the common GPT-3 and Codex models. When calling the API, you need to specify the deployment you want to use.\n",
"\n",
"Let's say your deployment name is `text-davinci-002-prod`. In the `openai` Python API, you can specify this deployment with the `engine` parameter. For example:\n",
"\n",
"```python\n",
"import openai\n",
"\n",
"response = openai.Completion.create(\n",
" engine=\"text-davinci-002-prod\",\n",
" prompt=\"This is a test\",\n",
" max_tokens=5\n",
")\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "8fad2a6e",
"metadata": {},
"outputs": [],
"source": [
"# Import Azure OpenAI\n",
"from langchain.llms import AzureOpenAI"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8c80213a",
"metadata": {},
"outputs": [],
"source": [
"# Create an instance of Azure OpenAI\n",
"# Replace the deployment name with your own\n",
"llm = AzureOpenAI(deployment_name=\"text-davinci-002-prod\", model_name=\"text-davinci-002\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "592dc404",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'\\n\\nWhy did the chicken cross the road?\\n\\nTo get to the other side.'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Run the LLM\n",
"llm(\"Tell me a joke\")"
]
},
{
"cell_type": "markdown",
"id": "bbfebea1",
"metadata": {},
"source": [
"We can also print the LLM and see its custom print."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9c33fa19",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1mAzureOpenAI\u001b[0m\n",
"Params: {'deployment_name': 'text-davinci-002', 'model_name': 'text-davinci-002', 'temperature': 0.7, 'max_tokens': 256, 'top_p': 1, 'frequency_penalty': 0, 'presence_penalty': 0, 'n': 1, 'best_of': 1}\n"
]
}
],
"source": [
"print(llm)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a8b5917",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.8"
},
"vscode": {
"interpreter": {
"hash": "3bae61d45a4f4d73ecea8149862d4bfbae7d4d4a2f71b6e609a1be8f6c8d4298"
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}

@ -7,7 +7,7 @@ from langchain.llms.cohere import Cohere
from langchain.llms.huggingface_hub import HuggingFaceHub
from langchain.llms.huggingface_pipeline import HuggingFacePipeline
from langchain.llms.nlpcloud import NLPCloud
from langchain.llms.openai import OpenAI
from langchain.llms.openai import AzureOpenAI, OpenAI
__all__ = [
"Cohere",
@ -16,6 +16,7 @@ __all__ = [
"HuggingFaceHub",
"HuggingFacePipeline",
"AI21",
"AzureOpenAI",
]
type_to_cls_dict: Dict[str, Type[BaseLLM]] = {
@ -25,4 +26,5 @@ type_to_cls_dict: Dict[str, Type[BaseLLM]] = {
"nlpcloud": NLPCloud,
"openai": OpenAI,
"huggingface_pipeline": HuggingFacePipeline,
"azure": AzureOpenAI,
}

@ -9,7 +9,7 @@ from langchain.schema import Generation
from langchain.utils import get_from_dict_or_env
class OpenAI(BaseLLM, BaseModel):
class BaseOpenAI(BaseLLM, BaseModel):
"""Wrapper around OpenAI large language models.
To use, you should have the ``openai`` python package installed, and the
@ -119,7 +119,7 @@ class OpenAI(BaseLLM, BaseModel):
response = openai.generate(["Tell me a joke."])
"""
# TODO: write a unit test for this
params = self._default_params
params = self._invocation_params
if stop is not None:
if "stop" in params:
raise ValueError("`stop` found in both the input and default params.")
@ -141,9 +141,7 @@ class OpenAI(BaseLLM, BaseModel):
# Includes prompt, completion, and total tokens used.
_keys = ["completion_tokens", "prompt_tokens", "total_tokens"]
for _prompts in sub_prompts:
response = self.client.create(
model=self.model_name, prompt=_prompts, **params
)
response = self.client.create(prompt=_prompts, **params)
choices.extend(response["choices"])
for _key in _keys:
if _key not in token_usage:
@ -179,14 +177,19 @@ class OpenAI(BaseLLM, BaseModel):
for token in generator:
yield token
"""
params = self._default_params
params = self._invocation_params
if params["best_of"] != 1:
raise ValueError("OpenAI only supports best_of == 1 for streaming")
params["stream"] = True
generator = self.client.create(model=self.model_name, prompt=prompt, **params)
generator = self.client.create(prompt=prompt, **params)
return generator
@property
def _invocation_params(self) -> Dict[str, Any]:
"""Get the parameters used to invoke the model."""
return self._default_params
@property
def _identifying_params(self) -> Mapping[str, Any]:
"""Get the identifying parameters."""
@ -274,3 +277,29 @@ class OpenAI(BaseLLM, BaseModel):
# get max context size for model by name
max_size = self.modelname_to_contextsize(self.model_name)
return max_size - num_tokens
class OpenAI(BaseOpenAI):
"""Generic OpenAI class that uses model name."""
@property
def _invocation_params(self) -> Dict[str, Any]:
return {**{"model": self.model_name}, **super()._invocation_params}
class AzureOpenAI(BaseOpenAI):
"""Azure specific OpenAI class that uses deployment name."""
deployment_name: str = ""
"""Deployment name to use."""
@property
def _identifying_params(self) -> Mapping[str, Any]:
return {
**{"deployment_name": self.deployment_name},
**super()._identifying_params,
}
@property
def _invocation_params(self) -> Dict[str, Any]:
return {**{"engine": self.deployment_name}, **super()._invocation_params}

Loading…
Cancel
Save