Skip to content

Commit 2ad7b4a

Browse files
authored
Merge branch 'main' into dependabot/pip/src/backend/h11-0.16.0
2 parents 7d375b6 + 6ab9ea5 commit 2ad7b4a

26 files changed

+104785
-156851
lines changed

.env.sample

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ POSTGRES_PASSWORD=postgres
55
POSTGRES_DATABASE=postgres
66
POSTGRES_SSL=disable
77

8-
# OPENAI_CHAT_HOST can be either azure, openai, or ollama:
8+
# OPENAI_CHAT_HOST can be either azure, openai, ollama, or github:
99
OPENAI_CHAT_HOST=azure
10-
# OPENAI_EMBED_HOST can be either azure or openai:
10+
# OPENAI_EMBED_HOST can be either azure, openai, ollama, or github:
1111
OPENAI_EMBED_HOST=azure
1212
# Needed for Azure:
1313
# You also need to `azd auth login` if running this locally
1414
AZURE_OPENAI_ENDPOINT=https://YOUR-AZURE-OPENAI-SERVICE-NAME.openai.azure.com
1515
AZURE_OPENAI_VERSION=2024-03-01-preview
1616
AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-4o-mini
1717
AZURE_OPENAI_CHAT_MODEL=gpt-4o-mini
18-
AZURE_OPENAI_EMBED_DEPLOYMENT=text-embedding-ada-002
19-
AZURE_OPENAI_EMBED_MODEL=text-embedding-ada-002
20-
AZURE_OPENAI_EMBED_DIMENSIONS=1536
21-
AZURE_OPENAI_EMBEDDING_COLUMN=embedding_ada002
18+
AZURE_OPENAI_EMBED_DEPLOYMENT=text-embedding-3-large
19+
AZURE_OPENAI_EMBED_MODEL=text-embedding-3-large
20+
AZURE_OPENAI_EMBED_DIMENSIONS=1024
21+
AZURE_OPENAI_EMBEDDING_COLUMN=embedding_3l
2222
AZURE_OPENAI_EVAL_DEPLOYMENT=gpt-4
2323
AZURE_OPENAI_EVAL_MODEL=gpt-4
2424
AZURE_TENANT_ID=
@@ -27,11 +27,18 @@ AZURE_OPENAI_KEY=
2727
# Needed for OpenAI.com:
2828
OPENAICOM_KEY=YOUR-OPENAI-API-KEY
2929
OPENAICOM_CHAT_MODEL=gpt-3.5-turbo
30-
OPENAICOM_EMBED_MODEL=text-embedding-ada-002
31-
OPENAICOM_EMBED_MODEL_DIMENSIONS=1536
32-
OPENAICOM_EMBEDDING_COLUMN=embedding_ada002
30+
OPENAICOM_EMBED_MODEL=text-embedding-3-large
31+
OPENAICOM_EMBED_DIMENSIONS=1024
32+
OPENAICOM_EMBEDDING_COLUMN=embedding_3l
3333
# Needed for Ollama:
3434
OLLAMA_ENDPOINT=http://host.docker.internal:11434/v1
3535
OLLAMA_CHAT_MODEL=llama3.1
3636
OLLAMA_EMBED_MODEL=nomic-embed-text
3737
OLLAMA_EMBEDDING_COLUMN=embedding_nomic
38+
# Needed for GitHub Models:
39+
GITHUB_TOKEN=YOUR-GITHUB-TOKEN
40+
GITHUB_BASE_URL=https://models.inference.ai.azure.com
41+
GITHUB_MODEL=gpt-4o
42+
GITHUB_EMBED_MODEL=text-embedding-3-large
43+
GITHUB_EMBED_DIMENSIONS=1024
44+
GITHUB_EMBEDDING_COLUMN=embedding_3l

.github/workflows/app-tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ jobs:
8585
architecture: x64
8686

8787
- name: Install uv
88-
uses: astral-sh/setup-uv@v5
88+
uses: astral-sh/setup-uv@v6
8989
with:
9090
enable-cache: true
9191
version: "0.4.20"

.github/workflows/evaluate.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ jobs:
8282
python-version: '3.12'
8383

