Commit fa73289

mo khan <mo@mokhan.ca>
2026-08-13 16:32:43
fix: stop dots from hanging indefinitely
1 parent 7b3850c
Changed files (1)
lib
lib/elelem/ollama.rb
@@ -3,9 +3,21 @@
 module Elelem
   module Net
     class Ollama
-      def initialize(model:, host: "localhost:11434", http: Elelem::Net.http)
+      def initialize(
+        model:,
+        host: "localhost:11434",
+        think: "medium",
+        keep_alive: "5m",
+        options: {},
+        params: {},
+        http: Elelem::Net.http
+      )
         @url = normalize_url(host)
         @model = model
+        @think = think
+        @keep_alive = keep_alive
+        @options = options
+        @params = params
         @http = http
       end
 
@@ -27,8 +39,82 @@ module Elelem
         "#{base}/api/chat"
       end
 
+      # POST /api/chat request body. Anything left unset uses the server or default.
+=begin
+
+  | Field              | Type                  | Notes                                                 |
+  | ---                | ---                   | ---                                                   |
+  | model              | string                │ required                                              │
+  | messages           | array                 │ see below                                             │
+  | tools              | array                 │ JSON tool schemas                                     │
+  | stream             | bool                  │ NDJSON stream when true                               │
+  | think              | bool or string        │ thinking models; "low"/"medium"/"high"                │
+  | format             | "json" or JSON schema │ structured output                                     │
+  | options            | object                │ model params, see below                               │
+  | keep_alive         | duration              │ how long model stays resident, e.g. "5m", 0 to unload │
+  | truncate           | bool                  │ truncate prompt to fit context                        │
+  | shift              | bool                  │ shift context window instead of erroring when full    │
+  | logprobs           | bool                  │ return token logprobs                                 │
+  | top_logprobs       | int                   │ how many alternatives per token                       │
+  | _debug_render_only | bool                  │ return rendered prompt without inference              │
+
+  Message object
+
+  | Field | Description |
+  | ---- | --------- |
+  | role | (system|user|assistant|tool) |
+  | content | |
+  | thinking | |
+  | images | (base64 array, multimodal) |
+  | tool_calls | |
+  | tool_name | name of the tool that produced a tool message |
+
+  Options
+
+    Sampling:
+
+    | Field | Description |
+    | ---- | ---- |
+    | seed | |
+    | temperature | |
+    | top_k | |
+    | top_p | |
+    | min_p | |
+    | typical_p | |
+    | num_predict | |
+    | num_keep | |
+    | stop (array) | |
+    | repeat_last_n | |
+    | repeat_penalty | |
+    | presence_penalty | |
+    | frequency_penalty | |
+
+    Runner:
+
+    | Field | Description |
+    | ----- | ----------- |
+    | num_ctx | |
+    | num_batch | |
+    | num_gpu | |
+    | main_gpu | |
+    | use_mmap | |
+    | num_thread | |
+    | draft_num_predict | |
+=end
       def build_request_body(messages, tools)
-        { model: @model, messages:, tools:, stream: true }
+        {
+          model: @model,
+          messages:,
+          stream: true,
+          tools: presence(tools),
+          think: @think,
+          keep_alive: @keep_alive,
+          options: presence(@options)
+        }.merge(@params).compact
+      end
+
+      def presence(value)
+        value unless value.nil? || value.empty?
       end
 
       def handle_event(event, tool_calls, &block)