Skip to content

Commit 9f4b12c

Browse files
authored
Merge pull request #1 from pamelafox/first
Initial demo files
2 parents b8a8cb8 + e4317aa commit 9f4b12c

14 files changed

+531
-80
lines changed

.devcontainer/devcontainer.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
"name": "Python 3",
55
"image": "mcr.microsoft.com/devcontainers/python:3.11-bullseye",
66

7+
"features": {
8+
"ghcr.io/devcontainers/features/azure-cli:latest": {},
9+
"ghcr.io/azure/azure-dev/azd:latest": {}
10+
},
711
// Configure tool-specific properties.
812
"customizations": {
913
// Configure properties specific to VS Code.
1014
"vscode": {
1115
// Set *default* container specific settings.json values on container create.
1216
"settings": {
1317
"python.defaultInterpreterPath": "/usr/local/bin/python",
14-
"python.testing.pytestEnabled": true,
15-
"python.testing.unittestEnabled": false,
1618
"files.exclude": {
17-
".coverage": true,
18-
".pytest_cache": true,
1919
"__pycache__": true
2020
}
2121
},
@@ -33,7 +33,7 @@
3333
// "forwardPorts": [],
3434

3535
// Use 'postCreateCommand' to run commands after the container is created.
36-
"postCreateCommand": "pip3 install --user -r requirements-dev.txt && pre-commit install",
36+
"postCreateCommand": "pip3 install --user -r requirements-dev.txt",
3737

3838
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
3939
"remoteUser": "vscode"

.env.sample

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# API_HOST can be either azure, ollama, or openai:
2+
API_HOST=azure
3+
# Needed for Azure:
4+
AZURE_OPENAI_ENDPOINT=https://YOUR-AZURE-OPENAI-SERVICE-NAME.openai.azure.com
5+
AZURE_OPENAI_DEPLOYMENT=YOUR-AZURE-DEPLOYMENT-NAME
6+
AZURE_OPENAI_VERSION=2024-03-01-preview
7+
# Needed for Ollama:
8+
OLLAMA_ENDPOINT=http://localhost:11434/v1
9+
OLLAMA_MODEL=llama2
10+
# Needed for OpenAI.com:
11+
OPENAI_KEY=YOUR-OPENAI-KEY
12+
OPENAI_MODEL=gpt-3.5-turbo

.github/workflows/python.yaml

-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,3 @@ jobs:
2323
run: ruff .
2424
- name: Check formatting with black
2525
run: black . --check --verbose
26-
- name: Run unit tests
27-
run: |
28-
pytest

.gitignore

+141-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,142 @@
1-
.venv
2-
__pycache__
1+
# Azure az webapp deployment details
2+
.azure
3+
*_env
4+
5+
# Byte-compiled / optimized / DLL files
6+
__pycache__/
7+
*.py[cod]
8+
*$py.class
9+
10+
# C extensions
11+
*.so
12+
13+
# Distribution / packaging
14+
.Python
15+
build/
16+
develop-eggs/
17+
dist/
18+
downloads/
19+
eggs/
20+
.eggs/
21+
lib/
22+
lib64/
23+
parts/
24+
sdist/
25+
var/
26+
wheels/
27+
share/python-wheels/
28+
*.egg-info/
29+
.installed.cfg
30+
*.egg
31+
MANIFEST
32+
33+
# PyInstaller
34+
# Usually these files are written by a python script from a template
35+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
36+
*.manifest
37+
*.spec
38+
39+
# Installer logs
40+
pip-log.txt
41+
pip-delete-this-directory.txt
42+
43+
# Unit test / coverage reports
44+
htmlcov/
45+
.tox/
46+
.nox/
347
.coverage
48+
.coverage.*
49+
.cache
50+
nosetests.xml
51+
coverage.xml
52+
*.cover
53+
*.py,cover
54+
.hypothesis/
55+
.pytest_cache/
56+
cover/
57+
58+
# Translations
59+
*.mo
60+
*.pot
61+
62+
# Django stuff:
63+
*.log
64+
local_settings.py
65+
db.sqlite3
66+
db.sqlite3-journal
67+
68+
# Flask stuff:
69+
instance/
70+
.webassets-cache
71+
72+
# Scrapy stuff:
73+
.scrapy
74+
75+
# Sphinx documentation
76+
docs/_build/
77+
78+
# PyBuilder
79+
.pybuilder/
80+
target/
81+
82+
# Jupyter Notebook
83+
.ipynb_checkpoints
84+
85+
# IPython
86+
profile_default/
87+
ipython_config.py
88+
89+
# pyenv
90+
# For a library or package, you might want to ignore these files since the code is
91+
# intended to run in multiple environments; otherwise, check them in:
92+
# .python-version
93+
94+
# pipenv
95+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
96+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
97+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
98+
# install all needed dependencies.
99+
#Pipfile.lock
100+
101+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
102+
__pypackages__/
103+
104+
# Celery stuff
105+
celerybeat-schedule
106+
celerybeat.pid
107+
108+
# SageMath parsed files
109+
*.sage.py
110+
111+
# Environments
112+
.env
113+
.venv
114+
env/
115+
venv/
116+
ENV/
117+
env.bak/
118+
venv.bak/
119+
120+
# Spyder project settings
121+
.spyderproject
122+
.spyproject
123+
124+
# Rope project settings
125+
.ropeproject
126+
127+
# mkdocs documentation
128+
/site
129+
130+
# mypy
131+
.mypy_cache/
132+
.dmypy.json
133+
dmypy.json
134+
135+
# Pyre type checker
136+
.pyre/
137+
138+
# pytype static type analyzer
139+
.pytype/
140+
141+
# Cython debug symbols
142+
cython_debug/

README.md

+43-57
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,64 @@
1-
# Python project template
1+
# Python OpenAI demos
22

3-
This is a template repository for any Python project that comes with the following dev tools:
3+
This repository contains a collection of Python scripts that demonstrate how to use the OpenAI API to generate chat completions.
44

5-
* `ruff`: identifies many errors and style issues (`flake8`, `isort`, `pyupgrade`)
6-
* `black`: auto-formats code
5+
In increasing order of complexity, the scripts are:
76

8-
Those checks are run as pre-commit hooks using the `pre-commit` library.
7+
1. [`chat.py`](./chat.py): A simple script that demonstrates how to use the OpenAI API to generate chat completions.
8+
2. [`chat_stream.py`](./chat_stream.py): Adds `stream=True` to the API call to return a generator that streams the completion as it is being generated.
9+
3. [`chat_history.py`](./chat_history.py): Adds a back-and-forth chat interface using `input()` which keeps track of past messages and sends them with each chat completion call.
10+
4. [`chat_history_stream.py`](./chat_history_stream.py): The same idea, but with `stream=True` enabled.
911

10-
It includes `pytest` for testing plus the `pytest-cov` plugin to measure coverage.
12+
Plus these scripts to demonstrate additional features:
1113

12-
The checks and tests are all run using Github actions on every pull request and merge to main.
14+
5. [`chat_safety.py`](./chat_safety.py): The simple script with exception handling for Azure AI Content Safety filter errors.
15+
6. [`chat_async.py`](./chat_async.py): Uses the async clients to make asynchronous calls, including an example of sending off multiple requests at once using `asyncio.gather`.
1316

14-
This repository is setup for Python 3.11. To change the version:
15-
1. Change the `image` argument in `.devcontainer/devcontainer.json` (see [https://github.com/devcontainers/images/tree/main/src/python](https://github.com/devcontainers/images/tree/main/src/python#configuration) for a list of pre-built Docker images)
16-
1. Change the config options in `.precommit-config.yaml`
17-
1. Change the version number in `.github/workflows/python.yaml`
17+
## Setting up the environment
1818

19-
## Development instructions
19+
If you open this up in a Dev Container or GitHub Codespaces, everything will be setup for you.
20+
If not, follow these steps:
2021

21-
## With devcontainer
22+
1. Set up a Python virtual environment and activate it.
2223

23-
This repository comes with a devcontainer (a Dockerized Python environment). If you open it in Codespaces, it should automatically initialize the devcontainer.
24+
2. Install the required packages:
2425

25-
Locally, you can open it in VS Code with the Dev Containers extension installed.
26-
27-
## Without devcontainer
28-
29-
If you can't or don't want to use the devcontainer, then you should first create a virtual environment:
30-
31-
```
32-
python3 -m venv .venv
33-
source .venv/bin/activate
34-
```
35-
36-
Then install the dev tools and pre-commit hooks:
37-
38-
```
39-
python3 -m pip install --user -r requirements-dev.txt
40-
pre-commit install
26+
```bash
27+
pip install -r requirements.txt
4128
```
4229

43-
## Adding code and tests
30+
## Configuring the OpenAI environment variables
4431

45-
This repository starts with a very simple `main.py` and a test for it at `tests/main_test.py`.
46-
You'll want to replace that with your own code, and you'll probably want to add additional files
47-
as your code grows in complexity.
32+
These scripts can be run against an Azure OpenAI account, an OpenAI.com account, or a local Ollama server,
33+
depending on the environment variables you set.
4834

49-
When you're ready to run tests, run:
35+
1. Copy the `.env.sample file to a new file called `.env`:
5036

51-
```
52-
python3 -m pytest
53-
```
37+
```bash
38+
cp .env.sample .env
39+
```
5440

55-
# File breakdown
41+
2. For Azure OpenAI, create an Azure OpenAI gpt-3.5 or gpt-4 deployment, and customize the `.env` file with your Azure OpenAI endpoint and deployment id.
5642

57-
Here's a short explanation of each file/folder in this template:
43+
```bash
44+
API_HOST=azure
45+
AZURE_OPENAI_ENDPOINT=https://YOUR-AZURE-OPENAI-SERVICE-NAME.openai.azure.com
46+
AZURE_OPENAI_DEPLOYMENT=YOUR-AZURE-DEPLOYMENT-NAME
47+
AZURE_OPENAI_VERSION=2024-03-01-preview
48+
```
5849

59-
* `.devcontainer`: Folder containing files used for setting up a devcontainer
60-
* `devcontainer.json`: File configuring the devcontainer, includes VS Code settings
61-
* `.github`: Folder for Github-specific files and folders
62-
* `workflows`: Folder containing Github actions config files
63-
* `python.yaml`: File configuring Github action that runs tools and tests
64-
* `tests`: Folder containing Python tests
65-
* `main_test.py`: File with pytest-style tests of main.py
66-
* `.gitignore`: File describing what file patterns Git should never track
67-
* `.pre-commit-config.yaml`: File listing all the pre-commit hooks and args
68-
* `main.py`: The main (and currently only) Python file for the program
69-
* `pyproject.toml`: File configuring most of the Python dev tools
70-
* `README.md`: You're reading it!
71-
* `requirements-dev.txt`: File listing all PyPi packages required for development
72-
* `requirements.txt`: File listing all PyPi packages required for production
50+
3. For OpenAI.com, customize the `.env` file with your OpenAI API key and desired model name.
7351

74-
For a longer explanation, read [this blog post](http://blog.pamelafox.org/2022/09/how-i-setup-python-project.html).
52+
```bash
53+
API_HOST=openai
54+
OPENAI_KEY=YOUR-OPENAI-API-KEY
55+
OPENAI_MODEL=gpt-3.5-turbo
56+
```
7557

76-
# 🔎 Found an issue or have an idea for improvement?
58+
4. For Ollama, customize the `.env` file with your Ollama endpoint and model name (any model you've pulled).
7759
78-
Help me make this template repository better by letting us know and opening an issue!
60+
```bash
61+
API_HOST=ollama
62+
OLLAMA_ENDPOINT=http://localhost:11434/v1
63+
OLLAMA_MODEL=llama2
64+
```

chat.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
3+
import azure.identity
4+
import openai
5+
from dotenv import load_dotenv
6+
7+
# Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API
8+
load_dotenv()
9+
API_HOST = os.getenv("API_HOST")
10+
11+
if API_HOST == "azure":
12+
token_provider = azure.identity.get_bearer_token_provider(
13+
azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"
14+
)
15+
client = openai.AzureOpenAI(
16+
api_version=os.getenv("AZURE_OPENAI_VERSION"),
17+
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
18+
azure_ad_token_provider=token_provider,
19+
)
20+
MODEL_NAME = os.getenv("AZURE_OPENAI_DEPLOYMENT")
21+
elif API_HOST == "ollama":
22+
client = openai.OpenAI(
23+
base_url="http://localhost:11434/v1",
24+
api_key="nokeyneeded",
25+
)
26+
MODEL_NAME = os.getenv("OLLAMA_MODEL")
27+
else:
28+
client = openai.OpenAI(api_key=os.getenv("OPENAI_KEY"))
29+
MODEL_NAME = os.getenv("OPENAI_MODEL")
30+
31+
32+
response = client.chat.completions.create(
33+
model=MODEL_NAME,
34+
temperature=0.7,
35+
n=1,
36+
messages=[
37+
{"role": "system", "content": "You are a helpful assistant that makes lots of cat references and uses emojis."},
38+
{"role": "user", "content": "Write a haiku about a hungry cat who wants tuna"},
39+
],
40+
)
41+
42+
print("Response: ")
43+
print(response.choices[0].message.content)

0 commit comments

Comments
 (0)