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
6 changes: 3 additions & 3 deletions config/config.sample.edn
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@
:url "http://localhost:3003",
:ebay {:appid ""},
:gemini {:api {:key ""
;; optional: override the default model (gemini-3.1-flash-image-preview)
;; :model "gemini-3.1-flash-image-preview"
;; optional: override the default model (gemini-3.6-flash-image-preview)
;; :model "gemini-3.6-flash-image-preview"
;; monthly budget in USD for image generation (default: 10.00)
;; :monthly-budget 10.00
;; estimated cost per image in USD (default: 0.045 for Gemini 3.1 Flash 512px)
;; estimated cost per image in USD (default: 0.045 for Gemini 3.6 Flash 512px)
;; :cost-per-image 0.045
}}
:giphy {:key ""},
Expand Down
2 changes: 1 addition & 1 deletion src/yetibot/core/commands/agent.clj
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
(:value (get-config ::str path)))

;; Gemini model for the agent. Defaults to the cheapest current Flash model;
;; override with [:gemini :agent :model] (e.g. "gemini-3.1-pro-preview") for reasoning.
;; override with [:gemini :agent :model] (e.g. "gemini-3.6-pro-preview") for reasoning.
(defn model [] (or (config-str [:gemini :agent :model]) "gemini-3.6-flash"))

