From 381bd5f73909d0dfc038e5cfd15fe6d3b2e4c2e5 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Wed, 15 Oct 2025 16:18:05 -0400 Subject: [PATCH] update all OpenAI SDK implementations to use environment variables MODEL_ENDPOINT_1, MODEL_ENDPOINT_2, TTS_ENDPOINT_1 with dynamic model discovery --- languages/csharp/openai/uncloseai.cs | 99 +++++++++-- languages/elixir/openai/mix.exs | 4 +- languages/elixir/openai/uncloseai.exs | 114 ++++++++++-- languages/go/openai/main.go | 138 ++++++++++++--- languages/java/openai/pom.xml | 5 + languages/java/openai/uncloseai.java | 245 ++++++++++++++++++-------- 6 files changed, 470 insertions(+), 135 deletions(-) diff --git a/languages/csharp/openai/uncloseai.cs b/languages/csharp/openai/uncloseai.cs index 6e0c2aa..6070624 100644 --- a/languages/csharp/openai/uncloseai.cs +++ b/languages/csharp/openai/uncloseai.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using System.Net.Http; +using System.Text.Json; using System.Threading.Tasks; using OpenAI; using OpenAI.Chat; @@ -9,20 +11,47 @@ class uncloseai { static async Task Main(string[] args) { - Console.WriteLine("=== UncloseAI C# Client (Official OpenAI SDK) ===\n"); + Console.WriteLine("=== uncloseai. C# Client (Official OpenAI SDK) ===\n"); - // Non-streaming chat with Hermes - Console.WriteLine("=== Non-Streaming Chat (Hermes) ==="); - var hermesClient = new ChatClient( - model: "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic", + // Discover endpoints from environment variables + var modelEndpoint1 = Environment.GetEnvironmentVariable("MODEL_ENDPOINT_1"); + var modelEndpoint2 = Environment.GetEnvironmentVariable("MODEL_ENDPOINT_2"); + var ttsEndpoint1 = Environment.GetEnvironmentVariable("TTS_ENDPOINT_1"); + + if (string.IsNullOrEmpty(modelEndpoint1) || string.IsNullOrEmpty(modelEndpoint2) || string.IsNullOrEmpty(ttsEndpoint1)) + { + Console.WriteLine("ERROR: No models discovered. Set environment variables:"); + Console.WriteLine(" MODEL_ENDPOINT_1, MODEL_ENDPOINT_2, TTS_ENDPOINT_1"); + Environment.Exit(1); + } + + // Discover models from endpoint 1 + Console.WriteLine($"Discovering models from {modelEndpoint1}..."); + using var httpClient = new HttpClient(); + var response1 = await httpClient.GetStringAsync($"{modelEndpoint1}/models"); + var models1 = JsonDocument.Parse(response1); + var model1Id = models1.RootElement.GetProperty("data")[0].GetProperty("id").GetString(); + Console.WriteLine($"Model 1: {model1Id}\n"); + + // Discover models from endpoint 2 + Console.WriteLine($"Discovering models from {modelEndpoint2}..."); + var response2 = await httpClient.GetStringAsync($"{modelEndpoint2}/models"); + var models2 = JsonDocument.Parse(response2); + var model2Id = models2.RootElement.GetProperty("data")[0].GetProperty("id").GetString(); + Console.WriteLine($"Model 2: {model2Id}\n"); + + // Non-streaming chat with Model 1 + Console.WriteLine("=== Non-Streaming Chat (Model 1) ==="); + var client1 = new ChatClient( + model: model1Id, apiKey: "dummy-key", new OpenAIClientOptions { - Endpoint = new Uri("https://hermes.ai.unturf.com/v1") + Endpoint = new Uri(modelEndpoint1) } ); - var hermesResponse = await hermesClient.CompleteChatAsync( + var response1Chat = await client1.CompleteChatAsync( new[] { new UserChatMessage("Give a Python Fizzbuzz solution in one line of code?") @@ -34,21 +63,59 @@ class uncloseai } ); - Console.WriteLine($"Response: {hermesResponse.Value.Content[0].Text}\n"); + Console.WriteLine($"Response: {response1Chat.Value.Content[0].Text}\n"); - // Streaming chat with Qwen - Console.WriteLine("=== Streaming Chat (Qwen) ==="); - var qwenClient = new ChatClient( - model: "hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M", + // Streaming chat with Model 1 + Console.WriteLine("=== Streaming Chat (Model 1) ==="); + Console.Write("Response: "); + await foreach (var update in client1.CompleteChatStreamingAsync( + new[] + { + new UserChatMessage("Explain quantum entanglement in one sentence.") + }, + new ChatCompletionOptions + { + Temperature = 0.5f, + MaxOutputTokenCount = 150 + } + )) + { + foreach (var contentPart in update.ContentUpdate) + { + Console.Write(contentPart.Text); + } + } + Console.WriteLine("\n"); + + // Non-streaming chat with Model 2 + Console.WriteLine("=== Non-Streaming Chat (Model 2) ==="); + var client2 = new ChatClient( + model: model2Id, apiKey: "dummy-key", new OpenAIClientOptions { - Endpoint = new Uri("https://qwen.ai.unturf.com/v1") + Endpoint = new Uri(modelEndpoint2) } ); + var response2Chat = await client2.CompleteChatAsync( + new[] + { + new UserChatMessage("Write a JavaScript function to check if a number is prime") + }, + new ChatCompletionOptions + { + Temperature = 0.5f, + MaxOutputTokenCount = 150 + } + ); + + Console.WriteLine($"Response: {response2Chat.Value.Content[0].Text}\n"); + + // Streaming chat with Model 2 + Console.WriteLine("=== Streaming Chat (Model 2) ==="); Console.Write("Response: "); - await foreach (var update in qwenClient.CompleteChatStreamingAsync( + await foreach (var update in client2.CompleteChatStreamingAsync( new[] { new UserChatMessage("Give a Python Fizzbuzz solution in one line of code?") @@ -71,10 +138,10 @@ class uncloseai Console.WriteLine("=== TTS Speech Generation ==="); var ttsClient = new AudioClient( model: "tts-1", - apiKey: "YOLO", + apiKey: "dummy-key", new OpenAIClientOptions { - Endpoint = new Uri("https://speech.ai.unturf.com/v1") + Endpoint = new Uri(ttsEndpoint1) } ); diff --git a/languages/elixir/openai/mix.exs b/languages/elixir/openai/mix.exs index 479ff7d..1a3ec8f 100644 --- a/languages/elixir/openai/mix.exs +++ b/languages/elixir/openai/mix.exs @@ -19,7 +19,9 @@ defmodule UncloseaiOpenai.MixProject do defp deps do [ - {:openai_ex, "~> 0.9.17"} + {:openai_ex, "~> 0.9.17"}, + {:httpoison, "~> 2.2"}, + {:jason, "~> 1.4"} ] end end diff --git a/languages/elixir/openai/uncloseai.exs b/languages/elixir/openai/uncloseai.exs index b233f06..a96ab6a 100644 --- a/languages/elixir/openai/uncloseai.exs +++ b/languages/elixir/openai/uncloseai.exs @@ -1,17 +1,42 @@ #!/usr/bin/env elixir -Mix.install([{:openai_ex, "~> 0.9.17"}]) +Mix.install([{:openai_ex, "~> 0.9.17"}, {:httpoison, "~> 2.2"}, {:jason, "~> 1.4"}]) -IO.puts("=== UncloseAI Elixir Client (OpenAI Ex Library) ===\n") +IO.puts("=== uncloseai. Elixir Client (OpenAI Ex Library) ===\n") -# Non-streaming chat with Hermes -IO.puts("=== Non-Streaming Chat (Hermes) ===") +# Discover endpoints from environment variables +model_endpoint_1 = System.get_env("MODEL_ENDPOINT_1") +model_endpoint_2 = System.get_env("MODEL_ENDPOINT_2") +tts_endpoint_1 = System.get_env("TTS_ENDPOINT_1") -hermes = OpenaiEx.new("dummy-key") - |> OpenaiEx.with_base_url("https://hermes.ai.unturf.com/v1") +if is_nil(model_endpoint_1) or is_nil(model_endpoint_2) or is_nil(tts_endpoint_1) do + IO.puts("ERROR: No models discovered. Set environment variables:") + IO.puts(" MODEL_ENDPOINT_1, MODEL_ENDPOINT_2, TTS_ENDPOINT_1") + System.halt(1) +end -hermes_req = OpenaiEx.ChatCompletion.new( - model: "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic", +# Discover models from endpoint 1 +IO.puts("Discovering models from #{model_endpoint_1}...") +{:ok, response1} = HTTPoison.get("#{model_endpoint_1}/models") +models1 = Jason.decode!(response1.body)["data"] +model_1_id = List.first(models1)["id"] +IO.puts("Model 1: #{model_1_id}\n") + +# Discover models from endpoint 2 +IO.puts("Discovering models from #{model_endpoint_2}...") +{:ok, response2} = HTTPoison.get("#{model_endpoint_2}/models") +models2 = Jason.decode!(response2.body)["data"] +model_2_id = List.first(models2)["id"] +IO.puts("Model 2: #{model_2_id}\n") + +# Non-streaming chat with Model 1 +IO.puts("=== Non-Streaming Chat (Model 1) ===") + +client1 = OpenaiEx.new("dummy-key") + |> OpenaiEx.with_base_url(model_endpoint_1) + +req1 = OpenaiEx.ChatCompletion.new( + model: model_1_id, messages: [ %{role: "user", content: "Give a Python Fizzbuzz solution in one line of code?"} ], @@ -19,7 +44,7 @@ hermes_req = OpenaiEx.ChatCompletion.new( max_tokens: 150 ) -case OpenaiEx.ChatCompletion.create(hermes, hermes_req) do +case OpenaiEx.ChatCompletion.create(client1, req1) do {:ok, response} -> content = response.choices |> List.first() |> Map.get(:message) |> Map.get(:content) IO.puts("Response: #{content}\n") @@ -27,14 +52,65 @@ case OpenaiEx.ChatCompletion.create(hermes, hermes_req) do IO.puts("Error: #{inspect(error)}\n") end -# Streaming chat with Qwen -IO.puts("=== Streaming Chat (Qwen) ===") +# Streaming chat with Model 1 +IO.puts("=== Streaming Chat (Model 1) ===") -qwen = OpenaiEx.new("dummy-key") - |> OpenaiEx.with_base_url("https://qwen.ai.unturf.com/v1") +stream_req1 = OpenaiEx.ChatCompletion.new( + model: model_1_id, + messages: [ + %{role: "user", content: "Explain quantum entanglement in one sentence."} + ], + temperature: 0.5, + max_tokens: 150, + stream: true +) -qwen_req = OpenaiEx.ChatCompletion.new( - model: "hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M", +IO.write("Response: ") + +OpenaiEx.ChatCompletion.create(client1, stream_req1) +|> Stream.each(fn + {:data, chunk} -> + case chunk do + %{choices: [%{delta: %{content: content}} | _]} when not is_nil(content) -> + IO.write(content) + _ -> + :ok + end + _ -> + :ok +end) +|> Stream.run() + +IO.puts("\n") + +# Non-streaming chat with Model 2 +IO.puts("=== Non-Streaming Chat (Model 2) ===") + +client2 = OpenaiEx.new("dummy-key") + |> OpenaiEx.with_base_url(model_endpoint_2) + +req2 = OpenaiEx.ChatCompletion.new( + model: model_2_id, + messages: [ + %{role: "user", content: "Write a JavaScript function to check if a number is prime"} + ], + temperature: 0.5, + max_tokens: 150 +) + +case OpenaiEx.ChatCompletion.create(client2, req2) do + {:ok, response} -> + content = response.choices |> List.first() |> Map.get(:message) |> Map.get(:content) + IO.puts("Response: #{content}\n") + {:error, error} -> + IO.puts("Error: #{inspect(error)}\n") +end + +# Streaming chat with Model 2 +IO.puts("=== Streaming Chat (Model 2) ===") + +stream_req2 = OpenaiEx.ChatCompletion.new( + model: model_2_id, messages: [ %{role: "user", content: "Give a Python Fizzbuzz solution in one line of code?"} ], @@ -45,7 +121,7 @@ qwen_req = OpenaiEx.ChatCompletion.new( IO.write("Response: ") -OpenaiEx.ChatCompletion.create(qwen, qwen_req) +OpenaiEx.ChatCompletion.create(client2, stream_req2) |> Stream.each(fn {:data, chunk} -> case chunk do @@ -64,8 +140,8 @@ IO.puts("\n") # TTS example IO.puts("=== TTS Speech Generation ===") -tts = OpenaiEx.new("YOLO") - |> OpenaiEx.with_base_url("https://speech.ai.unturf.com/v1") +tts_client = OpenaiEx.new("dummy-key") + |> OpenaiEx.with_base_url(tts_endpoint_1) tts_req = OpenaiEx.Audio.Speech.new( model: "tts-1", @@ -74,7 +150,7 @@ tts_req = OpenaiEx.Audio.Speech.new( speed: 0.9 ) -case OpenaiEx.Audio.Speech.create(tts, tts_req) do +case OpenaiEx.Audio.Speech.create(tts_client, tts_req) do {:ok, audio_data} -> File.write!("speech.mp3", audio_data) {:ok, file_info} = File.stat("speech.mp3") diff --git a/languages/go/openai/main.go b/languages/go/openai/main.go index a3e49f1..c661826 100644 --- a/languages/go/openai/main.go +++ b/languages/go/openai/main.go @@ -2,26 +2,79 @@ package main import ( "context" + "encoding/json" "fmt" "io" + "net/http" "os" "github.com/openai/openai-go" "github.com/openai/openai-go/option" ) -func main() { - fmt.Println("=== UncloseAI Go Client (Official OpenAI SDK) ===\n") +type ModelsResponse struct { + Data []struct { + ID string `json:"id"` + } `json:"data"` +} - // Non-streaming chat with Hermes - fmt.Println("=== Non-Streaming Chat (Hermes) ===") - hermesClient := openai.NewClient( - option.WithBaseURL("https://hermes.ai.unturf.com/v1"), +func main() { + fmt.Println("=== uncloseai. Go Client (Official OpenAI SDK) ===\n") + + // Discover endpoints from environment variables + modelEndpoint1 := os.Getenv("MODEL_ENDPOINT_1") + modelEndpoint2 := os.Getenv("MODEL_ENDPOINT_2") + ttsEndpoint1 := os.Getenv("TTS_ENDPOINT_1") + + if modelEndpoint1 == "" || modelEndpoint2 == "" || ttsEndpoint1 == "" { + fmt.Fprintf(os.Stderr, "ERROR: No models discovered. Set environment variables:\n") + fmt.Fprintf(os.Stderr, " MODEL_ENDPOINT_1, MODEL_ENDPOINT_2, TTS_ENDPOINT_1\n") + os.Exit(1) + } + + // Discover models from endpoint 1 + fmt.Printf("Discovering models from %s...\n", modelEndpoint1) + resp1, err := http.Get(modelEndpoint1 + "/models") + if err != nil { + fmt.Fprintf(os.Stderr, "Error discovering models: %v\n", err) + os.Exit(1) + } + defer resp1.Body.Close() + + var models1 ModelsResponse + if err := json.NewDecoder(resp1.Body).Decode(&models1); err != nil { + fmt.Fprintf(os.Stderr, "Error parsing models: %v\n", err) + os.Exit(1) + } + model1ID := models1.Data[0].ID + fmt.Printf("Model 1: %s\n\n", model1ID) + + // Discover models from endpoint 2 + fmt.Printf("Discovering models from %s...\n", modelEndpoint2) + resp2, err := http.Get(modelEndpoint2 + "/models") + if err != nil { + fmt.Fprintf(os.Stderr, "Error discovering models: %v\n", err) + os.Exit(1) + } + defer resp2.Body.Close() + + var models2 ModelsResponse + if err := json.NewDecoder(resp2.Body).Decode(&models2); err != nil { + fmt.Fprintf(os.Stderr, "Error parsing models: %v\n", err) + os.Exit(1) + } + model2ID := models2.Data[0].ID + fmt.Printf("Model 2: %s\n\n", model2ID) + + // Non-streaming chat with Model 1 + fmt.Println("=== Non-Streaming Chat (Model 1) ===") + client1 := openai.NewClient( + option.WithBaseURL(modelEndpoint1), option.WithAPIKey("dummy-key"), ) - chatResponse, err := hermesClient.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Model: openai.F("adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic"), + chatResponse1, err := client1.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ + Model: openai.F(model1ID), Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Give a Python Fizzbuzz solution in one line of code?"), }), @@ -32,18 +85,59 @@ func main() { if err != nil { fmt.Printf("Error: %v\n", err) } else { - fmt.Printf("Response: %s\n\n", chatResponse.Choices[0].Message.Content) + fmt.Printf("Response: %s\n\n", chatResponse1.Choices[0].Message.Content) } - // Streaming chat with Qwen - fmt.Println("=== Streaming Chat (Qwen) ===") - qwenClient := openai.NewClient( - option.WithBaseURL("https://qwen.ai.unturf.com/v1"), + // Streaming chat with Model 1 + fmt.Println("=== Streaming Chat (Model 1) ===") + stream1 := client1.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{ + Model: openai.F(model1ID), + Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + openai.UserMessage("Explain quantum entanglement in one sentence."), + }), + Temperature: openai.Float(0.5), + MaxTokens: openai.Int(150), + }) + + fmt.Print("Response: ") + for stream1.Next() { + chunk := stream1.Current() + if len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != "" { + fmt.Print(chunk.Choices[0].Delta.Content) + } + } + + if err := stream1.Err(); err != nil { + fmt.Printf("\nStream error: %v\n", err) + } + fmt.Println("\n") + + // Non-streaming chat with Model 2 + fmt.Println("=== Non-Streaming Chat (Model 2) ===") + client2 := openai.NewClient( + option.WithBaseURL(modelEndpoint2), option.WithAPIKey("dummy-key"), ) - stream := qwenClient.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{ - Model: openai.F("hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M"), + chatResponse2, err := client2.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ + Model: openai.F(model2ID), + Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + openai.UserMessage("Write a JavaScript function to check if a number is prime"), + }), + Temperature: openai.Float(0.5), + MaxTokens: openai.Int(150), + }) + + if err != nil { + fmt.Printf("Error: %v\n", err) + } else { + fmt.Printf("Response: %s\n\n", chatResponse2.Choices[0].Message.Content) + } + + // Streaming chat with Model 2 + fmt.Println("=== Streaming Chat (Model 2) ===") + stream2 := client2.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{ + Model: openai.F(model2ID), Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Give a Python Fizzbuzz solution in one line of code?"), }), @@ -52,14 +146,14 @@ func main() { }) fmt.Print("Response: ") - for stream.Next() { - chunk := stream.Current() + for stream2.Next() { + chunk := stream2.Current() if len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != "" { fmt.Print(chunk.Choices[0].Delta.Content) } } - if err := stream.Err(); err != nil { + if err := stream2.Err(); err != nil { fmt.Printf("\nStream error: %v\n", err) } fmt.Println("\n") @@ -67,8 +161,8 @@ func main() { // TTS example fmt.Println("=== TTS Speech Generation ===") ttsClient := openai.NewClient( - option.WithBaseURL("https://speech.ai.unturf.com/v1"), - option.WithAPIKey("YOLO"), + option.WithBaseURL(ttsEndpoint1), + option.WithAPIKey("dummy-key"), ) response, err := ttsClient.Audio.Speech.New(context.Background(), openai.AudioSpeechNewParams{ @@ -93,10 +187,10 @@ func main() { fmt.Printf("File write error: %v\n", err) } else { fileInfo, _ := os.Stat("speech.mp3") - fmt.Printf("[OK] Speech file created: speech.mp3 (%d bytes)\n", fileInfo.Size()) + fmt.Printf("[OK] Speech file created: speech.mp3 (%d bytes)\n\n", fileInfo.Size()) } } } - fmt.Println("\n=== Examples Complete ===") + fmt.Println("=== Examples Complete ===") } diff --git a/languages/java/openai/pom.xml b/languages/java/openai/pom.xml index 8dd682f..191dfdb 100644 --- a/languages/java/openai/pom.xml +++ b/languages/java/openai/pom.xml @@ -20,6 +20,11 @@ openai-java 0.8.1 + + org.json + json + 20240303 + diff --git a/languages/java/openai/uncloseai.java b/languages/java/openai/uncloseai.java index 65a9154..482b105 100644 --- a/languages/java/openai/uncloseai.java +++ b/languages/java/openai/uncloseai.java @@ -1,94 +1,185 @@ import com.openai.client.OpenAIClient; import com.openai.client.okhttp.OpenAIOkHttpClient; import com.openai.models.*; -import com.openai.core.JsonValue; import java.io.FileOutputStream; import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.util.List; import java.util.stream.Stream; +import org.json.JSONArray; +import org.json.JSONObject; + public class uncloseai { public static void main(String[] args) { - System.out.println("=== UncloseAI Java Client (Official OpenAI SDK) ===\n"); + System.out.println("=== uncloseai. Java Client (Official OpenAI SDK) ===\n"); - // Non-streaming chat with Hermes - System.out.println("=== Non-Streaming Chat (Hermes) ==="); - OpenAIClient hermesClient = OpenAIOkHttpClient.builder() - .apiKey("dummy-key") - .baseURL("https://hermes.ai.unturf.com/v1") - .build(); + // Discover endpoints from environment variables + String modelEndpoint1 = System.getenv("MODEL_ENDPOINT_1"); + String modelEndpoint2 = System.getenv("MODEL_ENDPOINT_2"); + String ttsEndpoint1 = System.getenv("TTS_ENDPOINT_1"); - ChatCompletionCreateParams hermesParams = ChatCompletionCreateParams.builder() - .model("adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic") - .addMessage(ChatCompletionMessageParam.ofChatCompletionUserMessageParam( - ChatCompletionUserMessageParam.builder() - .role(ChatCompletionUserMessageParam.Role.USER) - .content(ChatCompletionUserMessageParam.Content.ofTextContent( - "Give a Python Fizzbuzz solution in one line of code?" - )) - .build() - )) - .temperature(0.5) - .maxTokens(150L) - .build(); - - ChatCompletion hermesResponse = hermesClient.chat().completions().create(hermesParams); - System.out.println("Response: " + hermesResponse.choices().get(0).message().content().get() + "\n"); - - // Streaming chat with Qwen - System.out.println("=== Streaming Chat (Qwen) ==="); - OpenAIClient qwenClient = OpenAIOkHttpClient.builder() - .apiKey("dummy-key") - .baseURL("https://qwen.ai.unturf.com/v1") - .build(); - - ChatCompletionCreateParams qwenParams = ChatCompletionCreateParams.builder() - .model("hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M") - .addMessage(ChatCompletionMessageParam.ofChatCompletionUserMessageParam( - ChatCompletionUserMessageParam.builder() - .role(ChatCompletionUserMessageParam.Role.USER) - .content(ChatCompletionUserMessageParam.Content.ofTextContent( - "Give a Python Fizzbuzz solution in one line of code?" - )) - .build() - )) - .temperature(0.5) - .maxTokens(150L) - .build(); - - System.out.print("Response: "); - Stream qwenStream = qwenClient.chat().completions().createStreaming(qwenParams); - qwenStream.forEach(chunk -> { - if (!chunk.choices().isEmpty() && chunk.choices().get(0).delta().content().isPresent()) { - System.out.print(chunk.choices().get(0).delta().content().get()); - } - }); - System.out.println("\n"); - - // TTS example - System.out.println("=== TTS Speech Generation ==="); - OpenAIClient ttsClient = OpenAIOkHttpClient.builder() - .apiKey("YOLO") - .baseURL("https://speech.ai.unturf.com/v1") - .build(); - - SpeechCreateParams speechParams = SpeechCreateParams.builder() - .model(SpeechModel.TTS_1) - .voice(SpeechCreateParams.Voice.ALLOY) - .input("I think so therefore, Today is a wonderful day to grow something people love!") - .speed(0.9) - .build(); - - byte[] audioBytes = ttsClient.audio().speech().create(speechParams); - - try (FileOutputStream fos = new FileOutputStream("speech.mp3")) { - fos.write(audioBytes); - System.out.println("[OK] Speech file created: speech.mp3 (" + audioBytes.length + " bytes)\n"); - } catch (IOException e) { - System.err.println("Error writing audio file: " + e.getMessage()); + if (modelEndpoint1 == null || modelEndpoint2 == null || ttsEndpoint1 == null) { + System.err.println("ERROR: No models discovered. Set environment variables:"); + System.err.println(" MODEL_ENDPOINT_1, MODEL_ENDPOINT_2, TTS_ENDPOINT_1"); + System.exit(1); } - System.out.println("=== Examples Complete ==="); + try { + HttpClient httpClient = HttpClient.newHttpClient(); + + // Discover models from endpoint 1 + System.out.println("Discovering models from " + modelEndpoint1 + "..."); + HttpRequest req1 = HttpRequest.newBuilder() + .uri(URI.create(modelEndpoint1 + "/models")) + .GET() + .build(); + HttpResponse res1 = httpClient.send(req1, HttpResponse.BodyHandlers.ofString()); + JSONObject json1 = new JSONObject(res1.body()); + JSONArray models1 = json1.getJSONArray("data"); + String model1Id = models1.getJSONObject(0).getString("id"); + System.out.println("Model 1: " + model1Id + "\n"); + + // Discover models from endpoint 2 + System.out.println("Discovering models from " + modelEndpoint2 + "..."); + HttpRequest req2 = HttpRequest.newBuilder() + .uri(URI.create(modelEndpoint2 + "/models")) + .GET() + .build(); + HttpResponse res2 = httpClient.send(req2, HttpResponse.BodyHandlers.ofString()); + JSONObject json2 = new JSONObject(res2.body()); + JSONArray models2 = json2.getJSONArray("data"); + String model2Id = models2.getJSONObject(0).getString("id"); + System.out.println("Model 2: " + model2Id + "\n"); + + // Non-streaming chat with Model 1 + System.out.println("=== Non-Streaming Chat (Model 1) ==="); + OpenAIClient client1 = OpenAIOkHttpClient.builder() + .apiKey("dummy-key") + .baseURL(modelEndpoint1) + .build(); + + ChatCompletionCreateParams params1 = ChatCompletionCreateParams.builder() + .model(model1Id) + .addMessage(ChatCompletionMessageParam.ofChatCompletionUserMessageParam( + ChatCompletionUserMessageParam.builder() + .role(ChatCompletionUserMessageParam.Role.USER) + .content(ChatCompletionUserMessageParam.Content.ofTextContent( + "Give a Python Fizzbuzz solution in one line of code?" + )) + .build() + )) + .temperature(0.5) + .maxTokens(150L) + .build(); + + ChatCompletion response1 = client1.chat().completions().create(params1); + System.out.println("Response: " + response1.choices().get(0).message().content().get() + "\n"); + + // Streaming chat with Model 1 + System.out.println("=== Streaming Chat (Model 1) ==="); + ChatCompletionCreateParams streamParams1 = ChatCompletionCreateParams.builder() + .model(model1Id) + .addMessage(ChatCompletionMessageParam.ofChatCompletionUserMessageParam( + ChatCompletionUserMessageParam.builder() + .role(ChatCompletionUserMessageParam.Role.USER) + .content(ChatCompletionUserMessageParam.Content.ofTextContent( + "Explain quantum entanglement in one sentence." + )) + .build() + )) + .temperature(0.5) + .maxTokens(150L) + .build(); + + System.out.print("Response: "); + Stream stream1 = client1.chat().completions().createStreaming(streamParams1); + stream1.forEach(chunk -> { + if (!chunk.choices().isEmpty() && chunk.choices().get(0).delta().content().isPresent()) { + System.out.print(chunk.choices().get(0).delta().content().get()); + } + }); + System.out.println("\n"); + + // Non-streaming chat with Model 2 + System.out.println("=== Non-Streaming Chat (Model 2) ==="); + OpenAIClient client2 = OpenAIOkHttpClient.builder() + .apiKey("dummy-key") + .baseURL(modelEndpoint2) + .build(); + + ChatCompletionCreateParams params2 = ChatCompletionCreateParams.builder() + .model(model2Id) + .addMessage(ChatCompletionMessageParam.ofChatCompletionUserMessageParam( + ChatCompletionUserMessageParam.builder() + .role(ChatCompletionUserMessageParam.Role.USER) + .content(ChatCompletionUserMessageParam.Content.ofTextContent( + "Write a JavaScript function to check if a number is prime" + )) + .build() + )) + .temperature(0.5) + .maxTokens(150L) + .build(); + + ChatCompletion response2 = client2.chat().completions().create(params2); + System.out.println("Response: " + response2.choices().get(0).message().content().get() + "\n"); + + // Streaming chat with Model 2 + System.out.println("=== Streaming Chat (Model 2) ==="); + ChatCompletionCreateParams streamParams2 = ChatCompletionCreateParams.builder() + .model(model2Id) + .addMessage(ChatCompletionMessageParam.ofChatCompletionUserMessageParam( + ChatCompletionUserMessageParam.builder() + .role(ChatCompletionUserMessageParam.Role.USER) + .content(ChatCompletionUserMessageParam.Content.ofTextContent( + "Give a Python Fizzbuzz solution in one line of code?" + )) + .build() + )) + .temperature(0.5) + .maxTokens(150L) + .build(); + + System.out.print("Response: "); + Stream stream2 = client2.chat().completions().createStreaming(streamParams2); + stream2.forEach(chunk -> { + if (!chunk.choices().isEmpty() && chunk.choices().get(0).delta().content().isPresent()) { + System.out.print(chunk.choices().get(0).delta().content().get()); + } + }); + System.out.println("\n"); + + // TTS example + System.out.println("=== TTS Speech Generation ==="); + OpenAIClient ttsClient = OpenAIOkHttpClient.builder() + .apiKey("dummy-key") + .baseURL(ttsEndpoint1) + .build(); + + SpeechCreateParams speechParams = SpeechCreateParams.builder() + .model(SpeechModel.TTS_1) + .voice(SpeechCreateParams.Voice.ALLOY) + .input("I think so therefore, Today is a wonderful day to grow something people love!") + .speed(0.9) + .build(); + + byte[] audioBytes = ttsClient.audio().speech().create(speechParams); + + try (FileOutputStream fos = new FileOutputStream("speech.mp3")) { + fos.write(audioBytes); + System.out.println("[OK] Speech file created: speech.mp3 (" + audioBytes.length + " bytes)\n"); + } + + System.out.println("=== Examples Complete ==="); + + } catch (IOException | InterruptedException e) { + System.err.println("Error: " + e.getMessage()); + e.printStackTrace(); + } } }