Skip to content

Commit 9871f97

Browse files
committed
Test updates
1 parent 62502b1 commit 9871f97

File tree

7 files changed

+257
-70
lines changed

7 files changed

+257
-70
lines changed

src/backend/fastapi_app/__init__.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,17 @@ def create_app(testing: bool = False):
5858
else:
5959
if not testing:
6060
load_dotenv(override=True)
61-
logging.basicConfig(level=logging.INFO)
62-
# Turn off particularly noisy INFO level logs from Azure Core SDK:
63-
logging.getLogger("azure.core.pipeline.policies.http_logging_policy").setLevel(logging.WARNING)
64-
logging.getLogger("azure.identity").setLevel(logging.WARNING)
61+
logging.basicConfig(level=logging.DEBUG)
62+
63+
# Enable detailed HTTP traffic logging
64+
logging.getLogger("httpx").setLevel(logging.DEBUG)
65+
logging.getLogger("azure.core.pipeline.policies.http_logging_policy").setLevel(logging.DEBUG)
66+
logging.getLogger("azure.identity").setLevel(logging.DEBUG)
67+
logging.getLogger("urllib3").setLevel(logging.DEBUG)
68+
69+
# Configure httpx logging to show full bodies
70+
os.environ["HTTPX_LOG_LEVEL"] = "DEBUG"
71+
os.environ["HTTPCORE_LOG_LEVEL"] = "DEBUG"
6572

6673
if os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING"):
6774
logger.info("Configuring Azure Monitor")

src/backend/fastapi_app/routes/api_routes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import http.client
12
import json
23
import logging
34
from collections.abc import AsyncGenerator
@@ -26,6 +27,8 @@
2627
router = fastapi.APIRouter()
2728

2829

30+
http.client.HTTPConnection.debuglevel = 1
31+
2932
ERROR_FILTER = {"error": "Your message contains content that was flagged by the content filter."}
3033

3134

tests/conftest.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
ChatCompletionMessage,
1414
Choice,
1515
)
16+
from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall, Function
1617
from openai.types.create_embedding_response import Usage
1718
from sqlalchemy.ext.asyncio import async_sessionmaker
1819

@@ -232,6 +233,12 @@ def __init__(self, answer: str):
232233
}
233234
)
234235

236+
async def __aenter__(self):
237+
return self
238+
239+
async def __aexit__(self, exc_type, exc_val, exc_tb):
240+
return None
241+
235242
def __aiter__(self):
236243
return self
237244

@@ -244,9 +251,59 @@ async def __anext__(self):
244251
async def mock_acreate(*args, **kwargs):
245252
messages = kwargs["messages"]
246253
last_question = messages[-1]["content"]
247-
if last_question == "Generate search query for: What is the capital of France?":
248-
answer = "capital of France"
249-
elif last_question == "Generate search query for: Are interest rates high?":
254+
last_role = messages[-1]["role"]
255+
if last_role == "tool":
256+
return ChatCompletion(
257+
object="chat.completion",
258+
choices=[
259+
Choice(
260+
message=ChatCompletionMessage(
261+
role="assistant",
262+
tool_calls=[
263+
ChatCompletionMessageToolCall(
264+
id="call_abc123final",
265+
type="function",
266+
function=Function(
267+
name="final_result",
268+
arguments='{"query":"capital of France", "items":[], "filters":[]}',
269+
),
270+
)
271+
],
272+
),
273+
finish_reason="stop",
274+
index=0,
275+
)
276+
],
277+
id="test-123final",
278+
created=0,
279+
model="test-model",
280+
)
281+
if last_question == "Find search results for user query: What is the capital of France?":
282+
return ChatCompletion(
283+
object="chat.completion",
284+
choices=[
285+
Choice(
286+
message=ChatCompletionMessage(
287+
role="assistant",
288+
tool_calls=[
289+
ChatCompletionMessageToolCall(
290+
id="call_abc123",
291+
type="function",
292+
function=Function(
293+
name="search_database", arguments='{"search_query":"climbing gear outside"}'
294+
),
295+
)
296+
],
297+
),
298+
finish_reason="stop",
299+
index=0,
300+
)
301+
],
302+
id="test-123",
303+
created=0,
304+
model="test-model",
305+
)
306+
elif last_question == "Find search results for user query: Are interest rates high?":
250307
answer = "interest rates"
251308
elif isinstance(last_question, list) and last_question[2].get("image_url"):
252309
answer = "From the provided sources, the impact of interest rates and GDP growth on "

tests/snapshots/test_api_routes/test_advanced_chat_flow/advanced_chat_flow_response.json

