Python : Support FakeChatClient#5663
Conversation
|
@andresliszt please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
There was a problem hiding this comment.
Pull request overview
Adds a deterministic FakeChatClient to the Python core SDK to support testing/demo scenarios without a real model dependency (as requested in #5568).
Changes:
- Introduces
agent_framework.fake.FakeChatClient(andFakeChatOptions) for queued/cycling fake responses and basic streaming behavior. - Adds unit tests covering init/serialization, middleware integration, cycling/exhaustion behavior, and streaming finalization.
- Updates
python/PACKAGE_STATUS.mdto include a new “fake” package entry.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| python/packages/core/agent_framework/fake/_chat_client.py | Implements FakeChatClient and options, including response selection, cycling, and streaming updates. |
| python/packages/core/agent_framework/fake/init.py | Exposes the fake client/options from the agent_framework.fake namespace. |
| python/packages/core/tests/core/test_fake_chat_client.py | Adds test coverage for FakeChatClient behavior (middleware, streaming, exhaustion, cycle). |
| python/PACKAGE_STATUS.md | Adds an entry for an “agent-framework-fake” package. |
| class FakeChatOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): | ||
| """Fake-model options used by FakeChatClient. | ||
|
|
||
| Keys: | ||
| model: Optional model name override for this request. | ||
| response: Optional one-off response that overrides queued responses. | ||
| cycle: Optional per-request override for cycling behavior. | ||
| """ | ||
|
|
||
| response: FakeResponseItem | ||
| cycle: bool | ||
|
|
| self.middleware = list(self.chat_middleware) | ||
| self._responses = list(responses) | ||
| self._response_index = 0 | ||
| self._cycle = cycle | ||
|
|
| def _materialize_response(self, value: FakeResponseItem, options: Mapping[str, Any]) -> ChatResponse: | ||
| model = str(options.get("model") or self.model) | ||
|
|
||
| if isinstance(value, ChatResponse): | ||
| return value | ||
| if isinstance(value, Message): | ||
| return ChatResponse(messages=[value], model=model) | ||
| return ChatResponse(messages=[Message(role="assistant", contents=[value])], model=model) |
|
|
||
| def _build_default_response(self, *, messages: Sequence[Message], options: Mapping[str, Any]) -> ChatResponse: | ||
| model = str(options.get("model") or self.model) | ||
| last_user_text = "" | ||
| for message in reversed(messages): | ||
| if message.role == "user" and message.text: | ||
| last_user_text = message.text | ||
| break | ||
|
|
||
| default_text = f"Fake response: {last_user_text}" if last_user_text else "Fake response" | ||
| return ChatResponse(messages=[Message(role="assistant", contents=[default_text])], model=model) |
| | `agent-framework-declarative` | `python/packages/declarative` | `beta` | | ||
| | `agent-framework-devui` | `python/packages/devui` | `beta` | | ||
| | `agent-framework-durabletask` | `python/packages/durabletask` | `beta` | | ||
| | `agent-framework-fake` | `python/packages/fake` | `alpha` | |
Motivation and Context
Description
Thanks for this amazing project. This PR supports #5568. WIP!
Contribution Checklist