From b05c8b80f54d5bd93ea5b346a346e13267db0425 Mon Sep 17 00:00:00 2001 From: seven7763 Date: Mon, 13 Jul 2026 21:40:19 +0800 Subject: [PATCH 1/3] samples: add DaoXE OpenAI-compatible chat completion example Demonstrate Semantic Kernel OpenAIChatCompletion with AsyncOpenAI pointed at https://daoxe.com/v1, using env-based key and account model IDs. Signed-off-by: seven7763 --- .../local_models/daoxe_chat_completion.py | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 python/samples/concepts/local_models/daoxe_chat_completion.py diff --git a/python/samples/concepts/local_models/daoxe_chat_completion.py b/python/samples/concepts/local_models/daoxe_chat_completion.py new file mode 100644 index 000000000000..2a03723de232 --- /dev/null +++ b/python/samples/concepts/local_models/daoxe_chat_completion.py @@ -0,0 +1,101 @@ +# Copyright (c) Microsoft. All rights reserved. + +"""OpenAI-compatible multi-model gateway sample using DaoXE. + +DaoXE exposes OpenAI Chat Completions at https://daoxe.com/v1 (and other protocols +such as OpenAI Responses / Anthropic Messages for other clients). This sample uses +Semantic Kernel's OpenAIChatCompletion connector with a custom AsyncOpenAI client, +the same pattern as the Ollama / LM Studio samples. + +Requirements: +- DAOXE_API_KEY environment variable +- An exact model ID from your DaoXE account catalog (GET /v1/models) + +Docs / examples: https://github.com/seven7763/DaoXE-AI +""" + +import asyncio +import os + +from openai import AsyncOpenAI + +from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion +from semantic_kernel.contents.chat_history import ChatHistory +from semantic_kernel.functions.kernel_arguments import KernelArguments +from semantic_kernel.kernel import Kernel + +system_message = """ +You are a helpful assistant. Keep answers concise and practical. +""" + +api_key = os.environ.get("DAOXE_API_KEY") +if not api_key: + raise SystemExit("Set DAOXE_API_KEY to your DaoXE dashboard API key.") + +# Exact model ID from your account catalog — do not hardcode a public price list. +ai_model_id = os.environ.get("DAOXE_MODEL", "YOUR_DAOXE_MODEL_ID") +if ai_model_id == "YOUR_DAOXE_MODEL_ID": + print( + "Tip: export DAOXE_MODEL to an exact ID from " + "`curl -H \"Authorization: Bearer $DAOXE_API_KEY\" https://daoxe.com/v1/models`" + ) + +kernel = Kernel() +service_id = "daoxe" + +openAIClient: AsyncOpenAI = AsyncOpenAI( + api_key=api_key, + base_url="https://daoxe.com/v1", +) +kernel.add_service( + OpenAIChatCompletion( + service_id=service_id, + ai_model_id=ai_model_id, + async_client=openAIClient, + ) +) + +settings = kernel.get_prompt_execution_settings_from_service_id(service_id) +settings.max_tokens = 256 +settings.temperature = 0.7 + +chat_function = kernel.add_function( + plugin_name="ChatBot", + function_name="Chat", + prompt="{{$chat_history}}{{$user_input}}", + template_format="semantic-kernel", + prompt_execution_settings=settings, +) + +chat_history = ChatHistory(system_message=system_message) + + +async def chat() -> bool: + try: + user_input = input("User:> ") + except (KeyboardInterrupt, EOFError): + print("\n\nExiting chat...") + return False + + if user_input == "exit": + print("\n\nExiting chat...") + return False + + answer = await kernel.invoke( + chat_function, + KernelArguments(user_input=user_input, chat_history=chat_history), + ) + chat_history.add_user_message(user_input) + chat_history.add_assistant_message(str(answer)) + print(f"Assistant:> {answer}") + return True + + +async def main() -> None: + chatting = True + while chatting: + chatting = await chat() + + +if __name__ == "__main__": + asyncio.run(main()) From 472e4424b22168b0331716d7423f19d3c7f29149 Mon Sep 17 00:00:00 2001 From: seven7763 Date: Mon, 13 Jul 2026 21:40:51 +0800 Subject: [PATCH 2/3] samples: link DaoXE OpenAI-compatible example in concepts README Signed-off-by: seven7763 --- python/samples/concepts/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/samples/concepts/README.md b/python/samples/concepts/README.md index bfde792aed39..31eb47018bfd 100644 --- a/python/samples/concepts/README.md +++ b/python/samples/concepts/README.md @@ -163,13 +163,14 @@ - [Grounded](./grounding/grounded.py) -### Local Models - Using the [`OpenAI connector`](https://github.com/microsoft/semantic-kernel/blob/main/python/semantic_kernel/connectors/ai/open_ai/services/open_ai_chat_completion.py) and [`OnnxGenAI connector`](https://github.com/microsoft/semantic-kernel/blob/main/python/semantic_kernel/connectors/ai/onnx/services/onnx_gen_ai_chat_completion.py) to talk to models hosted locally in Ollama, OnnxGenAI, and LM Studio +### Local Models - Using the [`OpenAI connector`](https://github.com/microsoft/semantic-kernel/blob/main/python/semantic_kernel/connectors/ai/open_ai/services/open_ai_chat_completion.py) and [`OnnxGenAI connector`](https://github.com/microsoft/semantic-kernel/blob/main/python/semantic_kernel/connectors/ai/onnx/services/onnx_gen_ai_chat_completion.py) to talk to models hosted locally in Ollama, OnnxGenAI, and LM Studio, plus OpenAI-compatible gateways such as DaoXE - [ONNX Chat Completion](./local_models/onnx_chat_completion.py) - [LM Studio Text Embedding](./local_models/lm_studio_text_embedding.py) - [LM Studio Chat Completion](./local_models/lm_studio_chat_completion.py) - [ONNX Phi3 Vision Completion](./local_models/onnx_phi3_vision_completion.py) - [Ollama Chat Completion](./local_models/ollama_chat_completion.py) +- [DaoXE Chat Completion (OpenAI-compatible gateway)](./local_models/daoxe_chat_completion.py) - [ONNX Text Completion](./local_models/onnx_text_completion.py) ### Logging - Showing how to set up logging From efe3585fe249b84f58b3f11d18fca88a3530625f Mon Sep 17 00:00:00 2001 From: hei Date: Tue, 14 Jul 2026 01:18:10 +0800 Subject: [PATCH 3/3] samples: fail fast when DAOXE_MODEL is unset Copilot review: avoid continuing with a placeholder model ID that only fails later with a confusing API error. Co-Authored-By: Claude Fable 5 --- .../concepts/local_models/daoxe_chat_completion.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/python/samples/concepts/local_models/daoxe_chat_completion.py b/python/samples/concepts/local_models/daoxe_chat_completion.py index 2a03723de232..43cb605df8c1 100644 --- a/python/samples/concepts/local_models/daoxe_chat_completion.py +++ b/python/samples/concepts/local_models/daoxe_chat_completion.py @@ -33,11 +33,12 @@ raise SystemExit("Set DAOXE_API_KEY to your DaoXE dashboard API key.") # Exact model ID from your account catalog — do not hardcode a public price list. -ai_model_id = os.environ.get("DAOXE_MODEL", "YOUR_DAOXE_MODEL_ID") -if ai_model_id == "YOUR_DAOXE_MODEL_ID": - print( - "Tip: export DAOXE_MODEL to an exact ID from " - "`curl -H \"Authorization: Bearer $DAOXE_API_KEY\" https://daoxe.com/v1/models`" +ai_model_id = os.environ.get("DAOXE_MODEL") +if not ai_model_id: + raise SystemExit( + "Set DAOXE_MODEL to an exact model ID from your DaoXE account catalog " + '(GET /v1/models), e.g. ' + '`curl -H "Authorization: Bearer $DAOXE_API_KEY" https://daoxe.com/v1/models`.' ) kernel = Kernel()