ollama-client 0.2.0 → 0.2.2
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/FEATURES_ADDED.md +145 -0
- data/HANDLERS_ANALYSIS.md +190 -0
- data/README.md +213 -11
- data/examples/advanced_multi_step_agent.rb +100 -18
- data/examples/chat_console.rb +134 -0
- data/examples/dhan_console.rb +748 -0
- data/examples/dhanhq/README.md +236 -0
- data/examples/dhanhq/agents/base_agent.rb +74 -0
- data/examples/dhanhq/agents/data_agent.rb +66 -0
- data/examples/dhanhq/agents/orchestrator_agent.rb +120 -0
- data/examples/dhanhq/agents/technical_analysis_agent.rb +247 -0
- data/examples/dhanhq/agents/trading_agent.rb +81 -0
- data/examples/dhanhq/analysis/market_structure.rb +138 -0
- data/examples/dhanhq/analysis/pattern_recognizer.rb +192 -0
- data/examples/dhanhq/analysis/trend_analyzer.rb +88 -0
- data/examples/dhanhq/builders/market_context_builder.rb +67 -0
- data/examples/dhanhq/dhanhq_agent.rb +829 -0
- data/examples/dhanhq/indicators/technical_indicators.rb +158 -0
- data/examples/dhanhq/scanners/intraday_options_scanner.rb +492 -0
- data/examples/dhanhq/scanners/swing_scanner.rb +247 -0
- data/examples/dhanhq/schemas/agent_schemas.rb +61 -0
- data/examples/dhanhq/services/base_service.rb +46 -0
- data/examples/dhanhq/services/data_service.rb +118 -0
- data/examples/dhanhq/services/trading_service.rb +59 -0
- data/examples/dhanhq/technical_analysis_agentic_runner.rb +411 -0
- data/examples/dhanhq/technical_analysis_runner.rb +420 -0
- data/examples/dhanhq/test_tool_calling.rb +538 -0
- data/examples/dhanhq/test_tool_calling_verbose.rb +251 -0
- data/examples/dhanhq/utils/instrument_helper.rb +32 -0
- data/examples/dhanhq/utils/parameter_cleaner.rb +28 -0
- data/examples/dhanhq/utils/parameter_normalizer.rb +45 -0
- data/examples/dhanhq/utils/rate_limiter.rb +23 -0
- data/examples/dhanhq/utils/trading_parameter_normalizer.rb +72 -0
- data/examples/dhanhq_agent.rb +253 -51
- data/examples/dhanhq_tools.rb +1179 -144
- data/examples/structured_tools.rb +89 -0
- data/examples/tool_calling_direct.rb +124 -0
- data/examples/tool_calling_pattern.rb +4 -1
- data/examples/tool_dto_example.rb +94 -0
- data/exe/dhan_console +4 -0
- data/exe/ollama-client +1 -1
- data/lib/ollama/agent/executor.rb +117 -16
- data/lib/ollama/client.rb +78 -8
- data/lib/ollama/config.rb +36 -0
- data/lib/ollama/dto.rb +187 -0
- data/lib/ollama/embeddings.rb +77 -0
- data/lib/ollama/options.rb +96 -0
- data/lib/ollama/response.rb +123 -0
- data/lib/ollama/tool/function/parameters/property.rb +72 -0
- data/lib/ollama/tool/function/parameters.rb +100 -0
- data/lib/ollama/tool/function.rb +78 -0
- data/lib/ollama/tool.rb +60 -0
- data/lib/ollama/version.rb +1 -1
- data/lib/ollama_client.rb +3 -0
- data/test_dhanhq_tool_calling.rb +282 -0
- data/test_tool_calling.rb +160 -0
- metadata +48 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86bef7e3dc6197748e9d75572705cec97bc94a24da8c9e8f7402d9b5db1e1dc8
|
|
4
|
+
data.tar.gz: 1ae799bfc340896179b3819350b81fe852c8f2b944f6987cf4f8c76b61791153
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1b4a54c4625c0bcb947d74e914bedc0f974e6b0bbaad6f4f46673b8dce5eb6956c5a3bc75745845ccd7f79830149a24ad1e49c54bc03ef165c39ed71d14a92db
|
|
7
|
+
data.tar.gz: e2ce9114ab3396d65a3075f80c1d273e0d414d2d8be0d4bae4b5e1717fdc62451d2a57590d59e191be86613280fbbd925201ba9d1285a95a2d0cdfabdafc25c3
|
data/FEATURES_ADDED.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# New Features Added from ollama-ruby
|
|
2
|
+
|
|
3
|
+
This document describes the features we've integrated from `ollama-ruby` that align with our **agent-first philosophy**.
|
|
4
|
+
|
|
5
|
+
## ✅ Features Added
|
|
6
|
+
|
|
7
|
+
### 1. Embeddings API (`client.embeddings`)
|
|
8
|
+
|
|
9
|
+
**Purpose**: Enable RAG (Retrieval-Augmented Generation) and semantic search in agents.
|
|
10
|
+
|
|
11
|
+
**Why it fits**: Agents often need to search knowledge bases, compare documents, and build context from embeddings.
|
|
12
|
+
|
|
13
|
+
**Usage**:
|
|
14
|
+
```ruby
|
|
15
|
+
embedding = client.embeddings.embed(model: "all-minilm", input: "What is Ruby?")
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Files Added**:
|
|
19
|
+
- `lib/ollama/embeddings.rb` - Embeddings API wrapper
|
|
20
|
+
- Updated `lib/ollama/client.rb` - Added `embeddings` accessor
|
|
21
|
+
|
|
22
|
+
### 2. Config Loading from JSON (`Config.load_from_json`)
|
|
23
|
+
|
|
24
|
+
**Purpose**: Load configuration from JSON files for production deployments.
|
|
25
|
+
|
|
26
|
+
**Why it fits**: Production agents need configuration management without hardcoding values.
|
|
27
|
+
|
|
28
|
+
**Usage**:
|
|
29
|
+
```ruby
|
|
30
|
+
config = Ollama::Config.load_from_json("config.json")
|
|
31
|
+
client = Ollama::Client.new(config: config)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Files Modified**:
|
|
35
|
+
- `lib/ollama/config.rb` - Added `load_from_json` class method
|
|
36
|
+
|
|
37
|
+
### 3. Options Class (`Ollama::Options`)
|
|
38
|
+
|
|
39
|
+
**Purpose**: Type-safe model parameter configuration with validation.
|
|
40
|
+
|
|
41
|
+
**Why it fits**: Agents need to adjust model behavior dynamically with safety guarantees.
|
|
42
|
+
|
|
43
|
+
**Usage**:
|
|
44
|
+
```ruby
|
|
45
|
+
options = Ollama::Options.new(temperature: 0.7, top_p: 0.95)
|
|
46
|
+
client.generate(prompt: "...", schema: {...}, options: options.to_h)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Files Added**:
|
|
50
|
+
- `lib/ollama/options.rb` - Options class with type checking
|
|
51
|
+
|
|
52
|
+
### 4. Structured Tool Classes (`Ollama::Tool`, `Tool::Function`, etc.)
|
|
53
|
+
|
|
54
|
+
**Purpose**: Type-safe, explicit tool schema definitions for agent tools.
|
|
55
|
+
|
|
56
|
+
**Why it fits**: Production agents need explicit control over tool schemas beyond auto-inference. Enables enum constraints, detailed descriptions, and better documentation.
|
|
57
|
+
|
|
58
|
+
**Usage**:
|
|
59
|
+
```ruby
|
|
60
|
+
# Define explicit schema
|
|
61
|
+
property = Ollama::Tool::Function::Parameters::Property.new(
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "City name",
|
|
64
|
+
enum: %w[paris london tokyo] # Optional enum constraint
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
params = Ollama::Tool::Function::Parameters.new(
|
|
68
|
+
type: "object",
|
|
69
|
+
properties: { city: property },
|
|
70
|
+
required: %w[city]
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
function = Ollama::Tool::Function.new(
|
|
74
|
+
name: "get_weather",
|
|
75
|
+
description: "Get weather for a city",
|
|
76
|
+
parameters: params
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
tool = Ollama::Tool.new(type: "function", function: function)
|
|
80
|
+
|
|
81
|
+
# Use with Executor (explicit schema + callable)
|
|
82
|
+
tools = {
|
|
83
|
+
"get_weather" => {
|
|
84
|
+
tool: tool,
|
|
85
|
+
callable: ->(city:) { { city: city, temp: "22C" } }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Files Added**:
|
|
91
|
+
- `lib/ollama/dto.rb` - Simplified DTO module (no external dependencies)
|
|
92
|
+
- `lib/ollama/tool.rb` - Tool class with DTO support
|
|
93
|
+
- `lib/ollama/tool/function.rb` - Function definition with DTO support
|
|
94
|
+
- `lib/ollama/tool/function/parameters.rb` - Parameters specification with DTO support
|
|
95
|
+
- `lib/ollama/tool/function/parameters/property.rb` - Property definition with DTO support
|
|
96
|
+
- Updated `lib/ollama/agent/executor.rb` - Support for explicit Tool objects
|
|
97
|
+
- `examples/tool_dto_example.rb` - DTO serialization/deserialization examples
|
|
98
|
+
|
|
99
|
+
**DTO Features:**
|
|
100
|
+
- `to_json` - JSON serialization
|
|
101
|
+
- `from_hash` - Deserialization from hash/JSON
|
|
102
|
+
- `==` - Equality comparison based on hash representation
|
|
103
|
+
- `empty?` - Check if object has no meaningful attributes
|
|
104
|
+
|
|
105
|
+
All Tool classes include the DTO module, enabling serialization for storage, API responses, and testing.
|
|
106
|
+
|
|
107
|
+
## 🎯 Design Decisions
|
|
108
|
+
|
|
109
|
+
### What We Added
|
|
110
|
+
- ✅ Features that directly support agent workflows
|
|
111
|
+
- ✅ Type safety and validation (Options class)
|
|
112
|
+
- ✅ Production deployment needs (JSON config)
|
|
113
|
+
- ✅ RAG capabilities (embeddings)
|
|
114
|
+
|
|
115
|
+
### What We Didn't Add
|
|
116
|
+
- ❌ Handler-based architecture (doesn't fit our schema-first approach)
|
|
117
|
+
- See `HANDLERS_ANALYSIS.md` for detailed comparison
|
|
118
|
+
- We use `StreamingObserver` instead for presentation-only streaming
|
|
119
|
+
- ❌ Interactive console (not needed for agents)
|
|
120
|
+
- ❌ CLI executables (outside our scope)
|
|
121
|
+
- ❌ Full API coverage (we focus on agent building blocks)
|
|
122
|
+
|
|
123
|
+
## 📝 Examples
|
|
124
|
+
|
|
125
|
+
See `examples/structured_tools.rb` and `examples/tool_dto_example.rb` for complete examples demonstrating:
|
|
126
|
+
- Structured tool definitions
|
|
127
|
+
- RAG agent with embeddings
|
|
128
|
+
- Options usage for fine-tuning
|
|
129
|
+
|
|
130
|
+
## 🔄 Migration Notes
|
|
131
|
+
|
|
132
|
+
All new features are **additive** and **backward compatible**:
|
|
133
|
+
- Existing code continues to work unchanged
|
|
134
|
+
- New features are opt-in
|
|
135
|
+
- No breaking changes to existing APIs
|
|
136
|
+
|
|
137
|
+
## 🚀 Next Steps
|
|
138
|
+
|
|
139
|
+
These features enable:
|
|
140
|
+
1. **RAG Agents**: Build knowledge bases with semantic search
|
|
141
|
+
2. **Production Deployments**: JSON-based configuration
|
|
142
|
+
3. **Fine-Tuning**: Type-safe model parameter adjustment
|
|
143
|
+
4. **Structured Tools**: Explicit tool schemas with enum constraints and validation
|
|
144
|
+
|
|
145
|
+
All while maintaining our **agent-first philosophy** and **safety guarantees**.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Handlers Analysis: ollama-ruby vs ollama-client
|
|
2
|
+
|
|
3
|
+
## Handlers in ollama-ruby
|
|
4
|
+
|
|
5
|
+
The `ollama-ruby` gem uses a **handler-based architecture** where handlers respond to `to_proc` and return lambda expressions to process responses:
|
|
6
|
+
|
|
7
|
+
| Handler | Purpose | Use Case |
|
|
8
|
+
|---------|---------|----------|
|
|
9
|
+
| **Collector** | Collects all responses in an array | Streaming responses |
|
|
10
|
+
| **Single** | Returns single response directly | Non-streaming responses |
|
|
11
|
+
| **Progress** | Progress bar for create/pull/push | Model management operations |
|
|
12
|
+
| **DumpJSON** | Dumps responses as JSON | Debugging/inspection |
|
|
13
|
+
| **DumpYAML** | Dumps responses as YAML | Debugging/inspection |
|
|
14
|
+
| **Print** | Prints to display | Interactive use |
|
|
15
|
+
| **Markdown** | Prints as ANSI markdown | Interactive use |
|
|
16
|
+
| **Say** | Text-to-speech output | Accessibility |
|
|
17
|
+
| **NOP** | Does nothing | Silent operations |
|
|
18
|
+
|
|
19
|
+
## Why We Didn't Add Handlers
|
|
20
|
+
|
|
21
|
+
### 1. **Philosophical Mismatch**
|
|
22
|
+
|
|
23
|
+
**ollama-ruby approach:**
|
|
24
|
+
```ruby
|
|
25
|
+
# Handler-based, flexible, general-purpose
|
|
26
|
+
ollama.chat(model: 'llama3.1', stream: true, messages: msgs, &Print)
|
|
27
|
+
ollama.generate(model: 'llama3.1', prompt: '...', &Markdown)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**ollama-client approach:**
|
|
31
|
+
```ruby
|
|
32
|
+
# Schema-first, contract-based, agent-focused
|
|
33
|
+
result = client.generate(prompt: '...', schema: schema)
|
|
34
|
+
# Returns validated, structured data directly
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. **Different Return Semantics**
|
|
38
|
+
|
|
39
|
+
- **ollama-ruby**: Handlers control what gets returned (could be array, single value, nothing)
|
|
40
|
+
- **ollama-client**: Always returns validated, structured data matching the schema
|
|
41
|
+
|
|
42
|
+
### 3. **State Management**
|
|
43
|
+
|
|
44
|
+
- **ollama-ruby**: Handlers are stateless processors
|
|
45
|
+
- **ollama-client**: We have explicit state (Planner stateless, Executor stateful via messages)
|
|
46
|
+
|
|
47
|
+
### 4. **Streaming Philosophy**
|
|
48
|
+
|
|
49
|
+
- **ollama-ruby**: Handlers process streaming chunks (could affect control flow)
|
|
50
|
+
- **ollama-client**: Streaming is **presentation-only** via `StreamingObserver` (never affects control flow)
|
|
51
|
+
|
|
52
|
+
## What We Have Instead
|
|
53
|
+
|
|
54
|
+
### StreamingObserver (Agent-Focused)
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
observer = Ollama::StreamingObserver.new do |event|
|
|
58
|
+
case event.type
|
|
59
|
+
when :token
|
|
60
|
+
print event.text
|
|
61
|
+
when :tool_call_detected
|
|
62
|
+
puts "\n[Tool: #{event.name}]"
|
|
63
|
+
when :state
|
|
64
|
+
puts "State: #{event.state}"
|
|
65
|
+
when :final
|
|
66
|
+
puts "\n--- DONE ---"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
executor = Ollama::Agent::Executor.new(client, tools: tools, stream: observer)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Key differences:**
|
|
74
|
+
- ✅ Explicit event types (`:token`, `:tool_call_detected`, `:state`, `:final`)
|
|
75
|
+
- ✅ Never affects control flow (presentation-only)
|
|
76
|
+
- ✅ Agent-aware (knows about tool calls, state transitions)
|
|
77
|
+
- ✅ Structured events (not raw response chunks)
|
|
78
|
+
|
|
79
|
+
### Direct Return Values
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
# Always returns validated, structured data
|
|
83
|
+
result = client.generate(prompt: '...', schema: schema)
|
|
84
|
+
# result is a Hash matching the schema exactly
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**vs ollama-ruby:**
|
|
88
|
+
```ruby
|
|
89
|
+
# Handler determines return value
|
|
90
|
+
result = ollama.generate(model: '...', prompt: '...', &Collector)
|
|
91
|
+
# result could be array, single value, or nil depending on handler
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Potential Handler-Like Utilities for Agents
|
|
95
|
+
|
|
96
|
+
While we don't want the full handler architecture, there might be value in **debugging/development utilities**:
|
|
97
|
+
|
|
98
|
+
### 1. **Response Debugger** (Useful for Agents)
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
# Could add as a utility, not a handler
|
|
102
|
+
module Ollama
|
|
103
|
+
module Debug
|
|
104
|
+
def self.dump_json(response, output: $stdout)
|
|
105
|
+
output.puts JSON.pretty_generate(response)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def self.dump_yaml(response, output: $stdout)
|
|
109
|
+
require 'yaml'
|
|
110
|
+
output.puts response.to_yaml
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Usage:
|
|
116
|
+
result = client.generate(prompt: '...', schema: schema)
|
|
117
|
+
Ollama::Debug.dump_json(result) if ENV['DEBUG']
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 2. **Progress Indicator** (For Long-Running Agent Operations)
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
# Could add for agent workflows that take time
|
|
124
|
+
module Ollama
|
|
125
|
+
module Agent
|
|
126
|
+
class ProgressIndicator
|
|
127
|
+
def initialize(total_steps:)
|
|
128
|
+
@total = total_steps
|
|
129
|
+
@current = 0
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def step(message = nil)
|
|
133
|
+
@current += 1
|
|
134
|
+
print "\r[#{@current}/#{@total}] #{message || 'Processing...'}"
|
|
135
|
+
$stdout.flush
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def finish
|
|
139
|
+
puts "\n✓ Complete"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 3. **Response Formatter** (For Agent Output)
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
# Could add for pretty-printing agent responses
|
|
150
|
+
module Ollama
|
|
151
|
+
module Format
|
|
152
|
+
def self.markdown(text, output: $stdout)
|
|
153
|
+
# Use a markdown library to format
|
|
154
|
+
output.puts text
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def self.structured(data, output: $stdout)
|
|
158
|
+
output.puts JSON.pretty_generate(data)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Recommendation
|
|
165
|
+
|
|
166
|
+
**Don't add handlers** because:
|
|
167
|
+
1. ❌ They conflict with our schema-first, contract-based approach
|
|
168
|
+
2. ❌ They introduce ambiguity about return values
|
|
169
|
+
3. ❌ They don't fit our explicit state management
|
|
170
|
+
4. ❌ Our `StreamingObserver` already handles presentation needs
|
|
171
|
+
|
|
172
|
+
**Do consider** adding **utility modules** for:
|
|
173
|
+
1. ✅ Debugging helpers (`Ollama::Debug.dump_json`)
|
|
174
|
+
2. ✅ Progress indicators for long agent workflows
|
|
175
|
+
3. ✅ Response formatters (if needed for agent output)
|
|
176
|
+
|
|
177
|
+
These would be **explicit utilities** rather than **handler callbacks**, maintaining our philosophy while providing useful development tools.
|
|
178
|
+
|
|
179
|
+
## Summary
|
|
180
|
+
|
|
181
|
+
| Aspect | ollama-ruby Handlers | ollama-client Approach |
|
|
182
|
+
|--------|---------------------|------------------------|
|
|
183
|
+
| **Architecture** | Handler-based callbacks | Direct return values + StreamingObserver |
|
|
184
|
+
| **Return Values** | Handler-dependent | Always validated, structured data |
|
|
185
|
+
| **Streaming** | Handler processes chunks | Observer emits events (presentation-only) |
|
|
186
|
+
| **State** | Stateless processors | Explicit state (Planner/Executor) |
|
|
187
|
+
| **Use Case** | General-purpose, flexible | Agent-focused, contract-based |
|
|
188
|
+
| **Debugging** | DumpJSON/DumpYAML handlers | Could add utility modules |
|
|
189
|
+
|
|
190
|
+
**Conclusion**: Handlers don't fit our agent-first philosophy, but we could add explicit utility modules for debugging/development needs.
|
data/README.md
CHANGED
|
@@ -36,15 +36,15 @@ This keeps it **clean and future-proof**.
|
|
|
36
36
|
|
|
37
37
|
## 🔒 Guarantees
|
|
38
38
|
|
|
39
|
-
| Guarantee
|
|
40
|
-
|
|
|
41
|
-
| Client requests are explicit
|
|
42
|
-
| Planner is stateless (no hidden memory)| ✅ |
|
|
43
|
-
| Executor is stateful (explicit messages)| ✅
|
|
44
|
-
| Retry bounded
|
|
45
|
-
| Schema validated (when schema provided)| ✅ |
|
|
46
|
-
| Tools run in Ruby (not in the LLM)
|
|
47
|
-
| Streaming is display-only (Executor)
|
|
39
|
+
| Guarantee | Yes |
|
|
40
|
+
| ---------------------------------------- | --- |
|
|
41
|
+
| Client requests are explicit | ✅ |
|
|
42
|
+
| Planner is stateless (no hidden memory) | ✅ |
|
|
43
|
+
| Executor is stateful (explicit messages) | ✅ |
|
|
44
|
+
| Retry bounded | ✅ |
|
|
45
|
+
| Schema validated (when schema provided) | ✅ |
|
|
46
|
+
| Tools run in Ruby (not in the LLM) | ✅ |
|
|
47
|
+
| Streaming is display-only (Executor) | ✅ |
|
|
48
48
|
|
|
49
49
|
**Non-negotiable safety rule:** the **LLM never executes side effects**. It may request a tool call; **your Ruby code** executes the tool.
|
|
50
50
|
|
|
@@ -97,8 +97,8 @@ gem install ollama-client
|
|
|
97
97
|
|
|
98
98
|
This gem intentionally focuses on **agent building blocks**:
|
|
99
99
|
|
|
100
|
-
- **Supported**: `/api/generate`, `/api/chat`, `/api/tags`, `/api/ping`
|
|
101
|
-
- **Not guaranteed**: full endpoint parity with every Ollama release (
|
|
100
|
+
- **Supported**: `/api/generate`, `/api/chat`, `/api/tags`, `/api/ping`, `/api/embeddings`
|
|
101
|
+
- **Not guaranteed**: full endpoint parity with every Ollama release (advanced model mgmt, etc.)
|
|
102
102
|
|
|
103
103
|
### Agent endpoint mapping (unambiguous)
|
|
104
104
|
|
|
@@ -130,6 +130,8 @@ puts plan
|
|
|
130
130
|
|
|
131
131
|
### Executor Agent (tool loop, /api/chat)
|
|
132
132
|
|
|
133
|
+
**Simple approach (auto-inferred schemas):**
|
|
134
|
+
|
|
133
135
|
```ruby
|
|
134
136
|
require "ollama_client"
|
|
135
137
|
require "json"
|
|
@@ -151,6 +153,68 @@ answer = executor.run(
|
|
|
151
153
|
puts answer
|
|
152
154
|
```
|
|
153
155
|
|
|
156
|
+
**Structured approach (explicit schemas with Tool classes):**
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
require "ollama_client"
|
|
160
|
+
|
|
161
|
+
# Define explicit tool schema
|
|
162
|
+
location_prop = Ollama::Tool::Function::Parameters::Property.new(
|
|
163
|
+
type: "string",
|
|
164
|
+
description: "The city name"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
params = Ollama::Tool::Function::Parameters.new(
|
|
168
|
+
type: "object",
|
|
169
|
+
properties: { city: location_prop },
|
|
170
|
+
required: %w[city]
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
function = Ollama::Tool::Function.new(
|
|
174
|
+
name: "fetch_weather",
|
|
175
|
+
description: "Get weather for a city",
|
|
176
|
+
parameters: params
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
tool = Ollama::Tool.new(type: "function", function: function)
|
|
180
|
+
|
|
181
|
+
# Associate tool schema with callable
|
|
182
|
+
tools = {
|
|
183
|
+
"fetch_weather" => {
|
|
184
|
+
tool: tool,
|
|
185
|
+
callable: ->(city:) { { city: city, forecast: "sunny" } }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
executor = Ollama::Agent::Executor.new(client, tools: tools)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Use structured tools when you need:
|
|
193
|
+
- Explicit control over parameter types and descriptions
|
|
194
|
+
- Enum constraints on parameters
|
|
195
|
+
- Better documentation for complex tools
|
|
196
|
+
- Serialization/deserialization (JSON storage, API responses)
|
|
197
|
+
|
|
198
|
+
**DTO (Data Transfer Object) functionality:**
|
|
199
|
+
|
|
200
|
+
All Tool classes support serialization and deserialization:
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
# Serialize to JSON
|
|
204
|
+
json = tool.to_json
|
|
205
|
+
|
|
206
|
+
# Deserialize from hash
|
|
207
|
+
tool = Ollama::Tool.from_hash(JSON.parse(json))
|
|
208
|
+
|
|
209
|
+
# Equality comparison
|
|
210
|
+
tool1 == tool2 # Compares hash representations
|
|
211
|
+
|
|
212
|
+
# Empty check
|
|
213
|
+
params.empty? # True if no properties/required fields
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
See `examples/tool_dto_example.rb` for complete DTO usage examples.
|
|
217
|
+
|
|
154
218
|
### Streaming (Executor only; presentation-only)
|
|
155
219
|
|
|
156
220
|
Streaming is treated as **presentation**, not control. The agent buffers the full assistant message and only
|
|
@@ -407,6 +471,67 @@ rescue Ollama::Error => e
|
|
|
407
471
|
end
|
|
408
472
|
```
|
|
409
473
|
|
|
474
|
+
### Example: Tool Calling (Direct API Usage)
|
|
475
|
+
|
|
476
|
+
For tool calling, use `chat_raw()` to access `tool_calls` from the response:
|
|
477
|
+
|
|
478
|
+
```ruby
|
|
479
|
+
require "ollama_client"
|
|
480
|
+
|
|
481
|
+
client = Ollama::Client.new
|
|
482
|
+
|
|
483
|
+
# Define tool using Tool classes
|
|
484
|
+
tool = Ollama::Tool.new(
|
|
485
|
+
type: "function",
|
|
486
|
+
function: Ollama::Tool::Function.new(
|
|
487
|
+
name: "get_current_weather",
|
|
488
|
+
description: "Get the current weather for a location",
|
|
489
|
+
parameters: Ollama::Tool::Function::Parameters.new(
|
|
490
|
+
type: "object",
|
|
491
|
+
properties: {
|
|
492
|
+
location: Ollama::Tool::Function::Parameters::Property.new(
|
|
493
|
+
type: "string",
|
|
494
|
+
description: "The location to get the weather for, e.g. San Francisco, CA"
|
|
495
|
+
),
|
|
496
|
+
temperature_unit: Ollama::Tool::Function::Parameters::Property.new(
|
|
497
|
+
type: "string",
|
|
498
|
+
description: "The unit to return the temperature in",
|
|
499
|
+
enum: %w[celsius fahrenheit]
|
|
500
|
+
)
|
|
501
|
+
},
|
|
502
|
+
required: %w[location temperature_unit]
|
|
503
|
+
)
|
|
504
|
+
)
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
# Create message
|
|
508
|
+
message = Ollama::Agent::Messages.user("What is the weather today in Paris?")
|
|
509
|
+
|
|
510
|
+
# Use chat_raw() to get full response with tool_calls
|
|
511
|
+
response = client.chat_raw(
|
|
512
|
+
model: "llama3.1:8b",
|
|
513
|
+
messages: [message],
|
|
514
|
+
tools: tool, # Pass Tool object directly (or array of Tool objects)
|
|
515
|
+
allow_chat: true
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
# Access tool_calls from response
|
|
519
|
+
tool_calls = response.dig("message", "tool_calls")
|
|
520
|
+
if tool_calls && !tool_calls.empty?
|
|
521
|
+
tool_calls.each do |call|
|
|
522
|
+
name = call.dig("function", "name")
|
|
523
|
+
args = call.dig("function", "arguments")
|
|
524
|
+
puts "Tool: #{name}, Args: #{args}"
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
**Note:**
|
|
530
|
+
- `chat()` returns only the content (for simple use cases)
|
|
531
|
+
- `chat_raw()` returns the full response with `message.tool_calls` (for tool calling)
|
|
532
|
+
- Both methods accept `tools:` parameter (Tool object, array of Tool objects, or array of hashes)
|
|
533
|
+
- For agent tool loops, use `Ollama::Agent::Executor` instead (handles tool execution automatically)
|
|
534
|
+
|
|
410
535
|
### Example: Data Analysis with Validation
|
|
411
536
|
|
|
412
537
|
```ruby
|
|
@@ -505,6 +630,83 @@ models = client.list_models
|
|
|
505
630
|
puts "Available models: #{models.join(', ')}"
|
|
506
631
|
```
|
|
507
632
|
|
|
633
|
+
### Embeddings for RAG/Semantic Search
|
|
634
|
+
|
|
635
|
+
Use embeddings for building knowledge bases and semantic search in agents:
|
|
636
|
+
|
|
637
|
+
```ruby
|
|
638
|
+
require "ollama_client"
|
|
639
|
+
|
|
640
|
+
client = Ollama::Client.new
|
|
641
|
+
|
|
642
|
+
# Single text embedding
|
|
643
|
+
embedding = client.embeddings.embed(
|
|
644
|
+
model: "all-minilm",
|
|
645
|
+
input: "What is Ruby programming?"
|
|
646
|
+
)
|
|
647
|
+
# Returns: [0.123, -0.456, ...] (array of floats)
|
|
648
|
+
|
|
649
|
+
# Multiple texts
|
|
650
|
+
embeddings = client.embeddings.embed(
|
|
651
|
+
model: "all-minilm",
|
|
652
|
+
input: ["What is Ruby?", "What is Python?", "What is JavaScript?"]
|
|
653
|
+
)
|
|
654
|
+
# Returns: [[...], [...], [...]] (array of embedding arrays)
|
|
655
|
+
|
|
656
|
+
# Use for semantic similarity in agents
|
|
657
|
+
def find_similar(query_embedding, document_embeddings, threshold: 0.7)
|
|
658
|
+
document_embeddings.select do |doc_emb|
|
|
659
|
+
cosine_similarity(query_embedding, doc_emb) > threshold
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Configuration from JSON
|
|
665
|
+
|
|
666
|
+
Load configuration from JSON files for production deployments:
|
|
667
|
+
|
|
668
|
+
```ruby
|
|
669
|
+
require "ollama_client"
|
|
670
|
+
|
|
671
|
+
# config.json:
|
|
672
|
+
# {
|
|
673
|
+
# "base_url": "http://localhost:11434",
|
|
674
|
+
# "model": "llama3.1:8b",
|
|
675
|
+
# "timeout": 30,
|
|
676
|
+
# "retries": 3,
|
|
677
|
+
# "temperature": 0.2
|
|
678
|
+
# }
|
|
679
|
+
|
|
680
|
+
config = Ollama::Config.load_from_json("config.json")
|
|
681
|
+
client = Ollama::Client.new(config: config)
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
### Type-Safe Model Options
|
|
685
|
+
|
|
686
|
+
Use the `Options` class for type-checked model parameters:
|
|
687
|
+
|
|
688
|
+
```ruby
|
|
689
|
+
require "ollama_client"
|
|
690
|
+
|
|
691
|
+
# Options with validation
|
|
692
|
+
options = Ollama::Options.new(
|
|
693
|
+
temperature: 0.7,
|
|
694
|
+
top_p: 0.95,
|
|
695
|
+
top_k: 40,
|
|
696
|
+
num_ctx: 4096,
|
|
697
|
+
seed: 42
|
|
698
|
+
)
|
|
699
|
+
|
|
700
|
+
# Will raise ArgumentError if values are out of range
|
|
701
|
+
# options.temperature = 3.0 # Error: temperature must be between 0.0 and 2.0
|
|
702
|
+
|
|
703
|
+
client.generate(
|
|
704
|
+
prompt: "Analyze this data",
|
|
705
|
+
schema: analysis_schema,
|
|
706
|
+
options: options.to_h
|
|
707
|
+
)
|
|
708
|
+
```
|
|
709
|
+
|
|
508
710
|
### Error Handling
|
|
509
711
|
|
|
510
712
|
```ruby
|