(defn gemini-key [] (config-str [:gemini :key]))
Expand Down
12 changes: 6 additions & 6 deletions src/yetibot/core/commands/veo.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
(some-> msg (string/replace #"key=[^\s&\"]+" "key=***")))

(def model-presets
{"lite" {:model "veo-3.1-lite-generate-preview" :duration 4}
"fast" {:model "veo-3.1-fast-generate-preview" :duration 4}
"gigaveo" {:model "veo-3.1-generate-preview" :duration 8}
"preview" {:model "veo-3.1-generate-preview" :duration 8}
"better" {:model "veo-3.1-generate-preview" :duration 8}})
{"lite" {:model "veo-3.6-lite-generate-preview" :duration 4}
"fast" {:model "veo-3.6-fast-generate-preview" :duration 4}
"gigaveo" {:model "veo-3.6-generate-preview" :duration 8}
"preview" {:model "veo-3.6-generate-preview" :duration 8}
"better" {:model "veo-3.6-generate-preview" :duration 8}})

(defn parse-model-and-prompt
[raw-prompt]
Expand Down Expand Up @@ -47,7 +47,7 @@

(defn veo-cmd
"veo <prompt> # generate a short AI video with Veo
gigaveo <prompt> # generate a high-quality 8-second video with flagship Veo 3.1 model
gigaveo <prompt> # generate a high-quality 8-second video with flagship Veo 3.6 model

Examples:
veo a cat jumping
Expand Down
8 changes: 4 additions & 4 deletions src/yetibot/core/util/gemini.clj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
;; (YB_GEMINI_KEY) with the rest of Yetibot's Gemini features.
(def config (or (:value (get-config ::config [:gemini])) {}))

(def default-model "gemini-3.1-flash-image-preview")
(def default-model "gemini-3.6-flash-image-preview")

(defn gemini-model [] default-model)

Expand All @@ -48,7 +48,7 @@
;; -- Monthly budget throttling --

(def ^:private default-cost-per-image
"Default estimated cost per generated image in USD (gemini-3.1-flash-image-preview pricing, tied to default-model)."
"Default estimated cost per generated image in USD (gemini-3.6-flash-image-preview pricing, tied to default-model)."
0.039)

(def ^:private default-monthly-budget
Expand All @@ -58,7 +58,7 @@
(defn cost-per-image []
(or (parse-number (-> config :cost :per))
(case (gemini-model)
"gemini-3.1-flash-image-preview" 0.039
"gemini-3.6-flash-image-preview" 0.039
;; Add other models and their costs here as needed
default-cost-per-image)))

Expand Down Expand Up @@ -340,7 +340,7 @@

(def ^:private api-base "https://generativelanguage.googleapis.com/v1beta")

(def default-veo-model "veo-3.1-lite-generate-preview")
(def default-veo-model "veo-3.6-lite-generate-preview")

(defn veo-model [] (or (-> config :veo :model) default-veo-model))

Expand Down
4 changes: 2 additions & 2 deletions test/yetibot/core/test/commands/bameme_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
(facts "about bameme-cmd"
(fact "it generates a meme and returns URL with model and cost footer"
(bm/bameme-cmd {:match "bameme drake: writing tests / shipping to prod" :chat-source {}})
=> (contains {:result/value #"http://localhost:3003/generated-images/img123.png\n\nSent via gemini-3.1-flash-image-preview \| Cost: \$0.039"
=> (contains {:result/value #"http://localhost:3003/generated-images/img123.png\n\nSent via gemini-3.6-flash-image-preview \| Cost: \$0.039"
:result/data {:id "img123" :prompt "bameme drake: writing tests / shipping to prod" :url "http://localhost:3003/generated-images/img123.png"}})
(provided
(gemini/configured?) => true
(yetibot.core.util.image-input/extract-images "bameme drake: writing tests / shipping to prod" {}) => {:prompt "drake: writing tests / shipping to prod" :image-urls []}
(gemini/generate-image "Create a meme in the style of the 'drake' meme template with this text: writing tests / shipping to prod" anything []) => {:data "bytes" :mime-type "image/png"}
(yetibot.core.webapp.routes.images/store-image! {:data "bytes" :mime-type "image/png"}) => "img123"
(gemini/yetibot-base-url) => "http://localhost:3003"
(gemini/gemini-model) => "gemini-3.1-flash-image-preview"
(gemini/gemini-model) => "gemini-3.6-flash-image-preview"
(gemini/cost-per-image) => 0.039)))
4 changes: 2 additions & 2 deletions test/yetibot/core/test/commands/banana_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@
(facts "about banana-cmd"
(fact "it generates an image and returns URL with model and cost footer"
(b/banana-cmd {:match "banana monkey" :chat-source {}})
=> (contains {:result/value #"http://localhost:3003/generated-images/img123.png\n\nSent via gemini-3.1-flash-image-preview \| Cost: \$0.039"
=> (contains {:result/value #"http://localhost:3003/generated-images/img123.png\n\nSent via gemini-3.6-flash-image-preview \| Cost: \$0.039"
:result/data {:id "img123" :prompt "banana monkey" :url "http://localhost:3003/generated-images/img123.png"}})
(provided
(gemini/configured?) => true
(yetibot.core.util.image-input/extract-images "banana monkey" {}) => {:prompt "monkey" :image-urls []}
(gemini/generate-image "Generate an image: monkey" b/banana-system-instruction []) => {:data "bytes" :mime-type "image/png"}
(yetibot.core.webapp.routes.images/store-image! {:data "bytes" :mime-type "image/png"}) => "img123"
(gemini/yetibot-base-url) => "http://localhost:3003"
(gemini/gemini-model) => "gemini-3.1-flash-image-preview"
(gemini/gemini-model) => "gemini-3.6-flash-image-preview"
(gemini/cost-per-image) => 0.039)))
22 changes: 11 additions & 11 deletions test/yetibot/core/test/commands/veo.clj
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
(provided
(gemini/configured?) => true
(image-input/extract-images "a cool robot dancing" {}) => {:prompt "a cool robot dancing" :image-urls nil}
(gemini/generate-video "a cool robot dancing" nil "veo-3.1-lite-generate-preview" 4) => :video-bytes
(gemini/generate-video "a cool robot dancing" nil "veo-3.6-lite-generate-preview" 4) => :video-bytes
(store-image! :video-bytes) => "img123"
(gemini/yetibot-base-url) => "http://localhost:3000"
(gemini/calculate-video-cost "veo-3.1-lite-generate-preview" 4) => 0.20
(gemini/calculate-video-cost "veo-3.6-lite-generate-preview" 4) => 0.20
(chat/send-msg "<@user123>: http://localhost:3000/generated-images/img123.mp4 (Cost: $0.20)") => anything)))

(fact "future handles failure, posts error message"
Expand All @@ -51,25 +51,25 @@
(provided
(gemini/configured?) => true
(image-input/extract-images "a cool robot dancing" {}) => {:prompt "a cool robot dancing" :image-urls nil}
(gemini/generate-video "a cool robot dancing" nil "veo-3.1-lite-generate-preview" 4) => (throw (Exception. "API Error"))
(gemini/generate-video "a cool robot dancing" nil "veo-3.6-lite-generate-preview" 4) => (throw (Exception. "API Error"))
(chat/send-msg "<@user123>: Video generation failed: API Error") => anything))))

(facts "about veo model and prompt parsing"
(fact "correctly parses lite preset"
(veo/parse-model-and-prompt "lite a cute cat")
=> {:model "veo-3.1-lite-generate-preview" :duration 4 :prompt "a cute cat"})
=> {:model "veo-3.6-lite-generate-preview" :duration 4 :prompt "a cute cat"})

(fact "correctly parses fast preset"
(veo/parse-model-and-prompt "fast a cute cat")
=> {:model "veo-3.1-fast-generate-preview" :duration 4 :prompt "a cute cat"})
=> {:model "veo-3.6-fast-generate-preview" :duration 4 :prompt "a cute cat"})

(fact "correctly parses gigaveo preset"
(veo/parse-model-and-prompt "gigaveo a cute cat")
=> {:model "veo-3.1-generate-preview" :duration 8 :prompt "a cute cat"})
=> {:model "veo-3.6-generate-preview" :duration 8 :prompt "a cute cat"})

(fact "correctly parses better preset"
(veo/parse-model-and-prompt "better a cute cat")
=> {:model "veo-3.1-generate-preview" :duration 8 :prompt "a cute cat"})
=> {:model "veo-3.6-generate-preview" :duration 8 :prompt "a cute cat"})

(fact "ignores preset when no prompt text follows"
(veo/parse-model-and-prompt "lite")
Expand All @@ -90,10 +90,10 @@
(provided
(gemini/configured?) => true
(image-input/extract-images "lite a cool robot" {}) => {:prompt "lite a cool robot" :image-urls nil}
(gemini/generate-video "a cool robot" nil "veo-3.1-lite-generate-preview" 4) => :video-bytes
(gemini/generate-video "a cool robot" nil "veo-3.6-lite-generate-preview" 4) => :video-bytes
(store-image! :video-bytes) => "img123"
(gemini/yetibot-base-url) => "http://localhost:3000"
(gemini/calculate-video-cost "veo-3.1-lite-generate-preview" 4) => 0.20
(gemini/calculate-video-cost "veo-3.6-lite-generate-preview" 4) => 0.20
(chat/send-msg "<@user123>: http://localhost:3000/generated-images/img123.mp4 (Cost: $0.20)") => anything)))

