openai/chatkit-python
Publicmirrored from https://github.com/openai/chatkit-pythonAvailable
docs/guides/convert-user-input.md
89lines · modecode
| 1 | # Convert user input to model input |
| 2 | |
| 3 | ChatKit delivers structured thread items (messages, tools, attachments). Before running inference, convert those items into the model's expected input format. |
| 4 | |
| 5 | ## Load recent thread items |
| 6 | |
| 7 | Make the agent aware of recent context before converting input. Load recent thread items and pass them along with the new message so the model sees the conversation state. |
| 8 | |
| 9 | ```python |
| 10 | # Inside ChatKitServer.respond(...) |
| 11 | items_page = await self.store.load_thread_items( |
| 12 | thread.id, |
| 13 | after=None, |
| 14 | limit=20, |
| 15 | order="desc", |
| 16 | context=context, |
| 17 | ) |
| 18 | items = list(reversed(items_page.data)) |
| 19 | ``` |
| 20 | |
| 21 | ## Use default conversion helpers |
| 22 | |
| 23 | Start with the defaults: `simple_to_agent_input` converts a `UserMessageItem` into Agents SDK inputs, and `ThreadItemConverter` lets you override specific conversions when you need more control. Combine the converted user input with the `items` you loaded above to send the model both the latest message and recent thread context. |
| 24 | |
| 25 | ```python |
| 26 | from agents import Agent, Runner |
| 27 | from chatkit.agents import AgentContext, simple_to_agent_input, stream_agent_response |
| 28 | |
| 29 | |
| 30 | async def respond( |
| 31 | self, |
| 32 | thread: ThreadMetadata, |
| 33 | input: UserMessageItem | None, |
| 34 | context: Any, |
| 35 | ) -> AsyncIterator[ThreadStreamEvent]: |
| 36 | # Assume `items` was loaded as shown in the previous section. |
| 37 | |
| 38 | input_items = await simple_to_agent_input(items) |
| 39 | agent_context = AgentContext(thread=thread, store=self.store, request_context=context) |
| 40 | result = Runner.run_streamed( |
| 41 | assistant_agent, |
| 42 | input_items, |
| 43 | context=agent_context, |
| 44 | ) |
| 45 | ``` |
| 46 | |
| 47 | See [Stream thread events](stream-thread-events.md) for how to stream the resulting events back to the client. |
| 48 | |
| 49 | ## Customize a ThreadItemConverter |
| 50 | |
| 51 | Extend `ThreadItemConverter` when the defaults do not match your agent instructions (e.g. your prompt expects special tags around hidden context or tasks) or when you persist items the simple converter does not cover, such as @-mentions (entity tagging) or attachments. The example below wraps hidden context in a dedicated system message so the model treats it as internal-only guidance. |
| 52 | |
| 53 | ```python |
| 54 | class MyConverter(ThreadItemConverter): |
| 55 | async def hidden_context_to_input( |
| 56 | self, item: HiddenContextItem |
| 57 | ) -> Message: |
| 58 | text = ( |
| 59 | "DO NOT SHOW TO USER. Internal context for the assistant:\n" |
| 60 | f"<context>\n{item.content}\n</context>" |
| 61 | ) |
| 62 | return Message( |
| 63 | type="message", |
| 64 | role="system", |
| 65 | content=[ |
| 66 | ResponseInputTextParam( |
| 67 | type="input_text", |
| 68 | text=text, |
| 69 | ) |
| 70 | ], |
| 71 | ) |
| 72 | ``` |
| 73 | |
| 74 | You can also override methods like `attachment_to_message_content` or `tag_to_message_content` to translate @-mentions or attachments into model-readable text. |
| 75 | |
| 76 | ## Interpret inference options |
| 77 | |
| 78 | When you have specified composer options for tools or models in ChatKit.js, user-selected model or tool settings arrive as `input.inference_options`. Pass them through to your model runner—or even switch which agent you invoke—so the experience follows the user's choices. |
| 79 | |
| 80 | ```python |
| 81 | if input and input.inference_options: |
| 82 | model = input.inference_options.model |
| 83 | tool_choice = input.inference_options.tool_choice |
| 84 | # forward these into your inference call |
| 85 | ``` |
| 86 | |
| 87 | ## Next |
| 88 | |
| 89 | [Run inference](run-inference.md) |