Commit 8b102c2

mo khan <mo@mokhan.ca>
2025-12-23 23:04:44
test: use vcr fixture
1 parent 58b89e4
Changed files (2)
spec
fixtures
Net_Llm_Ollama
_chat
with_streaming
net
spec/fixtures/Net_Llm_Ollama/_chat/with_streaming/includes_tools.yml
@@ -0,0 +1,72 @@
+---
+http_interactions:
+- request:
+    method: post
+    uri: http://localhost:11434/api/chat
+    body:
+      encoding: UTF-8
+      string: '{"model":"gpt-oss","messages":[{"role":"user","content":"What is the weather for New York city?"}],"stream":true,"tools":[{"type":"function","function":{"name":"get_weather","description":"Get weather for a city","parameters":{"type":"object","properties":{"city":{"type":"string"}}}}}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      Host:
+      - localhost:11434
+  response:
+    status:
+      code: 200
+      message: OK
+    headers:
+      Content-Type:
+      - application/x-ndjson
+      Transfer-Encoding:
+      - chunked
+    body:
+      encoding: UTF-8
+      string: |
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.481641057Z","message":{"role":"assistant","content":"","thinking":"We"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.503077697Z","message":{"role":"assistant","content":"","thinking":" have"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.524275577Z","message":{"role":"assistant","content":"","thinking":" a"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.545633098Z","message":{"role":"assistant","content":"","thinking":" tool"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.566915517Z","message":{"role":"assistant","content":"","thinking":" function"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.588397603Z","message":{"role":"assistant","content":"","thinking":" get"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.609964659Z","message":{"role":"assistant","content":"","thinking":"_weather"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.631305078Z","message":{"role":"assistant","content":"","thinking":"."},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.652867676Z","message":{"role":"assistant","content":"","thinking":" The"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.674240075Z","message":{"role":"assistant","content":"","thinking":" user"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.695760053Z","message":{"role":"assistant","content":"","thinking":" asks"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.71723216Z","message":{"role":"assistant","content":"","thinking":":"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.738721269Z","message":{"role":"assistant","content":"","thinking":" \""},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.760194418Z","message":{"role":"assistant","content":"","thinking":"What"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.782239397Z","message":{"role":"assistant","content":"","thinking":" is"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.804483301Z","message":{"role":"assistant","content":"","thinking":" the"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.826510957Z","message":{"role":"assistant","content":"","thinking":" weather"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.848290404Z","message":{"role":"assistant","content":"","thinking":" for"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.870277052Z","message":{"role":"assistant","content":"","thinking":" New"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.891559321Z","message":{"role":"assistant","content":"","thinking":" York"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.912660518Z","message":{"role":"assistant","content":"","thinking":" city"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.934175527Z","message":{"role":"assistant","content":"","thinking":"?\""},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.955522548Z","message":{"role":"assistant","content":"","thinking":" We"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.976710579Z","message":{"role":"assistant","content":"","thinking":" need"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:29.998294858Z","message":{"role":"assistant","content":"","thinking":" to"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.019524117Z","message":{"role":"assistant","content":"","thinking":" call"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.040632768Z","message":{"role":"assistant","content":"","thinking":" the"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.062132187Z","message":{"role":"assistant","content":"","thinking":" function"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.083688533Z","message":{"role":"assistant","content":"","thinking":"."},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.104912341Z","message":{"role":"assistant","content":"","thinking":" Provide"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.126506319Z","message":{"role":"assistant","content":"","thinking":" arguments"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.147899176Z","message":{"role":"assistant","content":"","thinking":":"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.169298917Z","message":{"role":"assistant","content":"","thinking":" city"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.190979688Z","message":{"role":"assistant","content":"","thinking":"=\""},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.213552523Z","message":{"role":"assistant","content":"","thinking":"New"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.234882782Z","message":{"role":"assistant","content":"","thinking":" York"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.256257546Z","message":{"role":"assistant","content":"","thinking":"\"."},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.277533272Z","message":{"role":"assistant","content":"","thinking":" Then"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.298835529Z","message":{"role":"assistant","content":"","thinking":" output"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.320181548Z","message":{"role":"assistant","content":"","thinking":" the"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.341659196Z","message":{"role":"assistant","content":"","thinking":" result"},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.363157332Z","message":{"role":"assistant","content":"","thinking":"."},"done":false}
+        {"model":"gpt-oss","created_at":"2025-12-23T23:02:30.834167383Z","message":{"role":"assistant","content":"","tool_calls":[{"id":"call_t81u3wss","function":{"index":0,"name":"get_weather","arguments":{"city":"New York"}}}]},"done":true,"done_reason":"stop","total_duration":1621481172,"load_duration":101376342,"prompt_eval_count":129,"prompt_eval_duration":100474990,"eval_count":67,"eval_duration":1402407907}
+  recorded_at: Tue, 23 Dec 2025 23:02:30 GMT
+recorded_with: VCR 6.3.1
spec/net/llm/ollama_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe Net::Llm::Ollama do
         ])
       end
 
-      it "includes tools in streaming request when provided" do
+      it "includes tools", :vcr do
         tools = [{
           type: "function",
           function: {
@@ -126,28 +126,56 @@ RSpec.describe Net::Llm::Ollama do
             }
           }
         }]
-        chunks = [
-          { message: { content: "Checking weather" }, done: false }.to_json,
-          { message: { content: "" }, done: true }.to_json
-        ]
-        response_body = chunks.join("\n") + "\n"
-
-        stub_request(:post, "http://localhost:11434/api/chat")
-          .with(
-            body: hash_including(
-              model: "gpt-oss",
-              messages: messages,
-              tools: tools,
-              stream: true
-            )
-          )
-            .to_return(status: 200, body: response_body)
 
-          results = []
-          client.chat(messages, tools) { |chunk| results << chunk }
+        results = []
+        messages = [{ role: "user", content: "What is the weather for New York city?" }]
+        client.chat(messages, tools) { |chunk| results << chunk }
 
-          expect(results.size).to eq(2)
-          expect(results[0]["message"]["content"]).to eq("Checking weather")
+        expect(results).to match_array([
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.481641057Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "We"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.503077697Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " have"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.524275577Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " a"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.545633098Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " tool"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.566915517Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " function"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.588397603Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " get"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.609964659Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "_weather"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.631305078Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "."}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.652867676Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " The"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.674240075Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " user"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.695760053Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " asks"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.71723216Z", "message" => {"role" => "assistant", "content" => "", "thinking" => ":"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.738721269Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " \""}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.760194418Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "What"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.782239397Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " is"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.804483301Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " the"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.826510957Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " weather"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.848290404Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " for"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.870277052Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " New"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.891559321Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " York"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.912660518Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " city"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.934175527Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "?\""}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.955522548Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " We"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.976710579Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " need"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:29.998294858Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " to"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.019524117Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " call"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.040632768Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " the"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.062132187Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " function"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.083688533Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "."}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.104912341Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " Provide"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.126506319Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " arguments"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.147899176Z", "message" => {"role" => "assistant", "content" => "", "thinking" => ":"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.169298917Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " city"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.190979688Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "=\""}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.213552523Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "New"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.234882782Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " York"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.256257546Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "\"."}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.277533272Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " Then"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.298835529Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " output"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.320181548Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " the"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.341659196Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " result"}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.363157332Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "."}, "done" => false},
+          {"model" => "gpt-oss", "created_at" => "2025-12-23T23:02:30.834167383Z", "message" => {"role" => "assistant", "content" => "", "tool_calls" => [{"id" => "call_t81u3wss", "function" => {"index" => 0, "name" => "get_weather", "arguments" => {"city" => "New York"}}}]}, "done" => true, "done_reason" => "stop", "total_duration" => 1621481172, "load_duration" => 101376342, "prompt_eval_count" => 129, "prompt_eval_duration" => 100474990, "eval_count" => 67, "eval_duration" => 1402407907}
+        ])
       end
     end
   end