ollama-client 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +336 -91
- data/RELEASE_NOTES_v0.2.6.md +41 -0
- data/docs/AREAS_FOR_CONSIDERATION.md +325 -0
- data/docs/EXAMPLE_REORGANIZATION.md +412 -0
- data/docs/FEATURES_ADDED.md +12 -1
- data/docs/GETTING_STARTED.md +361 -0
- data/docs/INTEGRATION_TESTING.md +170 -0
- data/docs/NEXT_STEPS_SUMMARY.md +114 -0
- data/docs/PERSONAS.md +383 -0
- data/docs/QUICK_START.md +195 -0
- data/docs/TESTING.md +392 -170
- data/docs/TEST_CHECKLIST.md +450 -0
- data/examples/README.md +62 -63
- data/examples/basic_chat.rb +33 -0
- data/examples/basic_generate.rb +29 -0
- data/examples/mcp_executor.rb +39 -0
- data/examples/mcp_http_executor.rb +45 -0
- data/examples/tool_calling_parsing.rb +59 -0
- data/examples/tool_dto_example.rb +0 -0
- data/exe/ollama-client +128 -1
- data/lib/ollama/agent/planner.rb +7 -2
- data/lib/ollama/chat_session.rb +101 -0
- data/lib/ollama/client.rb +41 -35
- data/lib/ollama/config.rb +9 -4
- data/lib/ollama/document_loader.rb +1 -1
- data/lib/ollama/embeddings.rb +61 -28
- data/lib/ollama/errors.rb +1 -0
- data/lib/ollama/mcp/http_client.rb +149 -0
- data/lib/ollama/mcp/stdio_client.rb +146 -0
- data/lib/ollama/mcp/tools_bridge.rb +72 -0
- data/lib/ollama/mcp.rb +31 -0
- data/lib/ollama/options.rb +3 -1
- data/lib/ollama/personas.rb +287 -0
- data/lib/ollama/version.rb +1 -1
- data/lib/ollama_client.rb +17 -5
- metadata +22 -48
- data/examples/advanced_complex_schemas.rb +0 -366
- data/examples/advanced_edge_cases.rb +0 -241
- data/examples/advanced_error_handling.rb +0 -200
- data/examples/advanced_multi_step_agent.rb +0 -341
- data/examples/advanced_performance_testing.rb +0 -186
- data/examples/chat_console.rb +0 -143
- data/examples/complete_workflow.rb +0 -245
- data/examples/dhan_console.rb +0 -843
- data/examples/dhanhq/README.md +0 -236
- data/examples/dhanhq/agents/base_agent.rb +0 -74
- data/examples/dhanhq/agents/data_agent.rb +0 -66
- data/examples/dhanhq/agents/orchestrator_agent.rb +0 -120
- data/examples/dhanhq/agents/technical_analysis_agent.rb +0 -252
- data/examples/dhanhq/agents/trading_agent.rb +0 -81
- data/examples/dhanhq/analysis/market_structure.rb +0 -138
- data/examples/dhanhq/analysis/pattern_recognizer.rb +0 -192
- data/examples/dhanhq/analysis/trend_analyzer.rb +0 -88
- data/examples/dhanhq/builders/market_context_builder.rb +0 -67
- data/examples/dhanhq/dhanhq_agent.rb +0 -829
- data/examples/dhanhq/indicators/technical_indicators.rb +0 -158
- data/examples/dhanhq/scanners/intraday_options_scanner.rb +0 -492
- data/examples/dhanhq/scanners/swing_scanner.rb +0 -247
- data/examples/dhanhq/schemas/agent_schemas.rb +0 -61
- data/examples/dhanhq/services/base_service.rb +0 -46
- data/examples/dhanhq/services/data_service.rb +0 -118
- data/examples/dhanhq/services/trading_service.rb +0 -59
- data/examples/dhanhq/technical_analysis_agentic_runner.rb +0 -411
- data/examples/dhanhq/technical_analysis_runner.rb +0 -420
- data/examples/dhanhq/test_tool_calling.rb +0 -538
- data/examples/dhanhq/test_tool_calling_verbose.rb +0 -251
- data/examples/dhanhq/utils/instrument_helper.rb +0 -32
- data/examples/dhanhq/utils/parameter_cleaner.rb +0 -28
- data/examples/dhanhq/utils/parameter_normalizer.rb +0 -45
- data/examples/dhanhq/utils/rate_limiter.rb +0 -23
- data/examples/dhanhq/utils/trading_parameter_normalizer.rb +0 -72
- data/examples/dhanhq_agent.rb +0 -964
- data/examples/dhanhq_tools.rb +0 -1663
- data/examples/multi_step_agent_with_external_data.rb +0 -368
- data/examples/structured_outputs_chat.rb +0 -72
- data/examples/structured_tools.rb +0 -89
- data/examples/test_dhanhq_tool_calling.rb +0 -375
- data/examples/test_tool_calling.rb +0 -160
- data/examples/tool_calling_direct.rb +0 -124
- data/examples/tool_calling_pattern.rb +0 -269
- data/exe/dhan_console +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 53bd3c1ff3323d004a7ba3549317ef49d3ce9698d41133a1d2150d0a5135fa80
|
|
4
|
+
data.tar.gz: 4c726b2a7fabf164c91cd51206266d250de836986d1a36726556cbefb47a6e8e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1cdcc10b54d2fa318daefc2736d338715b65f03cacf94c7c9303c07ec745ea510e6de0ac73c0c668b0301481663989af1368d86727ebfa1252a43edab9d7d711
|
|
7
|
+
data.tar.gz: aead7b8ae703d436866cf796e91b102fbcc21ff47e6528c2edf62b13a1bac1f98f36d1146ba3e56a7fa0792bd0aff0880be65450c05b2352336cd20b39b3f9ab
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.7] - 2026-02-04
|
|
4
|
+
|
|
5
|
+
- Add MCP (Model Context Protocol) support for local and remote servers
|
|
6
|
+
- Add `Ollama::MCP::StdioClient` for local MCP servers over stdio (e.g. `npx @modelcontextprotocol/server-filesystem`)
|
|
7
|
+
- Add `Ollama::MCP::HttpClient` for remote MCP servers over HTTP (e.g. [gitmcp.io](https://gitmcp.io)/owner/repo)
|
|
8
|
+
- Add `Ollama::MCP::ToolsBridge` to expose MCP tools to `Ollama::Agent::Executor` (`client:` or `stdio_client:`)
|
|
9
|
+
- Add examples: `examples/mcp_executor.rb` (stdio), `examples/mcp_http_executor.rb` (URL)
|
|
10
|
+
- Document MCP usage and GitMCP URL in README; fix RuboCop offenses in MCP code
|
|
11
|
+
|
|
12
|
+
## [0.2.6] - 2026-01-26
|
|
13
|
+
|
|
14
|
+
- Reorganize examples: move agent examples to separate repository, keep minimal client examples
|
|
15
|
+
- Add comprehensive test coverage (increased from 65.66% to 79.59%)
|
|
16
|
+
- Add test suite for `Ollama::DocumentLoader` (file loading, context building)
|
|
17
|
+
- Add test suite for `Ollama::Embeddings` (API calls, error handling)
|
|
18
|
+
- Add test suite for `Ollama::ChatSession` (session management)
|
|
19
|
+
- Add test suite for tool classes (`Tool`, `Function`, `Parameters`, `Property`)
|
|
20
|
+
- Rewrite testing documentation to focus on client-only testing (transport/protocol)
|
|
21
|
+
- Add test checklist with specific test categories (G1-G3, C1-C3, A1-A2, F1-F3)
|
|
22
|
+
- Update README with enhanced "What This Gem IS NOT" section
|
|
23
|
+
- Fix RuboCop offenses and improve code quality
|
|
24
|
+
|
|
3
25
|
## [0.2.5] - 2026-01-22
|
|
4
26
|
|
|
5
27
|
- Add `Ollama::DocumentLoader` for loading files as context in queries
|
data/README.md
CHANGED
|
@@ -26,11 +26,15 @@ Domain tools and application logic live **outside** this gem. For convenience, i
|
|
|
26
26
|
|
|
27
27
|
## 🚫 What This Gem IS NOT
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
* ❌
|
|
31
|
-
* ❌
|
|
32
|
-
* ❌
|
|
33
|
-
* ❌ A
|
|
29
|
+
This gem is **NOT**:
|
|
30
|
+
* ❌ A chatbot UI framework
|
|
31
|
+
* ❌ A domain-specific agent implementation
|
|
32
|
+
* ❌ A tool execution engine
|
|
33
|
+
* ❌ A memory store
|
|
34
|
+
* ❌ A promise of full Ollama API coverage (focuses on agent workflows)
|
|
35
|
+
* ❌ An agent runtime (it provides transport + protocol, not agent logic)
|
|
36
|
+
|
|
37
|
+
**Domain tools and application logic live outside this gem.**
|
|
34
38
|
|
|
35
39
|
This keeps it **clean and future-proof**.
|
|
36
40
|
|
|
@@ -68,13 +72,115 @@ Or install it yourself as:
|
|
|
68
72
|
gem install ollama-client
|
|
69
73
|
```
|
|
70
74
|
|
|
75
|
+
## Quick Start
|
|
76
|
+
|
|
77
|
+
### Step 1: Simple Text Generation
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
require "ollama_client"
|
|
81
|
+
|
|
82
|
+
client = Ollama::Client.new
|
|
83
|
+
|
|
84
|
+
# Get plain text response (no schema = plain text)
|
|
85
|
+
response = client.generate(
|
|
86
|
+
prompt: "Explain Ruby blocks in one sentence"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
puts response
|
|
90
|
+
# => "Ruby blocks are anonymous functions passed to methods..."
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Step 2: Structured Outputs (Recommended for Agents)
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
require "ollama_client"
|
|
97
|
+
|
|
98
|
+
client = Ollama::Client.new
|
|
99
|
+
|
|
100
|
+
# Define JSON schema
|
|
101
|
+
schema = {
|
|
102
|
+
"type" => "object",
|
|
103
|
+
"required" => ["action", "reasoning"],
|
|
104
|
+
"properties" => {
|
|
105
|
+
"action" => { "type" => "string", "enum" => ["search", "calculate", "finish"] },
|
|
106
|
+
"reasoning" => { "type" => "string" }
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Get structured decision
|
|
111
|
+
result = client.generate(
|
|
112
|
+
prompt: "User wants weather in Paris. What should I do?",
|
|
113
|
+
schema: schema
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
puts result["action"] # => "search"
|
|
117
|
+
puts result["reasoning"] # => "Need to fetch weather data..."
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Step 3: Agent Planning (Stateless)
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
require "ollama_client"
|
|
124
|
+
|
|
125
|
+
client = Ollama::Client.new
|
|
126
|
+
planner = Ollama::Agent::Planner.new(client)
|
|
127
|
+
|
|
128
|
+
decision_schema = {
|
|
129
|
+
"type" => "object",
|
|
130
|
+
"required" => ["action"],
|
|
131
|
+
"properties" => {
|
|
132
|
+
"action" => { "type" => "string", "enum" => ["search", "calculate", "finish"] }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
plan = planner.run(
|
|
137
|
+
prompt: "Decide the next action",
|
|
138
|
+
schema: decision_schema
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Use the structured decision
|
|
142
|
+
case plan["action"]
|
|
143
|
+
when "search"
|
|
144
|
+
# Execute search
|
|
145
|
+
when "calculate"
|
|
146
|
+
# Execute calculation
|
|
147
|
+
when "finish"
|
|
148
|
+
# Task complete
|
|
149
|
+
end
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Step 4: Tool Calling (Stateful)
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
require "ollama_client"
|
|
156
|
+
|
|
157
|
+
client = Ollama::Client.new
|
|
158
|
+
|
|
159
|
+
# Define tools
|
|
160
|
+
tools = {
|
|
161
|
+
"get_weather" => ->(city:) { { city: city, temp: 22, condition: "sunny" } }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
executor = Ollama::Agent::Executor.new(client, tools: tools)
|
|
165
|
+
|
|
166
|
+
answer = executor.run(
|
|
167
|
+
system: "You are a helpful assistant. Use tools when needed.",
|
|
168
|
+
user: "What's the weather in Paris?"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
puts answer
|
|
172
|
+
# => "The weather in Paris is 22°C and sunny."
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Next Steps:** See [Choosing the Correct API](#choosing-the-correct-api-generate-vs-chat) below for guidance on when to use each method.
|
|
176
|
+
|
|
71
177
|
## Usage
|
|
72
178
|
|
|
73
179
|
**Note:** You can use `require "ollama_client"` (recommended) or `require "ollama/client"` directly. The client works with or without the global `OllamaClient` configuration module.
|
|
74
180
|
|
|
75
181
|
### Primary API: `generate()`
|
|
76
182
|
|
|
77
|
-
**`generate(prompt:, schema: nil)`** is the **primary and recommended method** for agent-grade usage:
|
|
183
|
+
**`generate(prompt:, schema: nil, model: nil, strict: false, return_meta: false)`** is the **primary and recommended method** for agent-grade usage:
|
|
78
184
|
|
|
79
185
|
- ✅ Stateless, explicit state injection
|
|
80
186
|
- ✅ Uses `/api/generate` endpoint
|
|
@@ -85,11 +191,46 @@ gem install ollama-client
|
|
|
85
191
|
**This is the method you should use for hybrid agents.**
|
|
86
192
|
|
|
87
193
|
**Usage:**
|
|
88
|
-
- **With schema** (structured JSON): `generate(prompt: "...", schema: {...})`
|
|
89
|
-
- **Without schema** (plain text): `generate(prompt: "...")` - returns plain text/markdown
|
|
194
|
+
- **With schema** (structured JSON): `generate(prompt: "...", schema: {...})` - returns Hash
|
|
195
|
+
- **Without schema** (plain text): `generate(prompt: "...")` - returns String (plain text/markdown)
|
|
90
196
|
|
|
91
197
|
### Choosing the Correct API (generate vs chat)
|
|
92
198
|
|
|
199
|
+
**Decision Tree:**
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
Need structured JSON output?
|
|
203
|
+
├─ Yes → Use generate() with schema
|
|
204
|
+
│ └─ Need conversation history?
|
|
205
|
+
│ ├─ No → Use generate() directly
|
|
206
|
+
│ └─ Yes → Include context in prompt (generate() is stateless)
|
|
207
|
+
│
|
|
208
|
+
└─ No → Need plain text/markdown?
|
|
209
|
+
├─ Yes → Use generate() without schema
|
|
210
|
+
│ └─ Need conversation history?
|
|
211
|
+
│ ├─ No → Use generate() directly
|
|
212
|
+
│ └─ Yes → Include context in prompt
|
|
213
|
+
│
|
|
214
|
+
└─ Need tool calling?
|
|
215
|
+
├─ Yes → Use Executor (chat API with tools)
|
|
216
|
+
│ └─ Multi-step workflow with tool loops
|
|
217
|
+
│
|
|
218
|
+
└─ No → Use ChatSession (chat API for UI)
|
|
219
|
+
└─ Human-facing chat interface
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Quick Reference:**
|
|
223
|
+
|
|
224
|
+
| Use Case | Method | API Endpoint | State |
|
|
225
|
+
|----------|--------|--------------|-------|
|
|
226
|
+
| Agent planning/routing | `generate()` | `/api/generate` | Stateless |
|
|
227
|
+
| Structured extraction | `generate()` | `/api/generate` | Stateless |
|
|
228
|
+
| Simple text generation | `generate()` | `/api/generate` | Stateless |
|
|
229
|
+
| Tool-calling loops | `Executor` | `/api/chat` | Stateful |
|
|
230
|
+
| UI chat interface | `ChatSession` | `/api/chat` | Stateful |
|
|
231
|
+
|
|
232
|
+
**Detailed Guidance:**
|
|
233
|
+
|
|
93
234
|
- **Use `/api/generate`** (via `Ollama::Client#generate` or `Ollama::Agent::Planner`) for **stateless planner/router** steps where you want strict, deterministic structured outputs.
|
|
94
235
|
- **Use `/api/chat`** (via `Ollama::Agent::Executor`) for **stateful tool-using** workflows where the model may request tool calls across multiple turns.
|
|
95
236
|
|
|
@@ -260,13 +401,13 @@ require "ollama_client"
|
|
|
260
401
|
|
|
261
402
|
client = Ollama::Client.new
|
|
262
403
|
|
|
263
|
-
# Get plain text/markdown response (
|
|
404
|
+
# Get plain text/markdown response (omit schema for plain text)
|
|
264
405
|
text_response = client.generate(
|
|
265
406
|
prompt: "Explain Ruby in simple terms"
|
|
266
407
|
)
|
|
267
408
|
|
|
268
409
|
puts text_response
|
|
269
|
-
# Output: Plain text or markdown explanation
|
|
410
|
+
# Output: Plain text or markdown explanation (String)
|
|
270
411
|
```
|
|
271
412
|
|
|
272
413
|
**Option 2: Using `chat_raw()` (for multi-turn conversations)**
|
|
@@ -289,8 +430,8 @@ puts text_response
|
|
|
289
430
|
```
|
|
290
431
|
|
|
291
432
|
**When to use which:**
|
|
292
|
-
- **`generate()` without schema** - Simple one-shot queries, explanations, text generation
|
|
293
|
-
- **`generate()` with schema** - Structured JSON outputs for agents
|
|
433
|
+
- **`generate()` without schema** - Simple one-shot queries, explanations, text generation (returns plain text)
|
|
434
|
+
- **`generate()` with schema** - Structured JSON outputs for agents (recommended for agents)
|
|
294
435
|
- **`chat_raw()` without format** - Multi-turn conversations with plain text
|
|
295
436
|
- **`chat_raw()` with format** - Multi-turn conversations with structured outputs
|
|
296
437
|
|
|
@@ -298,7 +439,7 @@ puts text_response
|
|
|
298
439
|
|
|
299
440
|
This gem intentionally focuses on **agent building blocks**:
|
|
300
441
|
|
|
301
|
-
- **Supported**: `/api/generate`, `/api/chat`, `/api/tags`, `/api/ping`, `/api/
|
|
442
|
+
- **Supported**: `/api/generate`, `/api/chat`, `/api/tags`, `/api/ping`, `/api/embed`
|
|
302
443
|
- **Not guaranteed**: full endpoint parity with every Ollama release (advanced model mgmt, etc.)
|
|
303
444
|
|
|
304
445
|
### Agent endpoint mapping (unambiguous)
|
|
@@ -315,6 +456,40 @@ Within `Ollama::Agent`:
|
|
|
315
456
|
```ruby
|
|
316
457
|
require "ollama_client"
|
|
317
458
|
|
|
459
|
+
client = Ollama::Client.new
|
|
460
|
+
|
|
461
|
+
# Option 1: With schema (recommended for structured outputs)
|
|
462
|
+
DECISION_SCHEMA = {
|
|
463
|
+
"type" => "object",
|
|
464
|
+
"required" => ["action", "reasoning"],
|
|
465
|
+
"properties" => {
|
|
466
|
+
"action" => {
|
|
467
|
+
"type" => "string",
|
|
468
|
+
"enum" => ["search", "calculate", "store", "retrieve", "finish"]
|
|
469
|
+
},
|
|
470
|
+
"reasoning" => {
|
|
471
|
+
"type" => "string"
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
planner = Ollama::Agent::Planner.new(client)
|
|
477
|
+
|
|
478
|
+
plan = planner.run(
|
|
479
|
+
prompt: "Given the user request, decide the next action.",
|
|
480
|
+
schema: DECISION_SCHEMA,
|
|
481
|
+
context: { user_request: "Plan a weekend trip to Rome" }
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
puts plan["action"] # => "search" (or one of the enum values)
|
|
485
|
+
puts plan["reasoning"] # => Explanation string
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
**Option 2: Without schema (returns any JSON)**
|
|
489
|
+
|
|
490
|
+
```ruby
|
|
491
|
+
require "ollama_client"
|
|
492
|
+
|
|
318
493
|
client = Ollama::Client.new
|
|
319
494
|
planner = Ollama::Agent::Planner.new(client)
|
|
320
495
|
|
|
@@ -326,7 +501,7 @@ plan = planner.run(
|
|
|
326
501
|
context: { user_request: "Plan a weekend trip to Rome" }
|
|
327
502
|
)
|
|
328
503
|
|
|
329
|
-
puts plan
|
|
504
|
+
puts plan # => Any valid JSON structure
|
|
330
505
|
```
|
|
331
506
|
|
|
332
507
|
### Executor Agent (tool loop, /api/chat)
|
|
@@ -669,6 +844,61 @@ result2 = client.chat(messages: messages, format: decision_schema, allow_chat: t
|
|
|
669
844
|
# Harder to reason about state in agent systems
|
|
670
845
|
```
|
|
671
846
|
|
|
847
|
+
### Decision Table: `generate()` vs `chat()` vs `ChatSession`
|
|
848
|
+
|
|
849
|
+
> **Use `generate()` for systems. Use `chat()` or `ChatSession` for humans.**
|
|
850
|
+
|
|
851
|
+
| Use Case | Method | Schema Guarantees | Streaming | Memory | When to Use |
|
|
852
|
+
|----------|--------|-------------------|-----------|--------|-------------|
|
|
853
|
+
| **Agent planning/routing** | `generate()` | ✅ Strong | ❌ No | ❌ Stateless | Default for agents |
|
|
854
|
+
| **Structured extraction** | `generate()` | ✅ Strong | ❌ No | ❌ Stateless | Data extraction, classification |
|
|
855
|
+
| **Tool-calling loops** | `chat_raw()` | ⚠️ Weaker | ✅ Yes | ✅ Stateful | Executor agent internals |
|
|
856
|
+
| **UI chat interface** | `ChatSession` | ⚠️ Best-effort | ✅ Yes | ✅ Stateful | Human-facing assistants |
|
|
857
|
+
| **Multi-turn conversations** | `ChatSession` | ⚠️ Best-effort | ✅ Yes | ✅ Stateful | Interactive chat |
|
|
858
|
+
|
|
859
|
+
**Core Rule:** Chat must be a feature flag, not default behavior.
|
|
860
|
+
|
|
861
|
+
### Using `ChatSession` for Human-Facing Chat
|
|
862
|
+
|
|
863
|
+
For UI assistants and interactive chat, use `ChatSession` to manage conversation state:
|
|
864
|
+
|
|
865
|
+
```ruby
|
|
866
|
+
require "ollama_client"
|
|
867
|
+
|
|
868
|
+
# Enable chat in config
|
|
869
|
+
config = Ollama::Config.new
|
|
870
|
+
config.allow_chat = true
|
|
871
|
+
config.streaming_enabled = true
|
|
872
|
+
|
|
873
|
+
client = Ollama::Client.new(config: config)
|
|
874
|
+
|
|
875
|
+
# Create streaming observer for presentation
|
|
876
|
+
observer = Ollama::StreamingObserver.new do |event|
|
|
877
|
+
case event.type
|
|
878
|
+
when :token
|
|
879
|
+
print event.text
|
|
880
|
+
when :final
|
|
881
|
+
puts "\n--- DONE ---"
|
|
882
|
+
end
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
# Create chat session with system message
|
|
886
|
+
chat = Ollama::ChatSession.new(
|
|
887
|
+
client,
|
|
888
|
+
system: "You are a helpful assistant",
|
|
889
|
+
stream: observer
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
# Send messages (history is managed automatically)
|
|
893
|
+
chat.say("Hello")
|
|
894
|
+
chat.say("Explain Ruby blocks")
|
|
895
|
+
|
|
896
|
+
# Clear history if needed (keeps system message)
|
|
897
|
+
chat.clear
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
**Important:** Schema validation in chat is **best-effort** for formatting, not correctness. Never use chat+schema for agent control flow.
|
|
901
|
+
|
|
672
902
|
### Example: Chat API (Advanced Use Case)
|
|
673
903
|
|
|
674
904
|
```ruby
|
|
@@ -790,6 +1020,58 @@ end
|
|
|
790
1020
|
- Both methods accept `tools:` parameter (Tool object, array of Tool objects, or array of hashes)
|
|
791
1021
|
- For agent tool loops, use `Ollama::Agent::Executor` instead (handles tool execution automatically)
|
|
792
1022
|
|
|
1023
|
+
### MCP support (local and remote servers)
|
|
1024
|
+
|
|
1025
|
+
You can connect to [Model Context Protocol](https://modelcontextprotocol.io) (MCP) servers and use their tools with the Executor.
|
|
1026
|
+
|
|
1027
|
+
**Remote MCP server (HTTP URL, e.g. [GitMCP](https://gitmcp.io)):**
|
|
1028
|
+
|
|
1029
|
+
```ruby
|
|
1030
|
+
require "ollama_client"
|
|
1031
|
+
|
|
1032
|
+
client = Ollama::Client.new
|
|
1033
|
+
|
|
1034
|
+
# Remote MCP server URL (e.g. GitMCP: https://gitmcp.io/owner/repo)
|
|
1035
|
+
mcp_client = Ollama::MCP::HttpClient.new(
|
|
1036
|
+
url: "https://gitmcp.io/shubhamtaywade82/agent-runtime",
|
|
1037
|
+
timeout_seconds: 60
|
|
1038
|
+
)
|
|
1039
|
+
|
|
1040
|
+
bridge = Ollama::MCP::ToolsBridge.new(client: mcp_client)
|
|
1041
|
+
tools = bridge.tools_for_executor
|
|
1042
|
+
|
|
1043
|
+
executor = Ollama::Agent::Executor.new(client, tools: tools)
|
|
1044
|
+
answer = executor.run(
|
|
1045
|
+
system: "You have access to the agent-runtime docs. Use tools when the user asks about the repo.",
|
|
1046
|
+
user: "What does this repo do?"
|
|
1047
|
+
)
|
|
1048
|
+
|
|
1049
|
+
puts answer
|
|
1050
|
+
mcp_client.close
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
**Local MCP server (stdio, e.g. filesystem server):**
|
|
1054
|
+
|
|
1055
|
+
```ruby
|
|
1056
|
+
# Local MCP server via stdio (requires Node.js/npx)
|
|
1057
|
+
mcp_client = Ollama::MCP::StdioClient.new(
|
|
1058
|
+
command: "npx",
|
|
1059
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
|
|
1060
|
+
timeout_seconds: 60
|
|
1061
|
+
)
|
|
1062
|
+
|
|
1063
|
+
bridge = Ollama::MCP::ToolsBridge.new(stdio_client: mcp_client) # or client: mcp_client
|
|
1064
|
+
tools = bridge.tools_for_executor
|
|
1065
|
+
# ... same executor usage
|
|
1066
|
+
mcp_client.close
|
|
1067
|
+
```
|
|
1068
|
+
|
|
1069
|
+
- **Stdio**: `Ollama::MCP::StdioClient` — spawns a subprocess; use for local servers (e.g. `npx @modelcontextprotocol/server-filesystem`).
|
|
1070
|
+
- **HTTP**: `Ollama::MCP::HttpClient` — POSTs JSON-RPC to a URL; use for remote servers (e.g. [gitmcp.io/owner/repo](https://gitmcp.io)).
|
|
1071
|
+
- **Bridge**: `Ollama::MCP::ToolsBridge.new(client: mcp_client)` or `stdio_client: mcp_client`; then `tools_for_executor` for the Executor.
|
|
1072
|
+
- No extra gem; implementation is self-contained.
|
|
1073
|
+
- See [examples/mcp_executor.rb](examples/mcp_executor.rb) (stdio) and [examples/mcp_http_executor.rb](examples/mcp_http_executor.rb) (URL).
|
|
1074
|
+
|
|
793
1075
|
### Example: Data Analysis with Validation
|
|
794
1076
|
|
|
795
1077
|
```ruby
|
|
@@ -958,42 +1240,37 @@ client = Ollama::Client.new
|
|
|
958
1240
|
# Note: You need an embedding model installed in Ollama
|
|
959
1241
|
# Common models: nomic-embed-text, all-minilm, mxbai-embed-large
|
|
960
1242
|
# Check available models: client.list_models
|
|
1243
|
+
# The client uses /api/embed endpoint internally
|
|
961
1244
|
|
|
962
1245
|
begin
|
|
963
1246
|
# Single text embedding
|
|
964
|
-
# Note:
|
|
1247
|
+
# Note: Model name can be with or without tag (e.g., "nomic-embed-text" or "nomic-embed-text:latest")
|
|
965
1248
|
embedding = client.embeddings.embed(
|
|
966
|
-
model: "nomic-embed-text
|
|
1249
|
+
model: "nomic-embed-text", # Use an available embedding model
|
|
967
1250
|
input: "What is Ruby programming?"
|
|
968
1251
|
)
|
|
969
1252
|
# Returns: [0.123, -0.456, ...] (array of floats)
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
puts "Embedding dimension: #{embedding.length}"
|
|
974
|
-
puts "First few values: #{embedding.first(5).map { |v| v.round(4) }}"
|
|
975
|
-
end
|
|
1253
|
+
# For nomic-embed-text, dimension is typically 768
|
|
1254
|
+
puts "Embedding dimension: #{embedding.length}"
|
|
1255
|
+
puts "First few values: #{embedding.first(5).map { |v| v.round(4) }}"
|
|
976
1256
|
|
|
977
1257
|
# Multiple texts
|
|
978
1258
|
embeddings = client.embeddings.embed(
|
|
979
|
-
model: "nomic-embed-text
|
|
1259
|
+
model: "nomic-embed-text",
|
|
980
1260
|
input: ["What is Ruby?", "What is Python?", "What is JavaScript?"]
|
|
981
1261
|
)
|
|
982
1262
|
# Returns: [[...], [...], [...]] (array of embedding arrays)
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
else
|
|
987
|
-
puts "Unexpected response format: #{embeddings.class}"
|
|
988
|
-
end
|
|
1263
|
+
# Each inner array is an embedding vector for the corresponding input text
|
|
1264
|
+
puts "Number of embeddings: #{embeddings.length}"
|
|
1265
|
+
puts "Each embedding dimension: #{embeddings.first.length}"
|
|
989
1266
|
|
|
990
1267
|
rescue Ollama::NotFoundError => e
|
|
991
1268
|
puts "Model not found. Install an embedding model first:"
|
|
992
1269
|
puts " ollama pull nomic-embed-text"
|
|
993
1270
|
puts "Or check available models: client.list_models"
|
|
994
|
-
puts "Note: Use the full model name with tag (e.g., 'nomic-embed-text:latest')"
|
|
995
1271
|
rescue Ollama::Error => e
|
|
996
1272
|
puts "Error: #{e.message}"
|
|
1273
|
+
# Error message includes helpful troubleshooting steps
|
|
997
1274
|
end
|
|
998
1275
|
|
|
999
1276
|
# Use for semantic similarity in agents
|
|
@@ -1204,67 +1481,35 @@ end
|
|
|
1204
1481
|
|
|
1205
1482
|
This keeps the `ollama-client` gem **domain-agnostic** and **reusable** across any project.
|
|
1206
1483
|
|
|
1207
|
-
**See
|
|
1208
|
-
|
|
1209
|
-
##
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
-
|
|
1216
|
-
-
|
|
1217
|
-
-
|
|
1218
|
-
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
-
|
|
1232
|
-
-
|
|
1233
|
-
-
|
|
1234
|
-
-
|
|
1235
|
-
|
|
1236
|
-
### `advanced_error_handling.rb`
|
|
1237
|
-
Comprehensive error handling patterns:
|
|
1238
|
-
- All error types (NotFoundError, HTTPError, TimeoutError, etc.)
|
|
1239
|
-
- Retry strategies with exponential backoff
|
|
1240
|
-
- Fallback mechanisms
|
|
1241
|
-
- Error statistics and observability
|
|
1242
|
-
|
|
1243
|
-
### `advanced_complex_schemas.rb`
|
|
1244
|
-
Real-world complex schemas:
|
|
1245
|
-
- Financial analysis (nested metrics, recommendations, risk factors)
|
|
1246
|
-
- Code review (issues, suggestions, effort estimation)
|
|
1247
|
-
- Research paper analysis (findings, methodology, citations)
|
|
1248
|
-
|
|
1249
|
-
### `advanced_performance_testing.rb`
|
|
1250
|
-
Performance and observability:
|
|
1251
|
-
- Latency measurement (min, max, avg, p95, p99)
|
|
1252
|
-
- Throughput testing
|
|
1253
|
-
- Error rate tracking
|
|
1254
|
-
- Metrics export
|
|
1255
|
-
|
|
1256
|
-
### `advanced_edge_cases.rb`
|
|
1257
|
-
Boundary and edge case testing:
|
|
1258
|
-
- Empty/long prompts
|
|
1259
|
-
- Special characters and unicode
|
|
1260
|
-
- Minimal/strict schemas
|
|
1261
|
-
- Deeply nested structures
|
|
1262
|
-
- Enum constraints
|
|
1263
|
-
|
|
1264
|
-
Run any example:
|
|
1265
|
-
```bash
|
|
1266
|
-
ruby examples/advanced_multi_step_agent.rb
|
|
1267
|
-
```
|
|
1484
|
+
**See the [ollama-agent-examples](https://github.com/shubhamtaywade82/ollama-agent-examples) repository for working implementations of this pattern.**
|
|
1485
|
+
|
|
1486
|
+
## 📚 Examples
|
|
1487
|
+
|
|
1488
|
+
### Minimal Examples (In This Repo)
|
|
1489
|
+
|
|
1490
|
+
The `examples/` directory contains minimal examples demonstrating **client usage only**:
|
|
1491
|
+
|
|
1492
|
+
- **`basic_generate.rb`** - Basic `/generate` usage with schema validation
|
|
1493
|
+
- **`basic_chat.rb`** - Basic `/chat` usage
|
|
1494
|
+
- **`tool_calling_parsing.rb`** - Tool-call parsing (no execution)
|
|
1495
|
+
- **`tool_dto_example.rb`** - Tool DTO serialization
|
|
1496
|
+
|
|
1497
|
+
These examples focus on **transport and protocol correctness**, not agent behavior.
|
|
1498
|
+
|
|
1499
|
+
### Full Agent Examples (Separate Repository)
|
|
1500
|
+
|
|
1501
|
+
For complete agent examples (trading agents, coding agents, RAG agents, multi-step workflows, tool execution patterns, etc.), see:
|
|
1502
|
+
|
|
1503
|
+
**[ollama-agent-examples](https://github.com/shubhamtaywade82/ollama-agent-examples)**
|
|
1504
|
+
|
|
1505
|
+
This separation keeps `ollama-client` focused on the transport layer while providing comprehensive examples for agent developers.
|
|
1506
|
+
|
|
1507
|
+
**Why this separation?**
|
|
1508
|
+
- Examples rot faster than APIs
|
|
1509
|
+
- Agent examples pull in domain-specific dependencies
|
|
1510
|
+
- Tool examples imply opinions about tool design
|
|
1511
|
+
- The client stays clean and maintainable
|
|
1512
|
+
- Users don't confuse client vs agent responsibilities
|
|
1268
1513
|
|
|
1269
1514
|
## Development
|
|
1270
1515
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Release v0.2.6
|
|
2
|
+
|
|
3
|
+
## 🎯 Major Changes
|
|
4
|
+
|
|
5
|
+
### Test Coverage & Quality
|
|
6
|
+
- **Increased test coverage from 65.66% to 79.59%**
|
|
7
|
+
- Added comprehensive test suites for:
|
|
8
|
+
- `Ollama::DocumentLoader` (file loading, context building)
|
|
9
|
+
- `Ollama::Embeddings` (API calls, error handling)
|
|
10
|
+
- `Ollama::ChatSession` (session management)
|
|
11
|
+
- Tool classes (`Tool`, `Function`, `Parameters`, `Property`)
|
|
12
|
+
|
|
13
|
+
### Documentation & Examples
|
|
14
|
+
- **Reorganized examples**: Moved agent examples to separate repository (`ollama-agent-examples`)
|
|
15
|
+
- Kept minimal client-focused examples in this repository
|
|
16
|
+
- Rewrote testing documentation to focus on client-only testing (transport/protocol)
|
|
17
|
+
- Added test checklist with specific test categories (G1-G3, C1-C3, A1-A2, F1-F3)
|
|
18
|
+
- Updated README with enhanced "What This Gem IS NOT" section
|
|
19
|
+
|
|
20
|
+
### Code Quality
|
|
21
|
+
- Fixed all RuboCop offenses
|
|
22
|
+
- Improved code quality and consistency
|
|
23
|
+
- Aligned workflow with agent-runtime repository
|
|
24
|
+
|
|
25
|
+
## 📦 Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
gem install ollama-client
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or add to your Gemfile:
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
gem 'ollama-client', '~> 0.2.6'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 🔗 Links
|
|
38
|
+
|
|
39
|
+
- [Full Changelog](https://github.com/shubhamtaywade82/ollama-client/blob/main/CHANGELOG.md)
|
|
40
|
+
- [Documentation](https://github.com/shubhamtaywade82/ollama-client#readme)
|
|
41
|
+
- [Examples Repository](https://github.com/shubhamtaywade82/ollama-agent-examples)
|