Skip to content

Commit 64a3484

Browse files
committed
Bring back optional
1 parent a594f3f commit 64a3484

26 files changed

+209
-318
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ repos:
77
- id: end-of-file-fixer
88
- id: trailing-whitespace
99
- repo: https://github.com/astral-sh/ruff-pre-commit
10-
rev: v0.9.3
10+
rev: v0.14.2
1111
hooks:
1212
- id: ruff
1313
- repo: https://github.com/psf/black

app/backend/approaches/approach.py

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from abc import ABC
33
from collections.abc import AsyncGenerator, Awaitable
44
from dataclasses import dataclass, field
5-
from typing import Any, TypedDict, cast
5+
from typing import Any, Optional, TypedDict, cast
66

77
from azure.search.documents.agent.aio import KnowledgeAgentRetrievalClient
88
from azure.search.documents.agent.models import (
@@ -38,18 +38,18 @@
3838

3939
@dataclass
4040
class Document:
41-
id: str | None = None
42-
content: str | None = None
43-
category: str | None = None
44-
sourcepage: str | None = None
45-
sourcefile: str | None = None
46-
oids: list[str] | None = None
47-
groups: list[str] | None = None
48-
captions: list[QueryCaptionResult] | None = None
49-
score: float | None = None
50-
reranker_score: float | None = None
51-
search_agent_query: str | None = None
52-
images: list[dict[str, Any]] | None = None
41+
id: Optional[str] = None
42+
content: Optional[str] = None
43+
category: Optional[str] = None
44+
sourcepage: Optional[str] = None
45+
sourcefile: Optional[str] = None
46+
oids: Optional[list[str]] = None
47+
groups: Optional[list[str]] = None
48+
captions: Optional[list[QueryCaptionResult]] = None
49+
score: Optional[float] = None
50+
reranker_score: Optional[float] = None
51+
search_agent_query: Optional[str] = None
52+
images: Optional[list[dict[str, Any]]] = None
5353

5454
def serialize_for_results(self) -> dict[str, Any]:
5555
result_dict = {
@@ -83,8 +83,8 @@ def serialize_for_results(self) -> dict[str, Any]:
8383
@dataclass
8484
class ThoughtStep:
8585
title: str
86-
description: Any | None
87-
props: dict[str, Any] | None = None
86+
description: Optional[Any]
87+
props: Optional[dict[str, Any]] = None
8888

8989
def update_token_usage(self, usage: CompletionUsage) -> None:
9090
if self.props:
@@ -93,23 +93,23 @@ def update_token_usage(self, usage: CompletionUsage) -> None:
9393

9494
@dataclass
9595
class DataPoints:
96-
text: list[str] | None = None
97-
images: list | None = None
98-
citations: list[str] | None = None
96+
text: Optional[list[str]] = None
97+
images: Optional[list] = None
98+
citations: Optional[list[str]] = None
9999

100100

101101
@dataclass
102102
class ExtraInfo:
103103
data_points: DataPoints
104104
thoughts: list[ThoughtStep] = field(default_factory=list)
105-
followup_questions: list[Any] | None = None
105+
followup_questions: Optional[list[Any]] = None
106106

107107

108108
@dataclass
109109
class TokenUsageProps:
110110
prompt_tokens: int
111111
completion_tokens: int
112-
reasoning_tokens: int | None
112+
reasoning_tokens: Optional[int]
113113
total_tokens: int
114114

115115
@classmethod
@@ -151,19 +151,19 @@ def __init__(
151151
self,
152152
search_client: SearchClient,
153153
openai_client: AsyncOpenAI,
154-
query_language: str | None,
155-
query_speller: str | None,
156-
embedding_deployment: str | None, # Not needed for non-Azure OpenAI or for retrieval_mode="text"
154+
query_language: Optional[str],
155+
query_speller: Optional[str],
156+
embedding_deployment: Optional[str], # Not needed for non-Azure OpenAI or for retrieval_mode="text"
157157
embedding_model: str,
158158
embedding_dimensions: int,
159159
embedding_field: str,
160160
openai_host: str,
161161
prompt_manager: PromptManager,
162-
reasoning_effort: str | None = None,
162+
reasoning_effort: Optional[str] = None,
163163
multimodal_enabled: bool = False,
164-
image_embeddings_client: ImageEmbeddings | None = None,
165-
global_blob_manager: BlobManager | None = None,
166-
user_blob_manager: AdlsBlobManager | None = None,
164+
image_embeddings_client: Optional[ImageEmbeddings] = None,
165+
global_blob_manager: Optional[BlobManager] = None,
166+
user_blob_manager: Optional[AdlsBlobManager] = None,
167167
):
168168
self.search_client = search_client
169169
self.openai_client = openai_client
@@ -182,30 +182,30 @@ def __init__(
182182
self.global_blob_manager = global_blob_manager
183183
self.user_blob_manager = user_blob_manager
184184

185-
def build_filter(self, overrides: dict[str, Any]) -> str | None:
185+
def build_filter(self, overrides: dict[str, Any]) -> Optional[str]:
186186
include_category = overrides.get("include_category")
187187
exclude_category = overrides.get("exclude_category")
188188
filters = []
189189
if include_category:
190190
filters.append("category eq '{}'".format(include_category.replace("'", "''")))
191191
if exclude_category:
192192
filters.append("category ne '{}'".format(exclude_category.replace("'", "''")))
193-
return None if len(filters) == 0 else " and ".join(filters)
193+
return None if not filters else " and ".join(filters)
194194

195195
async def search(
196196
self,
197197
top: int,
198-
query_text: str | None,
199-
filter: str | None,
198+
query_text: Optional[str],
199+
filter: Optional[str],
200200
vectors: list[VectorQuery],
201201
use_text_search: bool,
202202
use_vector_search: bool,
203203
use_semantic_ranker: bool,
204204
use_semantic_captions: bool,
205-
minimum_search_score: float | None = None,
206-
minimum_reranker_score: float | None = None,
207-
use_query_rewriting: bool | None = None,
208-
access_token: str | None = None,
205+
minimum_search_score: Optional[float] = None,
206+
minimum_reranker_score: Optional[float] = None,
207+
use_query_rewriting: Optional[bool] = None,
208+
access_token: Optional[str] = None,
209209
) -> list[Document]:
210210
search_text = query_text if use_text_search else ""
211211
search_vectors = vectors if use_vector_search else []
@@ -268,11 +268,11 @@ async def run_agentic_retrieval(
268268
messages: list[ChatCompletionMessageParam],
269269
agent_client: KnowledgeAgentRetrievalClient,
270270
search_index_name: str,
271-
top: int | None = None,
272-
filter_add_on: str | None = None,
273-
minimum_reranker_score: float | None = None,
274-
results_merge_strategy: str | None = None,
275-
access_token: str | None = None,
271+
top: Optional[int] = None,
272+
filter_add_on: Optional[str] = None,
273+
minimum_reranker_score: Optional[float] = None,
274+
results_merge_strategy: Optional[str] = None,
275+
access_token: Optional[str] = None,
276276
) -> tuple[KnowledgeAgentRetrievalResponse, list[Document]]:
277277
# STEP 1: Invoke agentic retrieval
278278
response = await agent_client.retrieve(
@@ -357,7 +357,7 @@ async def get_sources_content(
357357
use_semantic_captions: bool,
358358
include_text_sources: bool,
359359
download_image_sources: bool,
360-
user_oid: str | None = None,
360+
user_oid: Optional[str] = None,
361361
) -> DataPoints:
362362
"""Extract text/image sources & citations from documents.
363363
@@ -407,15 +407,15 @@ def clean_source(s: str) -> str:
407407
citations.append(self.get_image_citation(doc.sourcepage or "", img["url"]))
408408
return DataPoints(text=text_sources, images=image_sources, citations=citations)
409409

410-
def get_citation(self, sourcepage: str | None):
410+
def get_citation(self, sourcepage: Optional[str]):
411411
return sourcepage or ""
412412

413-
def get_image_citation(self, sourcepage: str | None, image_url: str):
413+
def get_image_citation(self, sourcepage: Optional[str], image_url: str):
414414
sourcepage_citation = self.get_citation(sourcepage)
415415
image_filename = image_url.split("/")[-1]
416416
return f"{sourcepage_citation}({image_filename})"
417417

418-
async def download_blob_as_base64(self, blob_url: str, user_oid: str | None = None) -> str | None:
418+
async def download_blob_as_base64(self, blob_url: str, user_oid: Optional[str] = None) -> Optional[str]:
419419
"""
420420
Downloads a blob from either Azure Blob Storage or Azure Data Lake Storage and returns it as a base64 encoded string.
421421
@@ -483,7 +483,7 @@ async def compute_multimodal_embedding(self, q: str):
483483
multimodal_query_vector = await self.image_embeddings_client.create_embedding_for_text(q)
484484
return VectorizedQuery(vector=multimodal_query_vector, k_nearest_neighbors=50, fields="images/embedding")
485485

486-
def get_system_prompt_variables(self, override_prompt: str | None) -> dict[str, str]:
486+
def get_system_prompt_variables(self, override_prompt: Optional[str]) -> dict[str, str]:
487487
# Allows client to replace the entire prompt, or to inject into the existing prompt using >>>
488488
if override_prompt is None:
489489
return {}
@@ -510,16 +510,16 @@ def get_lowest_reasoning_effort(self, model: str) -> ChatCompletionReasoningEffo
510510

511511
def create_chat_completion(
512512
self,
513-
chatgpt_deployment: str | None,
513+
chatgpt_deployment: Optional[str],
514514
chatgpt_model: str,
515515
messages: list[ChatCompletionMessageParam],
516516
overrides: dict[str, Any],
517517
response_token_limit: int,
518518
should_stream: bool = False,
519-
tools: list[ChatCompletionToolParam] | None = None,
520-
temperature: float | None = None,
521-
n: int | None = None,
522-
reasoning_effort: ChatCompletionReasoningEffort | None = None,
519+
tools: Optional[list[ChatCompletionToolParam]] = None,
520+
temperature: Optional[float] = None,
521+
n: Optional[int] = None,
522+
reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
523523
) -> Awaitable[ChatCompletion] | Awaitable[AsyncStream[ChatCompletionChunk]]:
524524
if chatgpt_model in self.GPT_REASONING_MODELS:
525525
params: dict[str, Any] = {
@@ -561,9 +561,9 @@ def format_thought_step_for_chatcompletion(
561561
messages: list[ChatCompletionMessageParam],
562562
overrides: dict[str, Any],
563563
model: str,
564-
deployment: str | None,
565-
usage: CompletionUsage | None = None,
566-
reasoning_effort: ChatCompletionReasoningEffort | None = None,
564+
deployment: Optional[str],
565+
usage: Optional[CompletionUsage] = None,
566+
reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
567567
) -> ThoughtStep:
568568
properties: dict[str, Any] = {"model": model}
569569
if deployment:

app/backend/approaches/chatreadretrieveread.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
import re
33
from collections.abc import AsyncGenerator, Awaitable
4-
from typing import Any, cast
4+
from typing import Any, Optional, cast
55

66
from azure.search.documents.agent.aio import KnowledgeAgentRetrievalClient
77
from azure.search.documents.aio import SearchClient
@@ -38,13 +38,13 @@ def __init__(
3838
*,
3939
search_client: SearchClient,
4040
search_index_name: str,
41-
agent_model: str | None,
42-
agent_deployment: str | None,
41+
agent_model: Optional[str],
42+
agent_deployment: Optional[str],
4343
agent_client: KnowledgeAgentRetrievalClient,
4444
openai_client: AsyncOpenAI,
4545
chatgpt_model: str,
46-
chatgpt_deployment: str | None, # Not needed for non-Azure OpenAI
47-
embedding_deployment: str | None, # Not needed for non-Azure OpenAI or for retrieval_mode="text"
46+
chatgpt_deployment: Optional[str], # Not needed for non-Azure OpenAI
47+
embedding_deployment: Optional[str], # Not needed for non-Azure OpenAI or for retrieval_mode="text"
4848
embedding_model: str,
4949
embedding_dimensions: int,
5050
embedding_field: str,
@@ -53,11 +53,11 @@ def __init__(
5353
query_language: str,
5454
query_speller: str,
5555
prompt_manager: PromptManager,
56-
reasoning_effort: str | None = None,
56+
reasoning_effort: Optional[str] = None,
5757
multimodal_enabled: bool = False,
58-
image_embeddings_client: ImageEmbeddings | None = None,
59-
global_blob_manager: BlobManager | None = None,
60-
user_blob_manager: AdlsBlobManager | None = None,
58+
image_embeddings_client: Optional[ImageEmbeddings] = None,
59+
global_blob_manager: Optional[BlobManager] = None,
60+
user_blob_manager: Optional[AdlsBlobManager] = None,
6161
):
6262
self.search_client = search_client
6363
self.search_index_name = search_index_name
@@ -104,7 +104,7 @@ def get_search_query(self, chat_completion: ChatCompletion, user_query: str):
104104
return query_text
105105
return user_query
106106

107-
def extract_followup_questions(self, content: str | None):
107+
def extract_followup_questions(self, content: Optional[str]):
108108
if content is None:
109109
return content, []
110110
return content.split("<<")[0], re.findall(r"<<([^>>]+)>>", content)

app/backend/approaches/retrievethenread.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, cast
1+
from typing import Any, Optional, cast
22

33
from azure.search.documents.agent.aio import KnowledgeAgentRetrievalClient
44
from azure.search.documents.aio import SearchClient
@@ -28,26 +28,26 @@ def __init__(
2828
*,
2929
search_client: SearchClient,
3030
search_index_name: str,
31-
agent_model: str | None,
32-
agent_deployment: str | None,
31+
agent_model: Optional[str],
32+
agent_deployment: Optional[str],
3333
agent_client: KnowledgeAgentRetrievalClient,
3434
openai_client: AsyncOpenAI,
3535
chatgpt_model: str,
36-
chatgpt_deployment: str | None, # Not needed for non-Azure OpenAI
36+
chatgpt_deployment: Optional[str], # Not needed for non-Azure OpenAI
3737
embedding_model: str,
38-
embedding_deployment: str | None, # Not needed for non-Azure OpenAI or for retrieval_mode="text"
38+
embedding_deployment: Optional[str], # Not needed for non-Azure OpenAI or for retrieval_mode="text"
3939
embedding_dimensions: int,
4040
embedding_field: str,
4141
sourcepage_field: str,
4242
content_field: str,
4343
query_language: str,
4444
query_speller: str,
4545
prompt_manager: PromptManager,
46-
reasoning_effort: str | None = None,
46+
reasoning_effort: Optional[str] = None,
4747
multimodal_enabled: bool = False,
48-
image_embeddings_client: ImageEmbeddings | None = None,
49-
global_blob_manager: BlobManager | None = None,
50-
user_blob_manager: AdlsBlobManager | None = None,
48+
image_embeddings_client: Optional[ImageEmbeddings] = None,
49+
global_blob_manager: Optional[BlobManager] = None,
50+
user_blob_manager: Optional[AdlsBlobManager] = None,
5151
):
5252
self.search_client = search_client
5353
self.search_index_name = search_index_name

app/backend/core/authentication.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import base64
44
import json
55
import logging
6-
from typing import Any
6+
from typing import Any, Optional
77

88
import aiohttp
99
import jwt
@@ -36,12 +36,12 @@ class AuthenticationHelper:
3636

3737
def __init__(
3838
self,
39-
search_index: SearchIndex | None,
39+
search_index: Optional[SearchIndex],
4040
use_authentication: bool,
41-
server_app_id: str | None,
42-
server_app_secret: str | None,
43-
client_app_id: str | None,
44-
tenant_id: str | None,
41+
server_app_id: Optional[str],
42+
server_app_secret: Optional[str],
43+
client_app_id: Optional[str],
44+
tenant_id: Optional[str],
4545
enforce_access_control: bool = False,
4646
enable_unauthenticated_access: bool = False,
4747
):

app/backend/core/sessionhelper.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import uuid
2+
from typing import Optional
23

34

45
def create_session_id(
56
config_chat_history_cosmos_enabled: bool, config_chat_history_browser_enabled: bool
6-
) -> str | None:
7+
) -> Optional[str]:
78
if config_chat_history_cosmos_enabled:
89
return str(uuid.uuid4())
910
if config_chat_history_browser_enabled:

0 commit comments

Comments
 (0)