Lines changed: 157 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,71 +4,160 @@
44
"role": "assistant"
55
},
66
"context": {
7-
"data_points": {
8-
"1": {
9-
"id": 1,
10-
"type": "Footwear",
11-
"brand": "Daybird",
12-
"name": "Wanderer Black Hiking Boots",
13-
"description": "Daybird's Wanderer Hiking Boots in sleek black are perfect for all your outdoor adventures. These boots are made with a waterproof leather upper and a durable rubber sole for superior traction. With their cushioned insole and padded collar, these boots will keep you comfortable all day long.",
14-
"price": 109.99
15-
}
16-
},
7+
"data_points": {},
178
"thoughts": [
189
{
1910
"title": "Prompt to generate search arguments",
2011
"description": [
2112
{
22-
"role": "system",
23-
"content": "Below is a history of the conversation so far, and a new question asked by the user that needs to be answered by searching database rows.\nYou have access to an Azure PostgreSQL database with an items table that has columns for title, description, brand, price, and type.\nGenerate a search query based on the conversation and the new question.\nIf the question is not in English, translate the question to English before generating the search query.\nIf you cannot generate a search query, return the original user question.\nDO NOT return anything besides the query.\n"
13+
"parts": [
14+
{
15+
"content": "good options for climbing gear that can be used outside?",
16+
"timestamp": "2025-05-07T19:02:46.977501Z",
17+
"part_kind": "user-prompt"
18+
}
19+
],
20+
"instructions": null,
21+
"kind": "request"
2422
},
2523
{
26-
"role": "user",
27-
"content": "good options for climbing gear that can be used outside?"
24+
"parts": [
25+
{
26+
"tool_name": "search_database",
27+
"args": "{\"search_query\":\"climbing gear outside\"}",
28+
"tool_call_id": "call_4HeBCmo2uioV6CyoePEGyZPc",
29+
"part_kind": "tool-call"
30+
}
31+
],
32+
"model_name": "gpt-4o-mini-2024-07-18",
33+
"timestamp": "2025-05-07T19:02:47Z",
34+
"kind": "response"
35+
},
36+
{
37+
"parts": [
38+
{
39+
"tool_name": "search_database",
40+
"content": "Search results for climbing gear that can be used outside: ...",
41+
"tool_call_id": "call_4HeBCmo2uioV6CyoePEGyZPc",
42+
"timestamp": "2025-05-07T19:02:48.242408Z",
43+
"part_kind": "tool-return"
44+
}
45+
],
46+
"instructions": null,
47+
"kind": "request"
48+
},
49+
{
50+
"parts": [
51+
{
52+
"content": "are there any shoes less than $50?",
53+
"timestamp": "2025-05-07T19:02:46.977501Z",
54+
"part_kind": "user-prompt"
55+
}
56+
],
57+
"instructions": null,
58+
"kind": "request"
59+
},
60+
{
61+
"parts": [
62+
{
63+
"tool_name": "search_database",
64+
"args": "{\"search_query\":\"shoes\",\"price_filter\":{\"comparison_operator\":\"<\",\"value\":50}}",
65+
"tool_call_id": "call_4HeBCmo2uioV6CyoePEGyZPc",
66+
"part_kind": "tool-call"
67+
}
68+
],
69+
"model_name": "gpt-4o-mini-2024-07-18",
70+
"timestamp": "2025-05-07T19:02:47Z",
71+
"kind": "response"
2872
},
2973
{
30-
"role": "assistant",
31-
"tool_calls": [
74+
"parts": [
3275
{
33-
"id": "call_abc123",
34-
"type": "function",
35-
"function": {
36-
"arguments": "{\"search_query\":\"climbing gear outside\"}",
37-
"name": "search_database"
38-
}
76+
"tool_name": "search_database",
77+
"content": "Search results for shoes cheaper than 50: ...",
78+
"tool_call_id": "call_4HeBCmo2uioV6CyoePEGyZPc",
79+
"timestamp": "2025-05-07T19:02:48.242408Z",
80+
"part_kind": "tool-return"
3981
}
40-
]
82+
],
83+
"instructions": null,
84+
"kind": "request"
4185
},
4286
{
43-
"role": "tool",
44-
"tool_call_id": "call_abc123",
45-
"content": "Search results for climbing gear that can be used outside: ..."
87+
"parts": [
88+
{
89+
"content": "Find search results for user query: What is the capital of France?",
90+
"timestamp": "2025-05-07T22:31:16.169127Z",
91+
"part_kind": "user-prompt"
92+
}
93+
],
94+
"instructions": null,
95+
"kind": "request"
4696
},
4797
{
48-
"role": "user",
49-
"content": "are there any shoes less than $50?"
98+
"parts": [
99+
{
100+
"tool_name": "search_database",
101+
"args": "{\"search_query\":\"climbing gear outside\"}",
102+
"tool_call_id": "call_abc123",
103+
"part_kind": "tool-call"
104+
}
105+
],
106+
"model_name": "test-model",
107+
"timestamp": "1970-01-01T00:00:00Z",
108+
"kind": "response"
50109
},
51110
{
52-
"role": "assistant",
53-
"tool_calls": [
111+
"parts": [
54112
{
55-
"id": "call_abc456",
56-
"type": "function",
57-
"function": {
58-
"arguments": "{\"search_query\":\"shoes\",\"price_filter\":{\"comparison_operator\":\"<\",\"value\":50}}",
59-
"name": "search_database"
60-
}
113+
"tool_name": "search_database",
114+
"content": {
115+
"query": "climbing gear outside",
116+
"items": [
117+
{
118+
"id": 1,
119+
"type": "Footwear",
120+
"brand": "Daybird",
121+
"name": "Wanderer Black Hiking Boots",
122+
"description": "Daybird's Wanderer Hiking Boots in sleek black are perfect for all your outdoor adventures. These boots are made with a waterproof leather upper and a durable rubber sole for superior traction. With their cushioned insole and padded collar, these boots will keep you comfortable all day long.",
123+
"price": 109.99
124+
}
125+
],
126+
"filters": []
127+
},
128+
"tool_call_id": "call_abc123",
129+
"timestamp": "2025-05-07T22:31:16.187780Z",
130+
"part_kind": "tool-return"
61131
}
62-
]
132+
],
133+
"instructions": null,
134+
"kind": "request"
63135
},
64136
{
65-
"role": "tool",
66-
"tool_call_id": "call_abc456",
67-
"content": "Search results for shoes cheaper than 50: ..."
137+
"parts": [
138+
{
139+
"tool_name": "final_result",
140+
"args": "{\"query\":\"capital of France\", \"items\":[], \"filters\":[]}",
141+
"tool_call_id": "call_abc123final",
142+
"part_kind": "tool-call"
143+
}
144+
],
145+
"model_name": "test-model",
146+
"timestamp": "1970-01-01T00:00:00Z",
147+
"kind": "response"
68148
},
69149
{
70-
"role": "user",
71-
"content": "What is the capital of France?"
150+
"parts": [
151+
{
152+
"tool_name": "final_result",
153+
"content": "Final result processed.",
154+
"tool_call_id": "call_abc123final",
155+
"timestamp": "2025-05-07T22:31:16.188322Z",
156+
"part_kind": "tool-return"
157+
}
158+
],
159+
"instructions": null,
160+
"kind": "request"
72161
}
73162
],
74163
"props": {
@@ -78,7 +167,7 @@
78167
},
79168
{
80169
"title": "Search using generated search arguments",
81-
"description": "The capital of France is Paris. [Benefit_Options-2.pdf].",
170+
"description": "capital of France",
82171
"props": {
83172
"top": 1,
84173
"vector_search": true,
@@ -88,28 +177,39 @@
88177
},
89178
{
90179
"title": "Search results",
91-
"description": [
92-
{
93-
"id": 1,
94-
"type": "Footwear",
95-
"brand": "Daybird",
96-
"name": "Wanderer Black Hiking Boots",
97-
"description": "Daybird's Wanderer Hiking Boots in sleek black are perfect for all your outdoor adventures. These boots are made with a waterproof leather upper and a durable rubber sole for superior traction. With their cushioned insole and padded collar, these boots will keep you comfortable all day long.",
98-
"price": 109.99
99-
}
100-
],
180+
"description": [],
101181
"props": {}
102182
},
103183
{
104184
"title": "Prompt to generate answer",
105185
"description": [
106186
{
107-
"role": "system",
108-
"content": "Assistant helps customers with questions about products.\nRespond as if you are a salesperson helping a customer in a store. Do NOT respond with tables.\nAnswer ONLY with the product details listed in the products.\nIf there isn't enough information below, say you don't know.\nDo not generate answers that don't use the sources below.\nEach product has an ID in brackets followed by colon and the product details.\nAlways include the product ID for each product you use in the response.\nUse square brackets to reference the source, for example [52].\nDon't combine citations, list each product separately, for example [27][51]."
187+
"parts": [
188+
{
189+
"content": "Assistant helps customers with questions about products.\nRespond as if you are a salesperson helping a customer in a store. Do NOT respond with tables.\nAnswer ONLY with the product details listed in the products.\nIf there isn't enough information below, say you don't know.\nDo not generate answers that don't use the sources below.\nEach product has an ID in brackets followed by colon and the product details.\nAlways include the product ID for each product you use in the response.\nUse square brackets to reference the source, for example [52].\nDon't combine citations, list each product separately, for example [27][51].",
190+
"timestamp": "2025-05-07T22:31:16.188611Z",
191+
"dynamic_ref": null,
192+
"part_kind": "system-prompt"
193+
},
194+
{
195+
"content": "What is the capital of France?Sources:\n",
196+
"timestamp": "2025-05-07T22:31:16.188613Z",
197+
"part_kind": "user-prompt"
198+
}
199+
],
200+
"instructions": null,
201+
"kind": "request"
109202
},
110203
{
111-
"role": "user",
112-
"content": "What is the capital of France?\n\nSources:\n[1]:Name:Wanderer Black Hiking Boots Description:Daybird's Wanderer Hiking Boots in sleek black are perfect for all your outdoor adventures. These boots are made with a waterproof leather upper and a durable rubber sole for superior traction. With their cushioned insole and padded collar, these boots will keep you comfortable all day long. Price:109.99 Brand:Daybird Type:Footwear\n\n"
204+
"parts": [
205+
{
206+
"content": "The capital of France is Paris. [Benefit_Options-2.pdf].",
207+
"part_kind": "text"
208+
}
209+
],
210+
"model_name": "test-model",
211+
"timestamp": "1970-01-01T00:00:00Z",
212+
"kind": "response"
113213
}
114214
],
115215
"props": {

0 commit comments

Comments
 (0)