Skip to content

Commit c16088b

Browse files
committed
Implementation of POST v1/responses endpoint
1 parent 482ac5e commit c16088b

29 files changed

Lines changed: 9453 additions & 3521 deletions

docs/openapi.json

Lines changed: 6443 additions & 3332 deletions
Large diffs are not rendered by default.

docs/responses.md

Lines changed: 86 additions & 33 deletions
Large diffs are not rendered by default.

src/app/endpoints/conversations_v1.py

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
APIConnectionError,
88
APIStatusError,
99
)
10+
from llama_stack_client.types.conversations import ItemListResponse
1011
from sqlalchemy.exc import SQLAlchemyError
1112

1213
from app.database import get_session
@@ -45,7 +46,10 @@
4546
normalize_conversation_id,
4647
to_llama_stack_conversation_id,
4748
)
48-
from utils.conversations import build_conversation_turns_from_items
49+
from utils.conversations import (
50+
build_conversation_turns_from_items,
51+
get_all_conversation_items,
52+
)
4953
from log import get_logger
5054

5155
logger = get_logger(__name__)
@@ -225,57 +229,54 @@ async def get_conversation_endpoint_handler( # pylint: disable=too-many-locals,
225229
logger.info(
226230
"Retrieving conversation %s using Conversations API", normalized_conv_id
227231
)
228-
232+
client = AsyncLlamaStackClientHolder().get_client()
229233
try:
230-
client = AsyncLlamaStackClientHolder().get_client()
231-
232234
# Convert to llama-stack format (add 'conv_' prefix if needed)
233235
llama_stack_conv_id = to_llama_stack_conversation_id(normalized_conv_id)
234236
logger.debug(
235237
"Calling llama-stack list_items with conversation_id: %s",
236238
llama_stack_conv_id,
237239
)
238240

241+
# Retrieve turns metadata from database
242+
db_turns: list[UserTurn] = []
243+
items: list[ItemListResponse] = []
244+
245+
try:
246+
with get_session() as session:
247+
db_turns.extend(
248+
(
249+
session.query(UserTurn)
250+
.filter_by(conversation_id=normalized_conv_id)
251+
.order_by(UserTurn.turn_number)
252+
.all()
253+
)
254+
)
255+
except SQLAlchemyError as e:
256+
logger.error(
257+
"Database error occurred while retrieving conversation turns for %s.",
258+
normalized_conv_id,
259+
)
260+
response = InternalServerErrorResponse.database_error()
261+
raise HTTPException(**response.model_dump()) from e
262+
239263
# Use Conversations API to retrieve conversation items
240-
conversation_items_response = await client.conversations.items.list(
241-
conversation_id=llama_stack_conv_id,
242-
after=None,
243-
include=None,
244-
limit=None,
245-
order="asc", # oldest first
264+
conversation_items = await get_all_conversation_items(
265+
client, llama_stack_conv_id
246266
)
247-
248-
if not conversation_items_response.data:
267+
if not conversation_items:
249268
logger.error("No items found for conversation %s", conversation_id)
250269
response = NotFoundResponse(
251270
resource="conversation", resource_id=normalized_conv_id
252271
).model_dump()
253272
raise HTTPException(**response)
254273

255-
items = conversation_items_response.data
256-
274+
items.extend(conversation_items)
257275
logger.info(
258276
"Successfully retrieved %d items for conversation %s",
259277
len(items),
260278
conversation_id,
261279
)
262-
# Retrieve turns metadata from database
263-
db_turns: list[UserTurn] = []
264-
try:
265-
with get_session() as session:
266-
db_turns = (
267-
session.query(UserTurn)
268-
.filter_by(conversation_id=normalized_conv_id)
269-
.order_by(UserTurn.turn_number)
270-
.all()
271-
)
272-
except SQLAlchemyError as e:
273-
logger.error(
274-
"Database error occurred while retrieving conversation turns for %s.",
275-
normalized_conv_id,
276-
)
277-
response = InternalServerErrorResponse.database_error()
278-
raise HTTPException(**response.model_dump()) from e
279280

280281
# Build conversation turns from items and populate turns metadata
281282
# Use conversation.created_at for legacy conversations without turn metadata
@@ -284,8 +285,7 @@ async def get_conversation_endpoint_handler( # pylint: disable=too-many-locals,
284285
)
285286

286287
return ConversationResponse(
287-
conversation_id=normalized_conv_id,
288-
chat_history=chat_history,
288+
conversation_id=normalized_conv_id, chat_history=chat_history
289289
)
290290

291291
except APIConnectionError as e:

src/app/endpoints/query.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# pylint: disable=too-many-locals,too-many-branches,too-many-nested-blocks
2-
31
"""Handler for REST API call to provide answer to query using Response API."""
42

53
import datetime
@@ -264,7 +262,7 @@ async def query_endpoint_handler(
264262
)
265263

266264

267-
async def retrieve_response( # pylint: disable=too-many-locals
265+
async def retrieve_response(
268266
client: AsyncLlamaStackClient,
269267
responses_params: ResponsesApiParams,
270268
moderation_result: ShieldModerationResult,
@@ -291,7 +289,9 @@ async def retrieve_response( # pylint: disable=too-many-locals
291289
responses_params.input,
292290
[moderation_result.refusal_response],
293291
)
294-
return TurnSummary(llm_response=moderation_result.message)
292+
return TurnSummary(
293+
id=moderation_result.moderation_id, llm_response=moderation_result.message
294+
)
295295
try:
296296
response = await client.responses.create(
297297
**responses_params.model_dump(exclude_none=True)

0 commit comments

Comments
 (0)