feat: add tags to feedback endpoint (#2881)

This commit is contained in:
cthomas
2025-09-14 17:23:50 -07:00
committed by GitHub
parent 48e50b957e
commit 05c2b4ffd3
3 changed files with 10 additions and 3 deletions

View File

@@ -116,12 +116,13 @@ async def retrieve_step_trace(
class AddFeedbackRequest(BaseModel):
feedback: FeedbackType | None = Field(None, description="Whether this feedback is positive or negative")
tags: list[str] | None = Field(None, description="Feedback tags to add to the step")
@router.patch("/{step_id}/feedback", response_model=Step, operation_id="add_feedback")
async def add_feedback(
step_id: str,
feedback: AddFeedbackRequest = Body(...),
request: AddFeedbackRequest = Body(...),
actor_id: Optional[str] = Header(None, alias="user_id"),
server: SyncServer = Depends(get_letta_server),
):
@@ -130,7 +131,7 @@ async def add_feedback(
"""
try:
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
return await server.step_manager.add_feedback_async(step_id=step_id, feedback=feedback, actor=actor)
return await server.step_manager.add_feedback_async(step_id=step_id, feedback=request.feedback, tags=request.tags, actor=actor)
except NoResultFound:
raise HTTPException(status_code=404, detail="Step not found")

View File

@@ -197,12 +197,16 @@ class StepManager:
@enforce_types
@trace_method
async def add_feedback_async(self, step_id: str, feedback: Optional[FeedbackType], actor: PydanticUser) -> PydanticStep:
async def add_feedback_async(
self, step_id: str, feedback: FeedbackType | None, actor: PydanticUser, tags: list[str] | None = None
) -> PydanticStep:
async with db_registry.async_session() as session:
step = await StepModel.read_async(db_session=session, identifier=step_id, actor=actor)
if not step:
raise NoResultFound(f"Step with id {step_id} does not exist")
step.feedback = feedback
if tags:
step.tags = tags
step = await step.update_async(session)
return step.to_pydantic()

View File

@@ -536,6 +536,8 @@ def enforce_types(func):
if origin is Union: # Handle Union types (including Optional)
return any(matches_type(value, arg) for arg in args)
elif hasattr(hint, "__class__") and hint.__class__.__name__ == "UnionType": # Handle Python 3.10+ X | Y syntax
return any(matches_type(value, arg) for arg in args)
elif origin is list and isinstance(value, list): # Handle List[T]
element_type = args[0] if args else None
return all(isinstance(v, element_type) for v in value) if element_type else True