diff --git a/languages/csharp/openai/Dockerfile b/languages/csharp/openai/Dockerfile new file mode 100644 index 0000000..bd57bca --- /dev/null +++ b/languages/csharp/openai/Dockerfile @@ -0,0 +1,22 @@ +# Use official .NET SDK to build +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder + +WORKDIR /app + +# Copy project file and restore dependencies +COPY uncloseai.csproj ./ +RUN dotnet restore + +# Copy source and build +COPY uncloseai.cs ./ +RUN dotnet build -c Release -o /app/build + +# Run stage +FROM mcr.microsoft.com/dotnet/runtime:8.0 + +WORKDIR /app + +# Copy built application from builder +COPY --from=builder /app/build . + +CMD ["dotnet", "uncloseai.dll"] diff --git a/languages/csharp/openai/uncloseai.cs b/languages/csharp/openai/uncloseai.cs new file mode 100644 index 0000000..6e0c2aa --- /dev/null +++ b/languages/csharp/openai/uncloseai.cs @@ -0,0 +1,96 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using OpenAI; +using OpenAI.Chat; +using OpenAI.Audio; + +class uncloseai +{ + static async Task Main(string[] args) + { + 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", + apiKey: "dummy-key", + new OpenAIClientOptions + { + Endpoint = new Uri("https://hermes.ai.unturf.com/v1") + } + ); + + var hermesResponse = await hermesClient.CompleteChatAsync( + new[] + { + new UserChatMessage("Give a Python Fizzbuzz solution in one line of code?") + }, + new ChatCompletionOptions + { + Temperature = 0.5f, + MaxOutputTokenCount = 150 + } + ); + + Console.WriteLine($"Response: {hermesResponse.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", + apiKey: "dummy-key", + new OpenAIClientOptions + { + Endpoint = new Uri("https://qwen.ai.unturf.com/v1") + } + ); + + Console.Write("Response: "); + await foreach (var update in qwenClient.CompleteChatStreamingAsync( + new[] + { + new UserChatMessage("Give a Python Fizzbuzz solution in one line of code?") + }, + new ChatCompletionOptions + { + Temperature = 0.5f, + MaxOutputTokenCount = 150 + } + )) + { + foreach (var contentPart in update.ContentUpdate) + { + Console.Write(contentPart.Text); + } + } + Console.WriteLine("\n"); + + // TTS example + Console.WriteLine("=== TTS Speech Generation ==="); + var ttsClient = new AudioClient( + model: "tts-1", + apiKey: "YOLO", + new OpenAIClientOptions + { + Endpoint = new Uri("https://speech.ai.unturf.com/v1") + } + ); + + var speech = await ttsClient.GenerateSpeechAsync( + "I think so therefore, Today is a wonderful day to grow something people love!", + GeneratedSpeechVoice.Alloy, + new SpeechGenerationOptions + { + Speed = 0.9f + } + ); + + await File.WriteAllBytesAsync("speech.mp3", speech.Value.ToArray()); + var fileInfo = new FileInfo("speech.mp3"); + Console.WriteLine($"[OK] Speech file created: speech.mp3 ({fileInfo.Length} bytes)\n"); + + Console.WriteLine("=== Examples Complete ==="); + } +} diff --git a/languages/csharp/openai/uncloseai.csproj b/languages/csharp/openai/uncloseai.csproj new file mode 100644 index 0000000..ea95396 --- /dev/null +++ b/languages/csharp/openai/uncloseai.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/languages/go/openai/Dockerfile b/languages/go/openai/Dockerfile new file mode 100644 index 0000000..195fcb8 --- /dev/null +++ b/languages/go/openai/Dockerfile @@ -0,0 +1,26 @@ +# Multi-stage build for Go with official OpenAI SDK +FROM golang:1.22-alpine AS builder + +WORKDIR /app + +# Copy go mod files +COPY go.mod ./ +RUN go mod download + +# Copy source code +COPY main.go ./ + +# Build the application +RUN CGO_ENABLED=0 GOOS=linux go build -o /uncloseai main.go + +# Final stage +FROM alpine:latest +WORKDIR /root/ +COPY --from=builder /uncloseai ./ + +# Set environment variables for testing +ENV MODEL_ENDPOINT_1=https://hermes.ai.unturf.com +ENV MODEL_ENDPOINT_2=https://qwen.ai.unturf.com +ENV TTS_ENDPOINT_1=https://speech.ai.unturf.com + +CMD ["./uncloseai"] diff --git a/languages/go/openai/go.mod b/languages/go/openai/go.mod new file mode 100644 index 0000000..1f92f06 --- /dev/null +++ b/languages/go/openai/go.mod @@ -0,0 +1,5 @@ +module uncloseai-go-openai + +go 1.22 + +require github.com/openai/openai-go v0.1.0-alpha.39 diff --git a/languages/go/openai/main.go b/languages/go/openai/main.go new file mode 100644 index 0000000..a3e49f1 --- /dev/null +++ b/languages/go/openai/main.go @@ -0,0 +1,102 @@ +package main + +import ( + "context" + "fmt" + "io" + "os" + + "github.com/openai/openai-go" + "github.com/openai/openai-go/option" +) + +func main() { + fmt.Println("=== UncloseAI Go Client (Official OpenAI SDK) ===\n") + + // Non-streaming chat with Hermes + fmt.Println("=== Non-Streaming Chat (Hermes) ===") + hermesClient := openai.NewClient( + option.WithBaseURL("https://hermes.ai.unturf.com/v1"), + 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"), + Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + openai.UserMessage("Give a Python Fizzbuzz solution in one line of code?"), + }), + 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", chatResponse.Choices[0].Message.Content) + } + + // Streaming chat with Qwen + fmt.Println("=== Streaming Chat (Qwen) ===") + qwenClient := openai.NewClient( + option.WithBaseURL("https://qwen.ai.unturf.com/v1"), + 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"), + Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + openai.UserMessage("Give a Python Fizzbuzz solution in one line of code?"), + }), + Temperature: openai.Float(0.5), + MaxTokens: openai.Int(150), + }) + + fmt.Print("Response: ") + for stream.Next() { + chunk := stream.Current() + if len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != "" { + fmt.Print(chunk.Choices[0].Delta.Content) + } + } + + if err := stream.Err(); err != nil { + fmt.Printf("\nStream error: %v\n", err) + } + fmt.Println("\n") + + // TTS example + fmt.Println("=== TTS Speech Generation ===") + ttsClient := openai.NewClient( + option.WithBaseURL("https://speech.ai.unturf.com/v1"), + option.WithAPIKey("YOLO"), + ) + + response, err := ttsClient.Audio.Speech.New(context.Background(), openai.AudioSpeechNewParams{ + Model: openai.F(openai.SpeechModelTTS1), + Voice: openai.F(openai.AudioSpeechNewParamsVoiceAlloy), + Input: openai.F("I think so therefore, Today is a wonderful day to grow something people love!"), + Speed: openai.Float(0.9), + }) + + if err != nil { + fmt.Printf("TTS Error: %v\n", err) + } else { + defer response.Body.Close() + + out, err := os.Create("speech.mp3") + if err != nil { + fmt.Printf("File creation error: %v\n", err) + } else { + defer out.Close() + _, err = io.Copy(out, response.Body) + if err != nil { + 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.Println("\n=== Examples Complete ===") +} diff --git a/languages/java/openai/Dockerfile b/languages/java/openai/Dockerfile new file mode 100644 index 0000000..1a8ecc9 --- /dev/null +++ b/languages/java/openai/Dockerfile @@ -0,0 +1,26 @@ +# Use official Maven image to build +FROM maven:3.9-eclipse-temurin-17-alpine AS builder + +WORKDIR /app + +# Copy POM and source +COPY pom.xml ./ +COPY uncloseai.java ./ + +# Build the application +RUN mvn clean compile + +# Run stage +FROM eclipse-temurin:17-jre-alpine + +WORKDIR /app + +# Copy compiled classes and dependencies from builder +COPY --from=builder /app/target/classes ./classes +COPY --from=builder /root/.m2/repository /root/.m2/repository +COPY --from=builder /app/pom.xml ./ + +# Install maven to have classpath available +RUN apk add --no-cache maven + +CMD ["mvn", "-q", "exec:java"] diff --git a/languages/java/openai/pom.xml b/languages/java/openai/pom.xml new file mode 100644 index 0000000..8dd682f --- /dev/null +++ b/languages/java/openai/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.uncloseai + uncloseai-java-openai + 1.0.0 + + + 17 + 17 + UTF-8 + + + + + com.openai + openai-java + 0.8.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + uncloseai + + + + + diff --git a/languages/java/openai/uncloseai.java b/languages/java/openai/uncloseai.java new file mode 100644 index 0000000..65a9154 --- /dev/null +++ b/languages/java/openai/uncloseai.java @@ -0,0 +1,94 @@ +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.util.List; +import java.util.stream.Stream; + +public class uncloseai { + public static void main(String[] args) { + 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(); + + 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()); + } + + System.out.println("=== Examples Complete ==="); + } +} diff --git a/languages/ruby/openai/Dockerfile b/languages/ruby/openai/Dockerfile new file mode 100644 index 0000000..2cf809a --- /dev/null +++ b/languages/ruby/openai/Dockerfile @@ -0,0 +1,16 @@ +# Use official Ruby image +FROM ruby:3.3-slim + +WORKDIR /app + +# Copy Gemfile +COPY Gemfile ./ + +# Install dependencies +RUN bundle install + +# Copy source code +COPY uncloseai.rb ./ +RUN chmod +x uncloseai.rb + +CMD ["ruby", "uncloseai.rb"] diff --git a/languages/ruby/openai/Gemfile b/languages/ruby/openai/Gemfile new file mode 100644 index 0000000..3a8d935 --- /dev/null +++ b/languages/ruby/openai/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' + +gem 'openai', '~> 0.30.0' diff --git a/languages/ruby/openai/uncloseai.rb b/languages/ruby/openai/uncloseai.rb new file mode 100644 index 0000000..4323a30 --- /dev/null +++ b/languages/ruby/openai/uncloseai.rb @@ -0,0 +1,73 @@ +#!/usr/bin/env ruby +# UncloseAI - Ruby Client using Official OpenAI SDK +# A Ruby client for OpenAI-compatible APIs with streaming support + +require 'openai' + +puts "=== UncloseAI Ruby Client (Official OpenAI SDK) ===\n\n" + +# Non-streaming chat with Hermes +puts "=== Non-Streaming Chat (Hermes) ===" +hermes_client = OpenAI::Client.new( + access_token: "dummy-key", + uri_base: "https://hermes.ai.unturf.com/v1" +) + +response = hermes_client.chat( + parameters: { + model: "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic", + messages: [ + { role: "user", content: "Give a Python Fizzbuzz solution in one line of code?" } + ], + temperature: 0.5, + max_tokens: 150 + } +) + +puts "Response: #{response.dig('choices', 0, 'message', 'content')}\n\n" + +# Streaming chat with Qwen +puts "=== Streaming Chat (Qwen) ===" +qwen_client = OpenAI::Client.new( + access_token: "dummy-key", + uri_base: "https://qwen.ai.unturf.com/v1" +) + +print "Response: " +qwen_client.chat( + parameters: { + model: "hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M", + messages: [ + { role: "user", content: "Give a Python Fizzbuzz solution in one line of code?" } + ], + temperature: 0.5, + max_tokens: 150, + stream: proc do |chunk, _bytesize| + content = chunk.dig('choices', 0, 'delta', 'content') + print content if content + end + } +) +puts "\n\n" + +# TTS example +puts "=== TTS Speech Generation ===" +tts_client = OpenAI::Client.new( + access_token: "YOLO", + uri_base: "https://speech.ai.unturf.com/v1" +) + +response = tts_client.audio.speech( + parameters: { + model: "tts-1", + voice: "alloy", + input: "I think so therefore, Today is a wonderful day to grow something people love!", + speed: 0.9 + } +) + +File.binwrite("speech.mp3", response) +file_size = File.size("speech.mp3") +puts "[OK] Speech file created: speech.mp3 (#{file_size} bytes)\n\n" + +puts "=== Examples Complete ==="