(fact "veo-cmd with gigaveo cmd generates 8s video with flagship model"
Expand All @@ -106,10 +106,10 @@
(provided
(gemini/configured?) => true
(image-input/extract-images "a cool robot" {}) => {:prompt "a cool robot" :image-urls nil}
(gemini/generate-video "a cool robot" nil "veo-3.1-generate-preview" 8) => :video-bytes
(gemini/generate-video "a cool robot" nil "veo-3.6-generate-preview" 8) => :video-bytes
(store-image! :video-bytes) => "img123"
(gemini/yetibot-base-url) => "http://localhost:3000"
(gemini/calculate-video-cost "veo-3.1-generate-preview" 8) => 3.20
(gemini/calculate-video-cost "veo-3.6-generate-preview" 8) => 3.20
(chat/send-msg "<@user123>: http://localhost:3000/generated-images/img123.mp4 (Cost: $3.20)") => anything))))

(facts "about redact"
Expand Down
4 changes: 2 additions & 2 deletions test/yetibot/core/test/commands/weathermap_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

(fact "it generates a weather map image and returns URL"
(wm/weathermap-cmd {:chat-source {} :user {:username "test-user"}})
=> (contains {:result/value #"http://localhost:3003/generated-images/img456.png\n\nSent via gemini-3.1-flash-image-preview \| Cost: \$0.039"
=> (contains {:result/value #"http://localhost:3003/generated-images/img456.png\n\nSent via gemini-3.6-flash-image-preview \| Cost: \$0.039"
:result/data {:id "img456"
:prompt "A highly detailed, professional weather map of North America showing temperature heat map, wind movements (using beautiful swirling arrows and streamlines), and air quality index overlays. Use modern weather graphics. The current conditions for reference in some cities are: Edmonton: 15C, Sunnyvale: 25C"
:url "http://localhost:3003/generated-images/img456.png"}})
Expand All @@ -20,5 +20,5 @@
(gemini/generate-image "A highly detailed, professional weather map of North America showing temperature heat map, wind movements (using beautiful swirling arrows and streamlines), and air quality index overlays. Use modern weather graphics. The current conditions for reference in some cities are: Edmonton: 15C, Sunnyvale: 25C" anything) => {:data "bytes" :mime-type "image/png"}
(yetibot.core.webapp.routes.images/store-image! {:data "bytes" :mime-type "image/png"}) => "img456"
(gemini/yetibot-base-url) => "http://localhost:3003"
(gemini/gemini-model) => "gemini-3.1-flash-image-preview"
(gemini/gemini-model) => "gemini-3.6-flash-image-preview"
(gemini/cost-per-image) => 0.039)))
8 changes: 4 additions & 4 deletions test/yetibot/core/test/util/gemini_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@

(facts "about model pricing"
(fact "it maps pro models to pro pricing"
(gemini/model-pricing "gemini-3.1-pro") => {:input 2.00 :cached 0.50 :output 12.00}
(gemini/model-pricing "gemini-3.1-pro-preview-customtools") => {:input 2.00 :cached 0.50 :output 12.00})
(gemini/model-pricing "gemini-3.6-pro") => {:input 2.00 :cached 0.50 :output 12.00}
(gemini/model-pricing "gemini-3.6-pro-preview-customtools") => {:input 2.00 :cached 0.50 :output 12.00})
(fact "it maps flash-lite models to lite pricing"
(gemini/model-pricing "gemini-2.5-flash-lite") => {:input 0.10 :cached 0.025 :output 0.40})
(fact "it maps flash models to flash pricing"
(gemini/model-pricing "gemini-3.1-flash") => {:input 0.075 :cached 0.01875 :output 0.30})
(gemini/model-pricing "gemini-3.6-flash") => {:input 0.075 :cached 0.01875 :output 0.30})
(fact "it defaults to pro pricing"
(gemini/model-pricing "unknown-model") => {:input 2.00 :cached 0.50 :output 12.00}))

(facts "about stats cost calculation"
(fact "it calculates correct cost based on tokens and model type"
(gemini/calculate-stats-cost
{:models {:gemini-3.1-pro-preview {:tokens {:input 100000 :candidates 10000 :cached 0}}}})
{:models {:gemini-3.6-pro-preview {:tokens {:input 100000 :candidates 10000 :cached 0}}}})
=> (roughly 0.32)
(gemini/calculate-stats-cost
{:models {:gemini-2.5-flash-lite {:tokens {:input 50000 :candidates 2000 :cached 10000}}}})
Expand Down