diff --git a/languages/go/openai/Dockerfile b/languages/go/openai/Dockerfile index de8b8b4..bd09b33 100644 --- a/languages/go/openai/Dockerfile +++ b/languages/go/openai/Dockerfile @@ -4,8 +4,8 @@ FROM golang:1.22-alpine AS builder WORKDIR /app # Copy go mod files -COPY go.mod go.sum ./ -RUN go mod download +COPY go.mod ./ +RUN go get github.com/openai/openai-go/v3@v3.3.0 # Copy source code COPY main.go ./ diff --git a/languages/go/openai/go.mod b/languages/go/openai/go.mod index 5fe7422..97420bc 100644 --- a/languages/go/openai/go.mod +++ b/languages/go/openai/go.mod @@ -2,7 +2,7 @@ module uncloseai-go-openai go 1.22 -require github.com/openai/openai-go v0.1.0-alpha.39 +require github.com/openai/openai-go/v3 v3.3.0 require ( github.com/tidwall/gjson v1.14.4 // indirect diff --git a/languages/go/openai/go.sum b/languages/go/openai/go.sum deleted file mode 100644 index 97b1a6f..0000000 --- a/languages/go/openai/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/openai/openai-go v0.1.0-alpha.39 h1:FvoNWy7BPhA0TjGOK5huRGU5sAUEx2jeubLXz34K9LE= -github.com/openai/openai-go v0.1.0-alpha.39/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A= -github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= -github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= -github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= -github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= -github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= diff --git a/languages/go/openai/main.go b/languages/go/openai/main.go index c661826..2118cc4 100644 --- a/languages/go/openai/main.go +++ b/languages/go/openai/main.go @@ -8,8 +8,8 @@ import ( "net/http" "os" - "github.com/openai/openai-go" - "github.com/openai/openai-go/option" + "github.com/openai/openai-go/v3" + "github.com/openai/openai-go/v3/option" ) type ModelsResponse struct { @@ -68,16 +68,17 @@ func main() { // Non-streaming chat with Model 1 fmt.Println("=== Non-Streaming Chat (Model 1) ===") + // Use full endpoint including /v1 - v3 SDK doesn't add it client1 := openai.NewClient( option.WithBaseURL(modelEndpoint1), option.WithAPIKey("dummy-key"), ) chatResponse1, err := client1.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Model: openai.F(model1ID), - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Model: openai.ChatModel(model1ID), + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Give a Python Fizzbuzz solution in one line of code?"), - }), + }, Temperature: openai.Float(0.5), MaxTokens: openai.Int(150), }) @@ -91,10 +92,10 @@ func main() { // 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{ + Model: openai.ChatModel(model1ID), + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Explain quantum entanglement in one sentence."), - }), + }, Temperature: openai.Float(0.5), MaxTokens: openai.Int(150), }) @@ -114,16 +115,17 @@ func main() { // Non-streaming chat with Model 2 fmt.Println("=== Non-Streaming Chat (Model 2) ===") + // Use full endpoint including /v1 - v3 SDK doesn't add it client2 := openai.NewClient( option.WithBaseURL(modelEndpoint2), option.WithAPIKey("dummy-key"), ) chatResponse2, err := client2.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Model: openai.F(model2ID), - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Model: openai.ChatModel(model2ID), + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Write a JavaScript function to check if a number is prime"), - }), + }, Temperature: openai.Float(0.5), MaxTokens: openai.Int(150), }) @@ -137,10 +139,10 @@ func main() { // 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{ + Model: openai.ChatModel(model2ID), + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Give a Python Fizzbuzz solution in one line of code?"), - }), + }, Temperature: openai.Float(0.5), MaxTokens: openai.Int(150), }) @@ -160,15 +162,16 @@ func main() { // TTS example fmt.Println("=== TTS Speech Generation ===") + // Use full endpoint including /v1 - v3 SDK doesn't add it ttsClient := openai.NewClient( option.WithBaseURL(ttsEndpoint1), option.WithAPIKey("dummy-key"), ) 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!"), + Model: openai.SpeechModelTTS1, + Voice: openai.AudioSpeechNewParamsVoiceAlloy, + Input: "I think so therefore, Today is a wonderful day to grow something people love!", Speed: openai.Float(0.9), }) diff --git a/languages/haskell/UncloseAI.hs b/languages/haskell/UncloseAI.hs index 4f3d1dd..c8feb41 100644 --- a/languages/haskell/UncloseAI.hs +++ b/languages/haskell/UncloseAI.hs @@ -259,8 +259,8 @@ chatStream client msgs maybeModelIdx maybeMaxToks maybeTemp = do result <- try $ do request <- parseRequest $ "POST " ++ modelEndpoint modelInfo ++ "/chat/completions" let request' = setRequestBodyJSON req request - httpSink request' $ \response -> do - responseBody response + withResponse request' $ \response -> + runConduit $ getResponseBody response .| CC.linesUnboundedAscii .| CL.mapM_ processSSELine diff --git a/languages/java/openai/Dockerfile b/languages/java/openai/Dockerfile index 87bd652..c8c222e 100644 --- a/languages/java/openai/Dockerfile +++ b/languages/java/openai/Dockerfile @@ -18,7 +18,13 @@ FROM eclipse-temurin:17-jre-alpine WORKDIR /app -# Copy jar with dependencies from builder +# Copy jar and dependencies from builder COPY --from=builder /app/target/*.jar ./uncloseai.jar +COPY --from=builder /app/target/lib ./lib -CMD ["java", "-jar", "uncloseai.jar"] +# Set environment variables for testing +ENV MODEL_ENDPOINT_1=https://hermes.ai.unturf.com/v1 +ENV MODEL_ENDPOINT_2=https://qwen.ai.unturf.com/v1 +ENV TTS_ENDPOINT_1=https://speech.ai.unturf.com/v1 + +CMD ["java", "-cp", "uncloseai.jar:lib/*", "uncloseai"] diff --git a/languages/java/openai/pom.xml b/languages/java/openai/pom.xml index ecfe69c..e79148a 100644 --- a/languages/java/openai/pom.xml +++ b/languages/java/openai/pom.xml @@ -18,7 +18,7 @@ com.openai openai-java - 0.8.1 + 4.3.0 org.json @@ -59,6 +59,18 @@ uncloseai + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + uncloseai + + + + diff --git a/languages/java/openai/uncloseai.java b/languages/java/openai/uncloseai.java index 2704f78..e6ab2f6 100644 --- a/languages/java/openai/uncloseai.java +++ b/languages/java/openai/uncloseai.java @@ -1,6 +1,7 @@ import com.openai.client.OpenAIClient; import com.openai.client.okhttp.OpenAIOkHttpClient; -import com.openai.models.*; +import com.openai.models.chat.completions.ChatCompletion; +import com.openai.models.chat.completions.ChatCompletionCreateParams; import java.io.FileOutputStream; import java.io.IOException; @@ -8,8 +9,6 @@ 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; @@ -65,14 +64,7 @@ public class uncloseai { 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() - )) + .addUserMessage("Give a Python Fizzbuzz solution in one line of code?") .temperature(0.5) .maxTokens(150L) .build(); @@ -84,14 +76,7 @@ public class uncloseai { 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() - )) + .addUserMessage("Explain quantum entanglement in one sentence.") .temperature(0.5) .maxTokens(150L) .build(); @@ -113,14 +98,7 @@ public class uncloseai { 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() - )) + .addUserMessage("Write a JavaScript function to check if a number is prime") .temperature(0.5) .maxTokens(150L) .build(); @@ -132,14 +110,7 @@ public class uncloseai { 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() - )) + .addUserMessage("Give a Python Fizzbuzz solution in one line of code?") .temperature(0.5) .maxTokens(150L) .build(); @@ -152,9 +123,9 @@ public class uncloseai { }); System.out.println("\n"); - // TTS example - not supported in openai-java 0.8.1 + // TTS example System.out.println("=== TTS Speech Generation ==="); - System.out.println("[SKIPPED] TTS not available in openai-java SDK 0.8.1\n"); + System.out.println("[SKIPPED] TTS implementation needs audio API research\n"); System.out.println("=== Examples Complete ==="); diff --git a/languages/javascript/openai/nodejs/package.json b/languages/javascript/openai/nodejs/package.json index c474419..7643219 100644 --- a/languages/javascript/openai/nodejs/package.json +++ b/languages/javascript/openai/nodejs/package.json @@ -22,6 +22,6 @@ "node": ">=18.0.0" }, "dependencies": { - "openai": "^4.77.0" + "openai": "6.3.0" } } diff --git a/languages/mojo/Dockerfile b/languages/mojo/Dockerfile index 62f2710..043d307 100644 --- a/languages/mojo/Dockerfile +++ b/languages/mojo/Dockerfile @@ -1,18 +1,44 @@ -# Mojo examples (source code reference) -# Note: Mojo SDK requires Modular license which isn't freely available in Docker -# We provide Python equivalents that demonstrate the same patterns -FROM python:3.13-alpine +# Mojo language container built from Ubuntu (Modular supports Ubuntu/Debian) +FROM ubuntu:24.04 WORKDIR /app -# Install HTTP client -RUN pip install --no-cache-dir httpx==0.28.1 +# Install dependencies +RUN apt-get update && apt-get install -y \ + curl \ + ca-certificates \ + python3 \ + python3-pip \ + python3-venv \ + && rm -rf /var/lib/apt/lists/* -# Copy source files +# Create virtual environment for pip packages +RUN python3 -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +# Install Modular CLI +RUN curl -s https://get.modular.com | sh - + +# Add modular to PATH +ENV PATH="/root/.modular/bin:$PATH" + +# Copy Mojo source files COPY hermes_nonstreaming.mojo . COPY qwen_nonstreaming.mojo . -COPY uncloseai.py . COPY README.md . -# Default command shows README and runs Python equivalent -CMD ["sh", "-c", "echo '=== Mojo Examples (Reference) ===\n' && cat README.md && echo '\n\n=== Running Python Equivalent ===\n' && python uncloseai.py"] +# Create entrypoint script +RUN echo '#!/bin/bash\n\ +if [ -z "$MODULAR_AUTH" ]; then\n\ + echo "ERROR: MODULAR_AUTH environment variable not set"\n\ + echo "Get your auth key from: https://developer.modular.com/"\n\ + echo "Then run: docker run -e MODULAR_AUTH=your-key ai-unturf-mojo"\n\ + exit 1\n\ +fi\n\ +modular auth $MODULAR_AUTH\n\ +modular install mojo\n\ +magic run mojo hermes_nonstreaming.mojo\n\ +' > /app/run.sh && chmod +x /app/run.sh + +# Default: run Mojo example +CMD ["/app/run.sh"] diff --git a/languages/mojo/uncloseai.py b/languages/mojo/uncloseai.py deleted file mode 100644 index 986f228..0000000 --- a/languages/mojo/uncloseai.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python3 -# uncloseai. - Python equivalent demonstrating patterns shown in Mojo examples -# This runs in place of Mojo since Mojo SDK requires Modular license - -import os -import httpx -import json - -print("=== uncloseai. Mojo Examples (Python Equivalent) ===\n") - -# Discover endpoints from environment variables -model_endpoint_1 = os.getenv("MODEL_ENDPOINT_1") -model_endpoint_2 = os.getenv("MODEL_ENDPOINT_2") -tts_endpoint_1 = os.getenv("TTS_ENDPOINT_1") - -if not model_endpoint_1 or not model_endpoint_2 or not tts_endpoint_1: - print("ERROR: No models discovered. Set environment variables:") - print(" MODEL_ENDPOINT_1, MODEL_ENDPOINT_2, TTS_ENDPOINT_1") - exit(1) - -# Discover models from endpoint 1 -print(f"Discovering models from {model_endpoint_1}...") -response1 = httpx.get(f"{model_endpoint_1}/models") -models1 = response1.json()["data"] -model_1_id = models1[0]["id"] -print(f"Model 1: {model_1_id}\n") - -# Discover models from endpoint 2 -print(f"Discovering models from {model_endpoint_2}...") -response2 = httpx.get(f"{model_endpoint_2}/models") -models2 = response2.json()["data"] -model_2_id = models2[0]["id"] -print(f"Model 2: {model_2_id}\n") - -# Non-streaming chat with Model 1 -print("=== Non-Streaming Chat (Model 1) ===") -payload1 = { - "model": model_1_id, - "messages": [{"role": "user", "content": "Give a Python Fizzbuzz solution in one line of code?"}], - "temperature": 0.5, - "max_tokens": 150 -} -chat_response1 = httpx.post(f"{model_endpoint_1}/chat/completions", json=payload1) -content1 = chat_response1.json()["choices"][0]["message"]["content"] -print(f"Response: {content1}\n") - -# Non-streaming chat with Model 2 -print("=== Non-Streaming Chat (Model 2) ===") -payload2 = { - "model": model_2_id, - "messages": [{"role": "user", "content": "Give a Python Fizzbuzz solution in one line of code?"}], - "temperature": 0.5, - "max_tokens": 150 -} -chat_response2 = httpx.post(f"{model_endpoint_2}/chat/completions", json=payload2) -content2 = chat_response2.json()["choices"][0]["message"]["content"] -print(f"Response: {content2}\n") - -# TTS example -print("=== TTS Speech Generation ===") -tts_payload = { - "model": "tts-1", - "voice": "alloy", - "input": "I think so therefore, Today is a wonderful day to grow something people love!", - "speed": 0.9 -} -tts_response = httpx.post(f"{tts_endpoint_1}/audio/speech", json=tts_payload) -with open("speech.mp3", "wb") as f: - f.write(tts_response.content) -print(f"[OK] Speech file created: speech.mp3 ({len(tts_response.content)} bytes)\n") - -print("=== Examples Complete ===") -print("\nNote: The .mojo files in this directory show what this would look like") -print("in Mojo. We run Python equivalents since Mojo SDK requires Modular license.")