8484
- name: Install uv
85-
uses: astral-sh/setup-uv@v5
85+
uses: astral-sh/setup-uv@v6
8686
with:
8787
enable-cache: true
8888
version: "0.4.20"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Once you've opened the project in [Codespaces](#github-codespaces), [Dev Contain
123123
azd up
124124
```
125125
126-
You will be asked to select two locations, first a region for most of the resources (Container Apps, PostgreSQL), then a region specifically for the Azure OpenAI models. This project uses the gpt-4o-mini and text-embedding-ada-002 models which may not be available in all Azure regions. Check for [up-to-date region availability](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#standard-deployment-model-availability) and select a region accordingly.
126+
You will be asked to select two locations, first a region for most of the resources (Container Apps, PostgreSQL), then a region specifically for the Azure OpenAI models. This project uses the gpt-4o-mini and text-embedding-3-large models which may not be available in all Azure regions. Check for [up-to-date region availability](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#standard-deployment-model-availability) and select a region accordingly.
127127
128128
## Local Development
129129

evals/evaluate.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ def get_openai_config() -> dict:
6666
# azure-ai-evaluate will call DefaultAzureCredential behind the scenes,
6767
# so we must be logged in to Azure CLI with the correct tenant
6868
openai_config["model"] = os.environ["AZURE_OPENAI_EVAL_MODEL"]
69+
elif os.environ.get("OPENAI_CHAT_HOST") == "ollama":
70+
raise NotImplementedError("Ollama is not supported. Switch to Azure or OpenAI.com")
71+
elif os.environ.get("OPENAI_CHAT_HOST") == "github":
72+
raise NotImplementedError("GitHub Models is not supported. Switch to Azure or OpenAI.com")
6973
else:
7074
logger.info("Using OpenAI Service with API Key from OPENAICOM_KEY")
7175
openai_config = {"api_key": os.environ["OPENAICOM_KEY"], "model": "gpt-4"}

evals/generate_ground_truth.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ def get_openai_client() -> tuple[Union[AzureOpenAI, OpenAI], str]:
101101
)
102102
model = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"]
103103
elif OPENAI_CHAT_HOST == "ollama":
104-
raise NotImplementedError("Ollama OpenAI Service is not supported. Switch to Azure or OpenAI.com")
104+
raise NotImplementedError("Ollama is not supported. Switch to Azure or OpenAI.com")
105+
elif OPENAI_CHAT_HOST == "github":
106+
raise NotImplementedError("GitHub Models is not supported. Switch to Azure or OpenAI.com")
105107
else:
106108
logger.info("Using OpenAI Service with API Key from OPENAICOM_KEY")
107109
openai_client = OpenAI(api_key=os.environ["OPENAICOM_KEY"])

evals/safety_evaluation.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,13 @@ async def run_simulator(target_url: str, max_simulations: int):
106106
else:
107107
logger.info(f"Failing score from:\nQ: {query}\nA: {answer}\n{evaluator} score: {eval_score}")
108108
numeric_severity_score = eval_score[f"{evaluator}_score"]
109-
if isinstance(numeric_severity_score, float):
109+
if isinstance(numeric_severity_score, float) or isinstance(numeric_severity_score, int):
110110
summary_scores[evaluator]["score_total"] += numeric_severity_score
111111

112112
# Compute the overall statistics
113113
for evaluator in evaluators:
114114
if len(outputs) > 0:
115-
summary_scores[evaluator]["mean_score"] = (
116-
summary_scores[evaluator]["score_total"] / summary_scores[evaluator]["low_count"]
117-
)
115+
summary_scores[evaluator]["mean_score"] = summary_scores[evaluator]["score_total"] / len(outputs)
118116
summary_scores[evaluator]["low_rate"] = summary_scores[evaluator]["low_count"] / len(outputs)
119117

120118
# Save summary scores

infra/main.bicep

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,12 +302,12 @@ var webAppEnv = union(azureOpenAIKeyEnv, openAIComKeyEnv, [
302302
value: openAIEmbedHost
303303
}
304304
{
305-
name: 'OPENAICOM_EMBED_MODEL_DIMENSIONS'
306-
value: openAIEmbedHost == 'openaicom' ? '1536' : ''
305+
name: 'OPENAICOM_EMBED_DIMENSIONS'
306+
value: openAIEmbedHost == 'openaicom' ? '1024' : ''
307307
}
308308
{
309309
name: 'OPENAICOM_EMBED_MODEL'
310-
value: openAIEmbedHost == 'openaicom' ? 'text-embedding-ada-002' : ''
310+
value: openAIEmbedHost == 'openaicom' ? 'text-embedding-3-large' : ''
311311
}
312312
{
313313
name: 'AZURE_OPENAI_EMBED_MODEL'

infra/main.parameters.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,22 @@
6969
"value": "${OPENAI_EMBED_HOST=azure}"
7070
},
7171
"embedModelName":{
72-
"value": "${AZURE_OPENAI_EMBED_MODEL=text-embedding-ada-002}"
72+
"value": "${AZURE_OPENAI_EMBED_MODEL=text-embedding-3-large}"
7373
},
7474
"embedDeploymentName": {
75-
"value": "${AZURE_OPENAI_EMBED_DEPLOYMENT=text-embedding-ada-002}"
75+
"value": "${AZURE_OPENAI_EMBED_DEPLOYMENT=text-embedding-3-large}"
7676
},
7777
"embedDeploymentVersion":{
78-
"value": "${AZURE_OPENAI_EMBED_DEPLOYMENT_VERSION=2}"
78+
"value": "${AZURE_OPENAI_EMBED_DEPLOYMENT_VERSION=1}"
7979
},
8080
"embedDeploymentSku": {
81-
"value": "${AZURE_OPENAI_EMBED_DEPLOYMENT_SKU=Standard}"
81+
"value": "${AZURE_OPENAI_EMBED_DEPLOYMENT_SKU=GlobalStandard}"
8282
},
8383
"embedDeploymentCapacity":{
8484
"value": "${AZURE_OPENAI_EMBED_DEPLOYMENT_CAPACITY=30}"
8585
},
8686
"embedDimensions": {
87-
"value": "${AZURE_OPENAI_EMBED_DIMENSIONS=1536}"
87+
"value": "${AZURE_OPENAI_EMBED_DIMENSIONS=1024}"
8888
},
8989
"openAIComKey": {
9090
"value": "${OPENAICOM_KEY}"

src/backend/fastapi_app/dependencies.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,35 @@ async def common_parameters():
4242
OPENAI_EMBED_HOST = os.getenv("OPENAI_EMBED_HOST")
4343
OPENAI_CHAT_HOST = os.getenv("OPENAI_CHAT_HOST")
4444
if OPENAI_EMBED_HOST == "azure":
45-
openai_embed_deployment = os.getenv("AZURE_OPENAI_EMBED_DEPLOYMENT") or "text-embedding-ada-002"
46-
openai_embed_model = os.getenv("AZURE_OPENAI_EMBED_MODEL") or "text-embedding-ada-002"
47-
openai_embed_dimensions = int(os.getenv("AZURE_OPENAI_EMBED_DIMENSIONS") or 1536)
48-
embedding_column = os.getenv("AZURE_OPENAI_EMBEDDING_COLUMN") or "embedding_ada002"
45+
openai_embed_deployment = os.getenv("AZURE_OPENAI_EMBED_DEPLOYMENT") or "text-embedding-3-large"
46+
openai_embed_model = os.getenv("AZURE_OPENAI_EMBED_MODEL") or "text-embedding-3-large"
47+
openai_embed_dimensions = int(os.getenv("AZURE_OPENAI_EMBED_DIMENSIONS") or 1024)
48+
embedding_column = os.getenv("AZURE_OPENAI_EMBEDDING_COLUMN") or "embedding_3l"
4949
elif OPENAI_EMBED_HOST == "ollama":
5050
openai_embed_deployment = None
5151
openai_embed_model = os.getenv("OLLAMA_EMBED_MODEL") or "nomic-embed-text"
5252
openai_embed_dimensions = None
5353
embedding_column = os.getenv("OLLAMA_EMBEDDING_COLUMN") or "embedding_nomic"
54+
elif OPENAI_EMBED_HOST == "github":
55+
openai_embed_deployment = None
56+
openai_embed_model = os.getenv("GITHUB_EMBED_MODEL") or "text-embedding-3-large"
57+
openai_embed_dimensions = int(os.getenv("GITHUB_EMBED_DIMENSIONS", 1024))
58+
embedding_column = os.getenv("GITHUB_EMBEDDING_COLUMN") or "embedding_3l"
5459
else:
5560
openai_embed_deployment = None
56-
openai_embed_model = os.getenv("OPENAICOM_EMBED_MODEL") or "text-embedding-ada-002"
57-
openai_embed_dimensions = int(os.getenv("OPENAICOM_EMBED_DIMENSIONS", 1536))
58-
embedding_column = os.getenv("OPENAICOM_EMBEDDING_COLUMN") or "embedding_ada002"
61+
openai_embed_model = os.getenv("OPENAICOM_EMBED_MODEL") or "text-embedding-3-large"
62+
openai_embed_dimensions = int(os.getenv("OPENAICOM_EMBED_DIMENSIONS", 1024))
63+
embedding_column = os.getenv("OPENAICOM_EMBEDDING_COLUMN") or "embedding_3l"
5964
if OPENAI_CHAT_HOST == "azure":
6065
openai_chat_deployment = os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT") or "gpt-4o-mini"
6166
openai_chat_model = os.getenv("AZURE_OPENAI_CHAT_MODEL") or "gpt-4o-mini"
6267
elif OPENAI_CHAT_HOST == "ollama":
6368
openai_chat_deployment = None
6469
openai_chat_model = os.getenv("OLLAMA_CHAT_MODEL") or "phi3:3.8b"
6570
openai_embed_model = os.getenv("OLLAMA_EMBED_MODEL") or "nomic-embed-text"
71+
elif OPENAI_CHAT_HOST == "github":
72+
openai_chat_deployment = None
73+
openai_chat_model = os.getenv("GITHUB_MODEL") or "gpt-4o"
6674
else:
6775
openai_chat_deployment = None
6876
openai_chat_model = os.getenv("OPENAICOM_CHAT_MODEL") or "gpt-3.5-turbo"

src/backend/fastapi_app/openai_clients.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ async def create_openai_chat_client(
5050
base_url=os.getenv("OLLAMA_ENDPOINT"),
5151
api_key="nokeyneeded",
5252
)
53+
elif OPENAI_CHAT_HOST == "github":
54+
logger.info("Setting up OpenAI client for chat completions using GitHub Models")
55+
github_base_url = os.getenv("GITHUB_BASE_URL", "https://models.inference.ai.azure.com")
56+
github_model = os.getenv("GITHUB_MODEL", "gpt-4o")
57+
logger.info(f"Using GitHub Models with base URL: {github_base_url}, model: {github_model}")
58+
openai_chat_client = openai.AsyncOpenAI(
59+
base_url=github_base_url,
60+
api_key=os.getenv("GITHUB_TOKEN"),
61+
)
5362
else:
5463
logger.info("Setting up OpenAI client for chat completions using OpenAI.com API key")
5564
openai_chat_client = openai.AsyncOpenAI(api_key=os.getenv("OPENAICOM_KEY"))
@@ -99,6 +108,15 @@ async def create_openai_embed_client(
99108
base_url=os.getenv("OLLAMA_ENDPOINT"),
100109
api_key="nokeyneeded",
101110
)
111+
elif OPENAI_EMBED_HOST == "github":
112+
logger.info("Setting up OpenAI client for embeddings using GitHub Models")
113+
github_base_url = os.getenv("GITHUB_BASE_URL", "https://models.inference.ai.azure.com")
114+
github_embed_model = os.getenv("GITHUB_EMBED_MODEL", "text-embedding-3-small")
115+
logger.info(f"Using GitHub Models with base URL: {github_base_url}, embedding model: {github_embed_model}")
116+
openai_embed_client = openai.AsyncOpenAI(
117+
base_url=github_base_url,
118+
api_key=os.getenv("GITHUB_TOKEN"),
119+
)
102120
else:
103121
logger.info("Setting up OpenAI client for embeddings using OpenAI.com API key")
104122
openai_embed_client = openai.AsyncOpenAI(api_key=os.getenv("OPENAICOM_KEY"))

src/backend/fastapi_app/postgres_models.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ class Item(Base):
1919
description: Mapped[str] = mapped_column()
2020
price: Mapped[float] = mapped_column()
2121
# Embeddings for different models:
22-
embedding_ada002: Mapped[Vector] = mapped_column(Vector(1536), nullable=True) # ada-002
22+
embedding_3l: Mapped[Vector] = mapped_column(Vector(1024), nullable=True) # text-embedding-3-large
2323
embedding_nomic: Mapped[Vector] = mapped_column(Vector(768), nullable=True) # nomic-embed-text
2424

2525
def to_dict(self, include_embedding: bool = False):
2626
model_dict = {column.name: getattr(self, column.name) for column in self.__table__.columns}
2727
if include_embedding:
28-
model_dict["embedding_ada002"] = model_dict.get("embedding_ada002", [])
28+
model_dict["embedding_3l"] = model_dict.get("embedding_3l", [])
2929
model_dict["embedding_nomic"] = model_dict.get("embedding_nomic", [])
3030
else:
31-
del model_dict["embedding_ada002"]
31+
del model_dict["embedding_3l"]
3232
del model_dict["embedding_nomic"]
3333
return model_dict
3434

@@ -51,12 +51,12 @@ def to_str_for_embedding(self):
5151

5252
table_name = Item.__tablename__
5353

54-
index_ada002 = Index(
55-
"hnsw_index_for_cosine_{table_name}_embedding_ada002",
56-
Item.embedding_ada002,
54+
index_3l = Index(
55+
f"hnsw_index_for_cosine_{table_name}_embedding_3l",
56+
Item.embedding_3l,
5757
postgresql_using="hnsw",
5858
postgresql_with={"m": 16, "ef_construction": 64},
59-
postgresql_ops={"embedding_ada002": "vector_cosine_ops"},
59+
postgresql_ops={"embedding_3l": "vector_cosine_ops"},
6060
)
6161

6262
index_nomic = Index(

src/backend/fastapi_app/query_rewriter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def extract_search_arguments(original_user_query: str, chat_completion: ChatComp
6969
arg = json.loads(function.arguments)
7070
# Even though its required, search_query is not always specified
7171
search_query = arg.get("search_query", original_user_query)
72-
if "price_filter" in arg and arg["price_filter"]:
72+
if "price_filter" in arg and arg["price_filter"] and isinstance(arg["price_filter"], dict):
7373
price_filter = arg["price_filter"]
7474
filters.append(
7575
{
@@ -78,7 +78,7 @@ def extract_search_arguments(original_user_query: str, chat_completion: ChatComp
7878
"value": price_filter["value"],
7979
}
8080
)
81-
if "brand_filter" in arg and arg["brand_filter"]:
81+
if "brand_filter" in arg and arg["brand_filter"] and isinstance(arg["brand_filter"], dict):
8282
brand_filter = arg["brand_filter"]
8383
filters.append(
8484
{

src/backend/fastapi_app/routes/api_routes.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async def similar_handler(
6868
f"SELECT *, {context.embedding_column} <=> :embedding as DISTANCE FROM {Item.__tablename__} "
6969
"WHERE id <> :item_id ORDER BY distance LIMIT :n"
7070
),
71-
{"embedding": item.embedding_ada002, "n": n, "item_id": id},
71+
{"embedding": getattr(item, context.embedding_column), "n": n, "item_id": id},
7272
)
7373
).fetchall()
7474

@@ -145,6 +145,7 @@ async def chat_handler(
145145
if isinstance(e, APIError) and e.code == "content_filter":
146146
return ERROR_FILTER
147147
else:
148+
logging.exception("Exception while generating response: %s", e)
148149
return {"error": str(e)}
149150

150151

0 commit comments

Comments
 (0)