ollama-client 0.2.1 → 0.2.3
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 +8 -0
- data/README.md +220 -12
- data/docs/CLOUD.md +29 -0
- data/docs/CONSOLE_IMPROVEMENTS.md +256 -0
- data/docs/FEATURES_ADDED.md +145 -0
- data/docs/HANDLERS_ANALYSIS.md +190 -0
- data/docs/README.md +37 -0
- data/docs/SCHEMA_FIXES.md +147 -0
- data/docs/TEST_UPDATES.md +107 -0
- data/examples/README.md +92 -0
- data/examples/advanced_complex_schemas.rb +6 -3
- data/examples/advanced_multi_step_agent.rb +13 -7
- data/examples/chat_console.rb +143 -0
- data/examples/complete_workflow.rb +14 -4
- data/examples/dhan_console.rb +843 -0
- data/examples/dhanhq/agents/base_agent.rb +0 -2
- data/examples/dhanhq/agents/orchestrator_agent.rb +1 -2
- data/examples/dhanhq/agents/technical_analysis_agent.rb +67 -49
- data/examples/dhanhq/analysis/market_structure.rb +44 -28
- data/examples/dhanhq/analysis/pattern_recognizer.rb +64 -47
- data/examples/dhanhq/analysis/trend_analyzer.rb +6 -8
- data/examples/dhanhq/dhanhq_agent.rb +296 -99
- data/examples/dhanhq/indicators/technical_indicators.rb +3 -5
- data/examples/dhanhq/scanners/intraday_options_scanner.rb +360 -255
- data/examples/dhanhq/scanners/swing_scanner.rb +118 -84
- data/examples/dhanhq/schemas/agent_schemas.rb +2 -2
- data/examples/dhanhq/services/data_service.rb +5 -7
- data/examples/dhanhq/services/trading_service.rb +0 -3
- data/examples/dhanhq/technical_analysis_agentic_runner.rb +217 -84
- data/examples/dhanhq/technical_analysis_runner.rb +216 -162
- data/examples/dhanhq/test_tool_calling.rb +538 -0
- data/examples/dhanhq/test_tool_calling_verbose.rb +251 -0
- data/examples/dhanhq/utils/trading_parameter_normalizer.rb +12 -17
- data/examples/dhanhq_agent.rb +159 -116
- data/examples/dhanhq_tools.rb +1158 -251
- data/examples/multi_step_agent_with_external_data.rb +368 -0
- data/examples/structured_tools.rb +89 -0
- data/examples/test_dhanhq_tool_calling.rb +375 -0
- data/examples/test_tool_calling.rb +160 -0
- data/examples/tool_calling_direct.rb +124 -0
- 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 +116 -15
- data/lib/ollama/client.rb +118 -55
- 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 +104 -0
- data/lib/ollama/response.rb +121 -0
- data/lib/ollama/tool/function/parameters/property.rb +72 -0
- data/lib/ollama/tool/function/parameters.rb +101 -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
- metadata +31 -3
- /data/{PRODUCTION_FIXES.md → docs/PRODUCTION_FIXES.md} +0 -0
- /data/{TESTING.md → docs/TESTING.md} +0 -0
|
@@ -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/docs/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Internal Documentation
|
|
2
|
+
|
|
3
|
+
This directory contains internal development documentation for the ollama-client gem.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
### Design Documentation
|
|
8
|
+
- **[HANDLERS_ANALYSIS.md](HANDLERS_ANALYSIS.md)** - Analysis of handler architecture decisions (why we didn't adopt ollama-ruby's handler pattern)
|
|
9
|
+
- **[FEATURES_ADDED.md](FEATURES_ADDED.md)** - Features integrated from ollama-ruby that align with our agent-first philosophy
|
|
10
|
+
- **[PRODUCTION_FIXES.md](PRODUCTION_FIXES.md)** - Production-ready fixes for hybrid agents (JSON parsing, retry policy, etc.)
|
|
11
|
+
- **[SCHEMA_FIXES.md](SCHEMA_FIXES.md)** - Schema validation fixes and best practices for numeric constraints
|
|
12
|
+
- **[CONSOLE_IMPROVEMENTS.md](CONSOLE_IMPROVEMENTS.md)** - Interactive console UX improvements (thinking indicators, formatted tool results)
|
|
13
|
+
|
|
14
|
+
### Testing Documentation
|
|
15
|
+
- **[TESTING.md](TESTING.md)** - Testing guide and examples
|
|
16
|
+
- **[TEST_UPDATES.md](TEST_UPDATES.md)** - Recent test updates for DhanHQ tool calling enhancements
|
|
17
|
+
|
|
18
|
+
### CI/Automation
|
|
19
|
+
- **[CLOUD.md](CLOUD.md)** - Cloud agent guide for automated testing and fixes
|
|
20
|
+
|
|
21
|
+
## For Users
|
|
22
|
+
|
|
23
|
+
If you're looking for user-facing documentation, see:
|
|
24
|
+
- [Main README](../README.md) - Getting started, API reference, examples
|
|
25
|
+
- [CHANGELOG](../CHANGELOG.md) - Version history and changes
|
|
26
|
+
- [CONTRIBUTING](../CONTRIBUTING.md) - How to contribute
|
|
27
|
+
- [Examples](../examples/) - Working code examples
|
|
28
|
+
|
|
29
|
+
## For Contributors
|
|
30
|
+
|
|
31
|
+
These internal docs help maintainers understand:
|
|
32
|
+
- **Why** certain design decisions were made
|
|
33
|
+
- **What** features have been added and why
|
|
34
|
+
- **How** to test and maintain the codebase
|
|
35
|
+
- **Where** production fixes were applied
|
|
36
|
+
|
|
37
|
+
They are not intended for end users and can be safely ignored when using the gem.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Schema Validation Fixes
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
LLMs were returning confidence values as percentages (e.g., 95, 100) instead of decimals (e.g., 0.95, 1.0), causing schema validation errors:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
The property '#/confidence' did not have a maximum value of 1, inclusively
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Root Cause
|
|
12
|
+
|
|
13
|
+
JSON schemas defined numeric constraints (0-1) but lacked explicit descriptions explaining the expected format. LLMs naturally interpret "confidence" as percentages without guidance.
|
|
14
|
+
|
|
15
|
+
## Solution
|
|
16
|
+
|
|
17
|
+
Added explicit descriptions to all numeric fields with constrained ranges, clarifying the expected format.
|
|
18
|
+
|
|
19
|
+
### Fixed Fields
|
|
20
|
+
|
|
21
|
+
#### Confidence Fields (0.0 to 1.0)
|
|
22
|
+
Updated in 8 locations across the codebase:
|
|
23
|
+
|
|
24
|
+
- `examples/complete_workflow.rb` (2 instances)
|
|
25
|
+
- TaskPlanner schema
|
|
26
|
+
- DataAnalyzer schema
|
|
27
|
+
- `examples/dhanhq_agent.rb` (2 instances)
|
|
28
|
+
- `examples/dhanhq/schemas/agent_schemas.rb` (2 instances)
|
|
29
|
+
- `examples/dhanhq/agents/technical_analysis_agent.rb` (1 instance)
|
|
30
|
+
- `examples/advanced_multi_step_agent.rb` (1 instance)
|
|
31
|
+
|
|
32
|
+
**Before:**
|
|
33
|
+
```ruby
|
|
34
|
+
"confidence" => {
|
|
35
|
+
"type" => "number",
|
|
36
|
+
"minimum" => 0,
|
|
37
|
+
"maximum" => 1
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**After:**
|
|
42
|
+
```ruby
|
|
43
|
+
"confidence" => {
|
|
44
|
+
"type" => "number",
|
|
45
|
+
"minimum" => 0,
|
|
46
|
+
"maximum" => 1,
|
|
47
|
+
"description" => "Confidence in this decision (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Other Constrained Fields
|
|
52
|
+
|
|
53
|
+
- `reproducibility_score` in `advanced_complex_schemas.rb`
|
|
54
|
+
- Added: "Reproducibility score (0.0 to 1.0, where 1.0 means fully reproducible)"
|
|
55
|
+
|
|
56
|
+
- `profit_margin` in `advanced_complex_schemas.rb`
|
|
57
|
+
- Added: "Profit margin as percentage (0 to 100)"
|
|
58
|
+
|
|
59
|
+
- `overall_score` in `advanced_complex_schemas.rb`
|
|
60
|
+
- Added: "Overall quality score (0 to 100)"
|
|
61
|
+
|
|
62
|
+
## Best Practices
|
|
63
|
+
|
|
64
|
+
### When Defining Schemas
|
|
65
|
+
|
|
66
|
+
1. **Always include descriptions** for numeric fields with constraints
|
|
67
|
+
2. **Be explicit about format**: decimal (0.0-1.0) vs percentage (0-100)
|
|
68
|
+
3. **Provide examples** in descriptions when helpful
|
|
69
|
+
4. **Use clear units**: "as percentage", "as decimal", "where 1.0 is 100%"
|
|
70
|
+
|
|
71
|
+
### When Writing Prompts
|
|
72
|
+
|
|
73
|
+
**Schema descriptions alone may not be enough!** Always reinforce numeric formats in the prompt itself:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
# ❌ BAD: Relies only on schema description
|
|
77
|
+
result = @client.generate(
|
|
78
|
+
prompt: "Analyze this data: #{data}",
|
|
79
|
+
schema: @schema
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# ✅ GOOD: Explicit examples in prompt
|
|
83
|
+
result = @client.generate(
|
|
84
|
+
prompt: "Analyze this data: #{data}\n\nIMPORTANT: Express confidence as a decimal between 0.0 and 1.0 (e.g., 0.85 for 85% confidence, not 85).",
|
|
85
|
+
schema: @schema
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Why this matters:**
|
|
90
|
+
- LLMs may not always read schema descriptions carefully
|
|
91
|
+
- Concrete examples in prompts are more effective
|
|
92
|
+
- Prevents "100" vs "1.0" confusion
|
|
93
|
+
|
|
94
|
+
### Example Patterns
|
|
95
|
+
|
|
96
|
+
**Decimal confidence (0-1):**
|
|
97
|
+
```ruby
|
|
98
|
+
"confidence" => {
|
|
99
|
+
"type" => "number",
|
|
100
|
+
"minimum" => 0,
|
|
101
|
+
"maximum" => 1,
|
|
102
|
+
"description" => "Confidence level (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Percentage score (0-100):**
|
|
107
|
+
```ruby
|
|
108
|
+
"score" => {
|
|
109
|
+
"type" => "number",
|
|
110
|
+
"minimum" => 0,
|
|
111
|
+
"maximum" => 100,
|
|
112
|
+
"description" => "Quality score as percentage (0 to 100)"
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Probability (0-1):**
|
|
117
|
+
```ruby
|
|
118
|
+
"probability" => {
|
|
119
|
+
"type" => "number",
|
|
120
|
+
"minimum" => 0,
|
|
121
|
+
"maximum" => 1,
|
|
122
|
+
"description" => "Probability value (0.0 to 1.0)"
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Testing
|
|
127
|
+
|
|
128
|
+
All modified files passed syntax validation:
|
|
129
|
+
```bash
|
|
130
|
+
ruby -c examples/complete_workflow.rb # Syntax OK
|
|
131
|
+
ruby -c examples/dhanhq_agent.rb # Syntax OK
|
|
132
|
+
ruby -c examples/advanced_multi_step_agent.rb # Syntax OK
|
|
133
|
+
ruby -c examples/advanced_complex_schemas.rb # Syntax OK
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Impact
|
|
137
|
+
|
|
138
|
+
- **Examples now run without schema validation errors**
|
|
139
|
+
- **LLMs receive clear guidance** on numeric formats
|
|
140
|
+
- **Consistent patterns** across all example schemas
|
|
141
|
+
- **Better developer experience** with self-documenting schemas
|
|
142
|
+
|
|
143
|
+
## Related Files
|
|
144
|
+
|
|
145
|
+
See also:
|
|
146
|
+
- [Testing Guide](TESTING.md) - How to test structured outputs
|
|
147
|
+
- [Features Added](FEATURES_ADDED.md) - Schema validation features
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Test File Updates
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
Updated test examples to reflect recent enhancements to DhanHQ tool calling, particularly around historical data and technical indicators.
|
|
6
|
+
|
|
7
|
+
## Files Updated
|
|
8
|
+
|
|
9
|
+
### 1. `examples/test_dhanhq_tool_calling.rb`
|
|
10
|
+
|
|
11
|
+
#### Changes Made:
|
|
12
|
+
|
|
13
|
+
1. **Updated `historical_data_tool` definition** (lines 66-101):
|
|
14
|
+
- Changed `interval` enum from `["daily", "weekly", "monthly"]` to `["1", "5", "15", "25", "60"]`
|
|
15
|
+
- Added proper description: "Minute interval for intraday data. Omit for daily data."
|
|
16
|
+
- Added `calculate_indicators` boolean parameter
|
|
17
|
+
- Updated description to mention technical indicators (RSI, MACD, SMA, EMA, Bollinger Bands, ATR)
|
|
18
|
+
- Added `required` fields: `from_date` and `to_date`
|
|
19
|
+
|
|
20
|
+
2. **Added Test 5: Historical Data with Technical Indicators**
|
|
21
|
+
- Tests the new `calculate_indicators` parameter
|
|
22
|
+
- Verifies LLM includes all required parameters including interval
|
|
23
|
+
- Shows how to request intraday data with indicators
|
|
24
|
+
|
|
25
|
+
3. **Added Test 6: Intraday Data with 5-minute intervals**
|
|
26
|
+
- Tests intraday data specifically
|
|
27
|
+
- Uses current date dynamically
|
|
28
|
+
- Validates interval parameter is one of the valid values (1, 5, 15, 25, 60)
|
|
29
|
+
- Shows date range handling
|
|
30
|
+
|
|
31
|
+
4. **Enhanced Summary Section**
|
|
32
|
+
- Added notes about historical data enhancements
|
|
33
|
+
- Documents interval usage for intraday vs daily data
|
|
34
|
+
- Explains `calculate_indicators` feature and its benefits
|
|
35
|
+
|
|
36
|
+
## Key Features Tested
|
|
37
|
+
|
|
38
|
+
### Intraday Data
|
|
39
|
+
- ✅ Interval parameter with values: "1", "5", "15", "25", "60"
|
|
40
|
+
- ✅ Date handling (from_date, to_date)
|
|
41
|
+
- ✅ 5-minute intervals (most commonly used for intraday analysis)
|
|
42
|
+
|
|
43
|
+
### Technical Indicators
|
|
44
|
+
- ✅ `calculate_indicators` parameter
|
|
45
|
+
- ✅ Returns RSI, MACD, SMA, EMA, Bollinger Bands, ATR
|
|
46
|
+
- ✅ Reduces response size vs raw OHLCV data
|
|
47
|
+
|
|
48
|
+
### Tool Calling
|
|
49
|
+
- ✅ chat_raw() method for accessing tool_calls
|
|
50
|
+
- ✅ Structured Tool classes
|
|
51
|
+
- ✅ Parameter validation
|
|
52
|
+
|
|
53
|
+
## Example Usage
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
# Get intraday data with indicators
|
|
57
|
+
historical_data_tool = Ollama::Tool.new(
|
|
58
|
+
type: "function",
|
|
59
|
+
function: Ollama::Tool::Function.new(
|
|
60
|
+
name: "get_historical_data",
|
|
61
|
+
description: "Get historical price data (OHLCV) or technical indicators...",
|
|
62
|
+
parameters: Ollama::Tool::Function::Parameters.new(
|
|
63
|
+
type: "object",
|
|
64
|
+
properties: {
|
|
65
|
+
interval: Ollama::Tool::Function::Parameters::Property.new(
|
|
66
|
+
type: "string",
|
|
67
|
+
description: "Minute interval for intraday data",
|
|
68
|
+
enum: %w[1 5 15 25 60] # Updated from ["daily", "weekly", "monthly"]
|
|
69
|
+
),
|
|
70
|
+
calculate_indicators: Ollama::Tool::Function::Parameters::Property.new(
|
|
71
|
+
type: "boolean",
|
|
72
|
+
description: "If true, returns technical indicators instead of raw data"
|
|
73
|
+
),
|
|
74
|
+
# ... other properties
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Request with intraday and indicators
|
|
81
|
+
response = client.chat_raw(
|
|
82
|
+
messages: [Ollama::Agent::Messages.user(
|
|
83
|
+
"Get NIFTY intraday data with 5-minute intervals and technical indicators"
|
|
84
|
+
)],
|
|
85
|
+
tools: historical_data_tool
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Testing
|
|
90
|
+
|
|
91
|
+
Run the updated tests:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Tool calling examples
|
|
95
|
+
ruby examples/test_dhanhq_tool_calling.rb
|
|
96
|
+
ruby examples/test_tool_calling.rb
|
|
97
|
+
|
|
98
|
+
# DhanHQ specific tests
|
|
99
|
+
ruby examples/dhanhq/test_tool_calling.rb
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Notes
|
|
103
|
+
|
|
104
|
+
- The `interval` parameter is now correctly defined for intraday minute intervals
|
|
105
|
+
- The old values ("daily", "weekly", "monthly") were incorrect for the DhanHQ API
|
|
106
|
+
- The new `calculate_indicators` parameter provides technical analysis without large response sizes
|
|
107
|
+
- Tests now include date handling examples using `Date.today`
|