Commit 58b89e4
Changed files (2)
spec
fixtures
Net_Llm_Ollama
_chat
with_streaming
net
llm
spec/fixtures/Net_Llm_Ollama/_chat/with_streaming/yields_each_chunk_to_the_block.yml
@@ -0,0 +1,54 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: http://localhost:11434/api/chat
+ body:
+ encoding: UTF-8
+ string: '{"model":"gpt-oss","messages":[{"role":"user","content":"Hello"}],"stream":true}'
+ 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-23T22:54:10.067169123Z","message":{"role":"assistant","content":"","thinking":"We"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.088628857Z","message":{"role":"assistant","content":"","thinking":" need"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.110277238Z","message":{"role":"assistant","content":"","thinking":" to"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.131673311Z","message":{"role":"assistant","content":"","thinking":" respond"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.153229608Z","message":{"role":"assistant","content":"","thinking":" to"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.174795132Z","message":{"role":"assistant","content":"","thinking":" a"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.196327623Z","message":{"role":"assistant","content":"","thinking":" greeting"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.218504501Z","message":{"role":"assistant","content":"","thinking":"."},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.239647938Z","message":{"role":"assistant","content":"","thinking":" Probably"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.26142463Z","message":{"role":"assistant","content":"","thinking":" just"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.28283973Z","message":{"role":"assistant","content":"","thinking":" a"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.304284706Z","message":{"role":"assistant","content":"","thinking":" friendly"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.325865659Z","message":{"role":"assistant","content":"","thinking":" greeting"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.347317348Z","message":{"role":"assistant","content":"","thinking":" back"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.369709382Z","message":{"role":"assistant","content":"","thinking":"."},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.52273047Z","message":{"role":"assistant","content":"Hello"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.544154958Z","message":{"role":"assistant","content":"!"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.565550401Z","message":{"role":"assistant","content":" How"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.586855583Z","message":{"role":"assistant","content":" can"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.608626505Z","message":{"role":"assistant","content":" I"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.630033709Z","message":{"role":"assistant","content":" help"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.651348891Z","message":{"role":"assistant","content":" you"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.672703566Z","message":{"role":"assistant","content":" today"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.694059765Z","message":{"role":"assistant","content":"?"},"done":false}
+ {"model":"gpt-oss","created_at":"2025-12-23T22:54:10.715377561Z","message":{"role":"assistant","content":""},"done":true,"done_reason":"stop","total_duration":932816840,"load_duration":112096225,"prompt_eval_count":68,"prompt_eval_duration":104278159,"eval_count":34,"eval_duration":704053402}
+ recorded_at: Tue, 23 Dec 2025 22:54:10 GMT
+recorded_with: VCR 6.3.1
spec/net/llm/ollama_spec.rb
@@ -79,25 +79,37 @@ RSpec.describe Net::Llm::Ollama do
end
context "with streaming" do
- it "yields each chunk to the block" do
- chunks = [
- { message: { content: "H" }, done: false }.to_json,
- { message: { content: "i" }, 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(stream: true))
- .to_return(status: 200, body: response_body)
-
+ it "yields each chunk to the block", :vcr do
results = []
client.chat(messages) { |chunk| results << chunk }
- expect(results.size).to eq(3)
- expect(results[0]["message"]["content"]).to eq("H")
- expect(results[1]["message"]["content"]).to eq("i")
- expect(results[2]["done"]).to eq(true)
+ expect(results).to match_array([
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.067169123Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "We"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.088628857Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " need"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.110277238Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " to"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.131673311Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " respond"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.153229608Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " to"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.174795132Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " a"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.196327623Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " greeting"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.218504501Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "."}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.239647938Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " Probably"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.26142463Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " just"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.28283973Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " a"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.304284706Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " friendly"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.325865659Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " greeting"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.347317348Z", "message" => {"role" => "assistant", "content" => "", "thinking" => " back"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.369709382Z", "message" => {"role" => "assistant", "content" => "", "thinking" => "."}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.52273047Z", "message" => {"role" => "assistant", "content" => "Hello"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.544154958Z", "message" => {"role" => "assistant", "content" => "!"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.565550401Z", "message" => {"role" => "assistant", "content" => " How"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.586855583Z", "message" => {"role" => "assistant", "content" => " can"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.608626505Z", "message" => {"role" => "assistant", "content" => " I"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.630033709Z", "message" => {"role" => "assistant", "content" => " help"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.651348891Z", "message" => {"role" => "assistant", "content" => " you"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.672703566Z", "message" => {"role" => "assistant", "content" => " today"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.694059765Z", "message" => {"role" => "assistant", "content" => "?"}, "done" => false},
+ {"model" => "gpt-oss", "created_at" => "2025-12-23T22:54:10.715377561Z", "message" => {"role" => "assistant", "content" => ""}, "done" => true, "done_reason" => "stop", "total_duration" => 932816840, "load_duration" => 112096225, "prompt_eval_count" => 68, "prompt_eval_duration" => 104278159, "eval_count" => 34, "eval_duration" => 704053402}
+ ])
end
it "includes tools in streaming request when provided" do