Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env-example
Original file line number Diff line number Diff line change
Expand Up @@ -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=
89 changes: 87 additions & 2 deletions lib/coderacer/ai.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,36 @@ 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.

Context: Create a practical code snippet that demonstrates real-world usage.
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)
Expand All @@ -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")}"
Expand Down
2 changes: 1 addition & 1 deletion lib/coderacer_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion test/coderacer/ai_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down