Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions chatkit/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,10 +690,26 @@ async def hidden_context_to_input(
) -> TResponseInputItem | list[TResponseInputItem] | None:
"""
Convert a HiddenContextItem into input item(s) to send to the model.
Required when HiddenContextItem are used.
Required to override when HiddenContextItems with non-string content are used.
"""
raise NotImplementedError(
"HiddenContextItem were present in a user message but Converter.hidden_context_to_input was not implemented"
if not isinstance(item.content, str):
raise NotImplementedError(
"HiddenContextItems with non-string content were present in a user message but a Converter.hidden_context_to_input was not implemented"
)

text = (
"Hidden context for the agent (not shown to the user):\n"
f"<HiddenContext>\n{item.content}\n</HiddenContext>"
)
Comment on lines +702 to +703
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm maybe this should just drop the auto-tags? Saw that we were doing that with <Task> in the default converter so added it here..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... mostly I wanted to get away from being too opinionated about prompt engineering, but since these are all overridable (and should probably be overwritten in even a medium complexity integration), I think maybe it's fine to have some reasonable opinions here.

return Message(
type="message",
content=[
ResponseInputTextParam(
type="input_text",
text=text,
)
],
role="user",
)

async def task_to_input(
Expand Down
68 changes: 68 additions & 0 deletions tests/test_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
ResponseContentPartAddedEvent,
)
from openai.types.responses.response_file_search_tool_call import Result
from openai.types.responses.response_input_item_param import Message
from openai.types.responses.response_output_text import (
AnnotationContainerFileCitation as ResponsesAnnotationContainerFileCitation,
)
Expand Down Expand Up @@ -77,6 +78,7 @@
CustomTask,
DurationSummary,
FileSource,
HiddenContextItem,
InferenceOptions,
Page,
TaskItem,
Expand Down Expand Up @@ -542,6 +544,72 @@ async def test_input_item_converter_user_input_with_tags_throws_by_default():
await simple_to_agent_input(items)


async def test_input_item_converter_for_hidden_context_with_string_content():
items = [
HiddenContextItem(
id="123",
content="User pressed the red button",
thread_id=thread.id,
created_at=datetime.now(),
)
]

# The default converter works for string content
items = await simple_to_agent_input(items)
assert len(items) == 1
assert items[0] == {
"content": [
{
"text": "Hidden context for the agent (not shown to the user):\n<HiddenContext>\nUser pressed the red button\n</HiddenContext>",
"type": "input_text",
},
],
"role": "user",
"type": "message",
}


async def test_input_item_converter_for_hidden_context_with_non_string_content():
items = [
HiddenContextItem(
id="123",
content={"harry": "potter", "hermione": "granger"},
thread_id=thread.id,
created_at=datetime.now(),
)
]

# Default converter should throw
with pytest.raises(NotImplementedError):
await simple_to_agent_input(items)

class MyThreadItemConverter(ThreadItemConverter):
async def hidden_context_to_input(self, item: HiddenContextItem):
content = ",".join(item.content.keys())
return Message(
type="message",
content=[
ResponseInputTextParam(
type="input_text", text=f"<HIDDEN>{content}</HIDDEN>"
)
],
role="user",
)

items = await MyThreadItemConverter().to_agent_input(items)
assert len(items) == 1
assert items[0] == {
"content": [
{
"text": "<HIDDEN>harry,hermione</HIDDEN>",
"type": "input_text",
},
],
"role": "user",
"type": "message",
}


async def test_input_item_converter_with_client_tool_call():
items = [
UserMessageItem(
Expand Down