From 94cc4a87941dfe58631450089e8433ad0ba7cda6 Mon Sep 17 00:00:00 2001 From: Riza Fahmi Date: Thu, 5 Jun 2025 14:50:38 +0700 Subject: [PATCH 1/2] Change to vertex ai --- .env-example | 1 + lib/coderacer/ai.ex | 89 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/.env-example b/.env-example index f3edd77..01455bc 100644 --- a/.env-example +++ b/.env-example @@ -2,3 +2,4 @@ GEMINI_API_KEY= DATABASE_PATH=./coderacer.db SECRET_KEY_BASE=run `mix phx.gen.secret` to get the key PHX_HOST=127.0.0.1 +VERTEX_API_KEY= diff --git a/lib/coderacer/ai.ex b/lib/coderacer/ai.ex index c1c7ecc..ffa81b3 100644 --- a/lib/coderacer/ai.ex +++ b/lib/coderacer/ai.ex @@ -3,7 +3,28 @@ defmodule Coderacer.AI do Module documentation for Coderacer.AI. """ def generate(language, difficulty, lines \\ 10) do - # Simulate code generation based on language and difficulty + system = + """ + You are a code generation assistant that creates diverse, real-world programming exercises. + + DIFFICULTY LEVELS: + - Easy: Simple syntax, common patterns, basic control structures, short variable names + - Medium: Moderate complexity, some nesting, standard library usage, descriptive names + - Hard: Complex syntax, advanced patterns, multiple concepts combined, longer identifiers + + REQUIREMENTS: + 1. Generate exactly #{lines} lines of functional, compilable code + 2. Use real-world scenarios (web apps, data processing, algorithms, etc.) + 3. Follow language best practices and conventions + 4. Vary code patterns - avoid repetitive structures + 5. Include diverse concepts: functions, classes, loops, conditionals, data structures + 6. Use realistic variable/function names, not placeholders + + OUTPUT FORMAT: + Return only the raw code without markdown, comments explaining the exercise, or extra text. + The code should be immediately usable and represent a complete, meaningful snippet. + """ + prompt = """ Generate at least #{lines} lines of #{language} code with #{difficulty} typing difficulty. @@ -11,7 +32,7 @@ defmodule Coderacer.AI do Ensure variety in syntax patterns and avoid repetitive structures. """ - case send(prompt) do + case ask_vertex(system, prompt) do %Req.Response{status: 200, body: body} -> result = parse_body(body) @@ -24,6 +45,70 @@ defmodule Coderacer.AI do end end + def ask_vertex(system, prompt) do + project_id = "genai-441313" + location_id = "global" + api_endpoint = "aiplatform.googleapis.com" + model_id = "gemini-2.0-flash-lite-001" + generate_content_api = "generateContent" + + url = + "https://#{api_endpoint}/v1/projects/#{project_id}/locations/#{location_id}/publishers/google/models/#{model_id}:#{generate_content_api}" + + http_client = Application.get_env(:coderacer, :http_client, Req) + + http_client.post!( + url, + headers: [ + {"Content-Type", "application/json"}, + {"Authorization", "Bearer #{System.get_env("VERTEX_API_KEY")}"} + ], + json: %{ + contents: [ + %{role: "user", parts: [%{text: prompt}]} + ], + systemInstruction: %{ + parts: [%{text: system}] + }, + generationConfig: %{ + temperature: 0.7, + topP: 0.8, + max_output_tokens: 6_400, + responseMimeType: "application/json", + responseSchema: %{ + type: "object", + properties: %{ + response: %{ + type: "STRING", + description: + "Analysis of the typing test results and programming language suitability" + } + }, + required: ["response"] + } + }, + safetySettings: [ + %{ + category: "HARM_CATEGORY_HATE_SPEECH", + threshold: "OFF" + }, + %{ + category: "HARM_CATEGORY_DANGEROUS_CONTENT", + threshold: "OFF" + }, + %{ + category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", + threshold: "OFF" + }, + %{ + category: "HARM_CATEGORY_HARASSMENT", + threshold: "OFF" + } + ] + } + ) + end + def send(prompt, lines \\ 10) do url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=#{System.get_env("GEMINI_API_KEY")}" From 1452a4b875a622c837284793a31ce61a6eafd90f Mon Sep 17 00:00:00 2001 From: Riza Fahmi Date: Thu, 5 Jun 2025 14:59:41 +0700 Subject: [PATCH 2/2] Fix test case change to vertex ai --- lib/coderacer_web/endpoint.ex | 2 +- mix.exs | 2 +- test/coderacer/ai_test.exs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/coderacer_web/endpoint.ex b/lib/coderacer_web/endpoint.ex index 7b3147e..8e11599 100644 --- a/lib/coderacer_web/endpoint.ex +++ b/lib/coderacer_web/endpoint.ex @@ -26,7 +26,7 @@ defmodule CoderacerWeb.Endpoint do gzip: not code_reloading?, only: CoderacerWeb.static_paths() - if Code.ensure_loaded?(Tidewave) do + if Mix.env() == :dev and Code.ensure_loaded?(Tidewave) do plug Tidewave end diff --git a/mix.exs b/mix.exs index 252c58e..e1ed4f3 100644 --- a/mix.exs +++ b/mix.exs @@ -78,7 +78,7 @@ defmodule Coderacer.MixProject do {:bandit, "~> 1.5"}, {:dialyxir, "~> 1.3", only: [:dev], runtime: false}, {:credo, "~> 1.7", only: [:dev], runtime: false}, - {:tidewave, "~> 0.1.7", only: [:dev, :test]} + {:tidewave, "~> 0.1.7", only: [:dev]} ] end diff --git a/test/coderacer/ai_test.exs b/test/coderacer/ai_test.exs index e03defd..176fab1 100644 --- a/test/coderacer/ai_test.exs +++ b/test/coderacer/ai_test.exs @@ -5,7 +5,7 @@ defmodule Coderacer.AITest do defmodule MockReq do def post!(url, _opts) do # Verify the request is going to the correct endpoint - assert String.contains?(url, "generativelanguage.googleapis.com") + assert String.contains?(url, "aiplatform.googleapis.com") # Return a mock response with a known code snippet %Req.Response{