@@ -44,14 +44,12 @@ def _get_openai_client():
4444 """Lazily initialize the Azure OpenAI client."""
4545 global _openai_client
4646 if _openai_client is None :
47- # TODO: Uncomment and configure
48- # from openai import AzureOpenAI
49- # _openai_client = AzureOpenAI(
50- # azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
51- # api_key=os.environ["AZURE_OPENAI_API_KEY"],
52- # api_version="2024-10-21",
53- # )
54- raise NotImplementedError ("Configure the Azure OpenAI client" )
47+ from openai import AzureOpenAI
48+ _openai_client = AzureOpenAI (
49+ azure_endpoint = os .environ ["AZURE_OPENAI_ENDPOINT" ],
50+ api_key = os .environ ["AZURE_OPENAI_API_KEY" ],
51+ api_version = "2024-10-21" ,
52+ )
5553 return _openai_client
5654
5755
@@ -61,14 +59,12 @@ def _get_content_safety_client():
6159 if _content_safety_client is None :
6260 # NOTE: The Content Safety SDK handles API versioning internally --
6361 # no api_version parameter is needed (unlike the OpenAI SDK).
64- # TODO: Uncomment and configure
65- # from azure.ai.contentsafety import ContentSafetyClient
66- # from azure.core.credentials import AzureKeyCredential
67- # _content_safety_client = ContentSafetyClient(
68- # endpoint=os.environ["AZURE_CONTENT_SAFETY_ENDPOINT"],
69- # credential=AzureKeyCredential(os.environ["AZURE_CONTENT_SAFETY_KEY"]),
70- # )
71- raise NotImplementedError ("Configure the Content Safety client" )
62+ from azure .ai .contentsafety import ContentSafetyClient
63+ from azure .core .credentials import AzureKeyCredential
64+ _content_safety_client = ContentSafetyClient (
65+ endpoint = os .environ ["AZURE_CONTENT_SAFETY_ENDPOINT" ],
66+ credential = AzureKeyCredential (os .environ ["AZURE_CONTENT_SAFETY_KEY" ]),
67+ )
7268 return _content_safety_client
7369
7470
@@ -78,14 +74,12 @@ def _get_language_client():
7874 if _language_client is None :
7975 # NOTE: The Language SDK handles API versioning internally --
8076 # no api_version parameter is needed (unlike the OpenAI SDK).
81- # TODO: Uncomment and configure
82- # from azure.ai.textanalytics import TextAnalyticsClient
83- # from azure.core.credentials import AzureKeyCredential
84- # _language_client = TextAnalyticsClient(
85- # endpoint=os.environ["AZURE_AI_LANGUAGE_ENDPOINT"],
86- # credential=AzureKeyCredential(os.environ["AZURE_AI_LANGUAGE_KEY"]),
87- # )
88- raise NotImplementedError ("Configure the AI Language client" )
77+ from azure .ai .textanalytics import TextAnalyticsClient
78+ from azure .core .credentials import AzureKeyCredential
79+ _language_client = TextAnalyticsClient (
80+ endpoint = os .environ ["AZURE_AI_LANGUAGE_ENDPOINT" ],
81+ credential = AzureKeyCredential (os .environ ["AZURE_AI_LANGUAGE_KEY" ]),
82+ )
8983 return _language_client
9084
9185
@@ -100,7 +94,7 @@ def classify_311_request(request_text: str) -> dict:
10094
10195 Returns:
10296 dict with keys: category, confidence, reasoning
103- """
97+
10498 # TODO: Step 1.1 - Get the OpenAI client
10599 # TODO: Step 1.2 - Call client.chat.completions.create() with:
106100 # model=os.environ.get("AZURE_OPENAI_DEPLOYMENT", "gpt-4o")
@@ -109,8 +103,29 @@ def classify_311_request(request_text: str) -> dict:
109103 # response_format={"type": "json_object"}, temperature=0
110104 # TODO: Step 1.3 - Parse the JSON response with json.loads()
111105 raise NotImplementedError("Implement classify_311_request in Step 1")
106+ """
107+ client = _get_openai_client ()
108+
109+ resp = client .chat .completions .create (
110+ model = os .environ .get ("AZURE_OPENAI_DEPLOYMENT" , "gpt-4o" ),
111+ messages = [
112+ {
113+ "role" : "system" ,
114+ "content" : (
115+ "You are an assistant for classifying Memphis 311 service requests. "
116+ "Classify the citizen's complaint into one of the following categories: "
117+ "Pothole, Noise Complaint, Trash/Litter, Street Light, Water/Sewer, Other. "
118+ "Respond with a JSON object with keys: category (one of the above), "
119+ "confidence (0-1), reasoning (brief explanation)."
120+ ),
121+ },
122+ {"role" : "user" , "content" : request_text },
123+ ],
124+ response_format = {"type" : "json_object" },
125+ temperature = 0 ,
126+ )
112127
113-
128+ return json . loads ( resp . choices [ 0 ]. message . content )
114129# ---------------------------------------------------------------------------
115130# TODO: Step 2 - Check content safety
116131# ---------------------------------------------------------------------------
@@ -124,10 +139,34 @@ def check_content_safety(text: str) -> dict:
124139 dict with keys: safe (bool), categories (dict of category: severity)
125140 """
126141 # TODO: Step 2.1 - Get the Content Safety client
142+ client = _get_content_safety_client ()
143+
127144 # TODO: Step 2.2 - Call client.analyze_text() with AnalyzeTextOptions
145+ from azure .ai .contentsafety .models import AnalyzeTextOptions
146+
147+ result = client .analyze_text (AnalyzeTextOptions (text = text ))
148+ categories : dict [str , int ] = {}
149+
150+ # Extract category severity scores from the result
151+ if hasattr (result , "categories_analysis" ) and result .categories_analysis :
152+ for category in result .categories_analysis :
153+ # The category object has 'category' (the name) and 'severity' (the score)
154+ cat_name = category .category
155+ cat_severity = category .severity
156+ categories [cat_name ] = cat_severity
157+
158+ # Determine safety: True if all categories have severity 0
159+ is_safe = all (sev == 0 for sev in categories .values ()) if categories else True
160+
128161 # TODO: Step 2.3 - Return safety results
129- raise NotImplementedError ("Implement check_content_safety in Step 2" )
130-
162+ return {
163+ "safe" : is_safe ,
164+ "categories" : categories ,
165+ }
166+ #raise NotImplementedError("Implement check_content_safety in Step 2")
167+
168+
169+
131170
132171# ---------------------------------------------------------------------------
133172# TODO: Step 3 - Extract key phrases
@@ -142,9 +181,15 @@ def extract_key_phrases(text: str) -> list[str]:
142181 List of key phrase strings.
143182 """
144183 # TODO: Step 3.1 - Get the Language client
184+ client = _get_language_client ()
185+
145186 # TODO: Step 3.2 - Call client.extract_key_phrases([text])
187+ response = client .extract_key_phrases ([text ])
188+ if response and not response [0 ].is_error :
189+ return response [0 ].key_phrases
190+ return []
146191 # TODO: Step 3.3 - Return the list of key phrases
147- raise NotImplementedError ("Implement extract_key_phrases in Step 3" )
192+ # raise NotImplementedError("Implement extract_key_phrases in Step 3")
148193
149194
150195def main ():
@@ -186,7 +231,9 @@ def main():
186231 except NotImplementedError :
187232 print ("Step 2 not implemented yet -- skipping content safety" )
188233 except Exception as e :
189- print (f"Step 2 error: { e } " )
234+ print (f"Step 2 error: { type (e ).__name__ } : { e } " )
235+ import traceback
236+ traceback .print_exc ()
190237
191238 # Step 3: Key phrase extraction
192239 key_phrases = None
0 commit comments