From bb41094ef51943c9addf87b320c586bf2a716d08 Mon Sep 17 00:00:00 2001 From: Tyler Thomas Date: Tue, 26 Mar 2024 19:47:52 +0000 Subject: [PATCH 1/4] https -> http, fix bug with http_kwargs --- Project.toml | 2 +- src/GoogleGenAI.jl | 56 +++++++++++++++++++++++----------------------- test/runtests.jl | 10 +++++++-- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/Project.toml b/Project.toml index 06511d6..283ce48 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GoogleGenAI" uuid = "903d41d1-eaca-47dd-943b-fee3930375ab" authors = ["Tyler Thomas "] -version = "0.2.0" +version = "0.3.0" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" diff --git a/src/GoogleGenAI.jl b/src/GoogleGenAI.jl index fb19d00..f9b84f6 100644 --- a/src/GoogleGenAI.jl +++ b/src/GoogleGenAI.jl @@ -84,11 +84,11 @@ end #TODO: Should we use different function names? """ - generate_content(provider::AbstractGoogleProvider, model_name::String, prompt::String, image_path::String; api_kwargs=NamedTuple(), https_kwargs=NamedTuple()) -> NamedTuple - generate_content(api_key::String, model_name::String, prompt::String, image_path::String; api_kwargs=NamedTuple(), https_kwargs=NamedTuple()) -> NamedTuple + generate_content(provider::AbstractGoogleProvider, model_name::String, prompt::String, image_path::String; api_kwargs=NamedTuple(), http_kwargs=NamedTuple()) -> NamedTuple + generate_content(api_key::String, model_name::String, prompt::String, image_path::String; api_kwargs=NamedTuple(), http_kwargs=NamedTuple()) -> NamedTuple - generate_content(provider::AbstractGoogleProvider, model_name::String, conversation::Vector{Dict{Symbol,Any}}; api_kwargs=NamedTuple(), https_kwargs=NamedTuple()) -> NamedTuple - generate_content(api_key::String, model_name::String, conversation::Vector{Dict{Symbol,Any}}; api_kwargs=NamedTuple(), https_kwargs=NamedTuple()) -> NamedTuple + generate_content(provider::AbstractGoogleProvider, model_name::String, conversation::Vector{Dict{Symbol,Any}}; api_kwargs=NamedTuple(), http_kwargs=NamedTuple()) -> NamedTuple + generate_content(api_key::String, model_name::String, conversation::Vector{Dict{Symbol,Any}}; api_kwargs=NamedTuple(), http_kwargs=NamedTuple()) -> NamedTuple Generate content based on a combination of text prompt and an image (optional). @@ -122,7 +122,7 @@ function generate_content( model_name::String, prompt::String; api_kwargs=NamedTuple(), - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) endpoint = "models/$model_name:generateContent" @@ -141,7 +141,7 @@ function generate_content( "safetySettings" => safety_settings, ) - response = _request(provider, endpoint, :POST, body; https_kwargs...) + response = _request(provider, endpoint, :POST, body; http_kwargs...) return _parse_response(response) end function generate_content( @@ -149,10 +149,10 @@ function generate_content( model_name::String, prompt::String; api_kwargs=NamedTuple(), - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) return generate_content( - GoogleProvider(; api_key), model_name, prompt; api_kwargs, https_kwargs + GoogleProvider(; api_key), model_name, prompt; api_kwargs, http_kwargs ) end @@ -162,7 +162,7 @@ function generate_content( prompt::String, image_path::String; api_kwargs=NamedTuple(), - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) image_data = open(base64encode, image_path) safety_settings = get(api_kwargs, :safety_settings, nothing) @@ -189,7 +189,7 @@ function generate_content( ) response = _request( - provider, "models/$model_name:generateContent", :POST, body; https_kwargs... + provider, "models/$model_name:generateContent", :POST, body; http_kwargs... ) return _parse_response(response) end @@ -199,10 +199,10 @@ function generate_content( prompt::String, image_path::String; api_kwargs=NamedTuple(), - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) return generate_content( - GoogleProvider(; api_key), model_name, prompt, image_path; api_kwargs, https_kwargs + GoogleProvider(; api_key), model_name, prompt, image_path; api_kwargs, http_kwargs ) end @@ -211,7 +211,7 @@ function generate_content( model_name::String, conversation::Vector{Dict{Symbol,Any}}; api_kwargs=NamedTuple(), - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) endpoint = "models/$model_name:generateContent" @@ -236,7 +236,7 @@ function generate_content( "safetySettings" => safety_settings, ) - response = _request(provider, endpoint, :POST, body; https_kwargs) + response = _request(provider, endpoint, :POST, body; http_kwargs...) return _parse_response(response) end function generate_content( @@ -244,10 +244,10 @@ function generate_content( model_name::String, conversation::Vector{Dict{Symbol,Any}}; api_kwargs=NamedTuple(), - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) return generate_content( - GoogleProvider(; api_key), model_name, conversation; api_kwargs, https_kwargs + GoogleProvider(; api_key), model_name, conversation; api_kwargs, http_kwargs ) end @@ -278,10 +278,10 @@ function count_tokens(api_key::String, model_name::String, prompt::String) end """ - embed_content(provider::AbstractGoogleProvider, model_name::String, prompt::String https_kwargs=NamedTuple()) -> NamedTuple - embed_content(api_key::String, model_name::String, prompt::String https_kwargs=NamedTuple()) -> NamedTuple - embed_content(provider::AbstractGoogleProvider, model_name::String, prompts::Vector{String} https_kwargs=NamedTuple()) -> Vector{NamedTuple} - embed_content(api_key::String, model_name::String, prompts::Vector{String}, https_kwargs=NamedTuple()) -> Vector{NamedTuple} + embed_content(provider::AbstractGoogleProvider, model_name::String, prompt::String http_kwargs=NamedTuple()) -> NamedTuple + embed_content(api_key::String, model_name::String, prompt::String http_kwargs=NamedTuple()) -> NamedTuple + embed_content(provider::AbstractGoogleProvider, model_name::String, prompts::Vector{String} http_kwargs=NamedTuple()) -> Vector{NamedTuple} + embed_content(api_key::String, model_name::String, prompts::Vector{String}, http_kwargs=NamedTuple()) -> Vector{NamedTuple} Generate an embedding for the given prompt text using the specified model. @@ -303,30 +303,30 @@ function embed_content( provider::AbstractGoogleProvider, model_name::String, prompt::String; - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) endpoint = "models/$model_name:embedContent" body = Dict( "model" => "models/$model_name", "content" => Dict("parts" => [Dict("text" => prompt)]), ) - response = _request(provider, endpoint, :POST, body; https_kwargs...) + response = _request(provider, endpoint, :POST, body; http_kwargs...) embedding_values = get( get(JSON3.read(response.body), "embedding", Dict()), "values", Vector{Float64}() ) return (values=embedding_values, response_status=response.status) end function embed_content( - api_key::String, model_name::String, prompt::String, https_kwargs=NamedTuple() + api_key::String, model_name::String, prompt::String, http_kwargs=NamedTuple() ) - return embed_content(GoogleProvider(; api_key), model_name, prompt; https_kwargs...) + return embed_content(GoogleProvider(; api_key), model_name, prompt; http_kwargs...) end function embed_content( provider::AbstractGoogleProvider, model_name::String, prompts::Vector{String}, - https_kwargs=NamedTuple(), + http_kwargs=NamedTuple(), ) endpoint = "models/$model_name:batchEmbedContents" body = Dict( @@ -337,7 +337,7 @@ function embed_content( ) for prompt in prompts ], ) - response = _request(provider, endpoint, :POST, body; https_kwargs...) + response = _request(provider, endpoint, :POST, body; http_kwargs...) embedding_values = [ get(embedding, "values", Vector{Float64}()) for embedding in JSON3.read(response.body)["embeddings"] @@ -345,9 +345,9 @@ function embed_content( return (values=embedding_values, response_status=response.status) end function embed_content( - api_key::String, model_name::String, prompts::Vector{String}, https_kwargs=NamedTuple() + api_key::String, model_name::String, prompts::Vector{String}, http_kwargs=NamedTuple() ) - return embed_content(GoogleProvider(; api_key), model_name, prompts; https_kwargs...) + return embed_content(GoogleProvider(; api_key), model_name, prompts; http_kwargs...) end """ diff --git a/test/runtests.jl b/test/runtests.jl index 875db22..bece8dd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,8 +7,11 @@ if haskey(ENV, "GOOGLE_API_KEY") @testset "GoogleGenAI.jl" begin api_kwargs = (max_output_tokens=50,) + http_kwargs = (retries=2,) # Generate text from text - response = generate_content(secret_key, "gemini-pro", "Hello"; api_kwargs) + response = generate_content( + secret_key, "gemini-pro", "Hello"; api_kwargs, http_kwargs + ) # Generate text from text+image response = generate_content( @@ -17,11 +20,14 @@ if haskey(ENV, "GOOGLE_API_KEY") "What is this picture?", "example.jpg"; api_kwargs, + http_kwargs, ) # Multi-turn conversation conversation = [Dict(:role => "user", :parts => [Dict(:text => "Hello")])] - response = generate_content(secret_key, "gemini-pro", conversation; api_kwargs) + response = generate_content( + secret_key, "gemini-pro", conversation; api_kwargs, http_kwargs + ) n_tokens = count_tokens(secret_key, "gemini-pro", "Hello") @test n_tokens == 1 From d5ee203b8a73c6f863c17c31b448b10c8ad8cf51 Mon Sep 17 00:00:00 2001 From: Tyler Thomas Date: Tue, 26 Mar 2024 19:54:15 +0000 Subject: [PATCH 2/4] add Downgrade.yml --- .github/workflows/Downgrade.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/Downgrade.yml diff --git a/.github/workflows/Downgrade.yml b/.github/workflows/Downgrade.yml new file mode 100644 index 0000000..aca7e41 --- /dev/null +++ b/.github/workflows/Downgrade.yml @@ -0,0 +1,28 @@ +name: Downgrade +on: + pull_request: + branches: + - main + paths-ignore: + - 'docs/**' + push: + branches: + - main + paths-ignore: + - 'docs/**' +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + version: ['1'] + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + - uses: cjdoris/julia-downgrade-compat-action@v1 + with: + skip: Pkg,TOML + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 From f3c5c067fd14163d87cae1961f446af0396b44cc Mon Sep 17 00:00:00 2001 From: Tyler Thomas Date: Tue, 26 Mar 2024 19:55:50 +0000 Subject: [PATCH 3/4] Fix issues identified by Downgrade --- Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 283ce48..13b7fd3 100644 --- a/Project.toml +++ b/Project.toml @@ -11,11 +11,11 @@ JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" [compat] Aqua = "0.8" -Base64 = "1" -Dates = "1" +Base64 = "<0.0.1, 1" +Dates = "<0.0.1, 1" HTTP = "1" JSON3 = "1" -Test = "1" +Test = "<0.0.1, 1" julia = "1" [extras] From df65cb66a7025e8cb273f71c6d0152dcf3fc27a4 Mon Sep 17 00:00:00 2001 From: Tyler Thomas Date: Tue, 26 Mar 2024 19:57:52 +0000 Subject: [PATCH 4/4] bump aqua.jl to fix bug with persistent tasks --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 13b7fd3..08c9f02 100644 --- a/Project.toml +++ b/Project.toml @@ -10,7 +10,7 @@ HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" [compat] -Aqua = "0.8" +Aqua = "0.8.4" Base64 = "<0.0.1, 1" Dates = "<0.0.1, 1" HTTP = "1"