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
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Example: Tool Calling Pattern (as documented in README)
|
|
5
|
-
# Demonstrates the correct architecture: LLM outputs intent, agent executes tools
|
|
6
|
-
# This matches the pattern shown in README.md lines 430-500
|
|
7
|
-
|
|
8
|
-
require "json"
|
|
9
|
-
require_relative "../lib/ollama_client"
|
|
10
|
-
|
|
11
|
-
# Tool Registry - stores available tools
|
|
12
|
-
class ToolRegistry
|
|
13
|
-
def initialize
|
|
14
|
-
@tools = {}
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def register(name, tool)
|
|
18
|
-
@tools[name] = tool
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def fetch(name)
|
|
22
|
-
@tools.fetch(name) { raise "Tool '#{name}' not found. Available: #{@tools.keys.join(', ')}" }
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def available
|
|
26
|
-
@tools.keys
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Base Tool class
|
|
31
|
-
class Tool
|
|
32
|
-
attr_reader :name, :description
|
|
33
|
-
|
|
34
|
-
def initialize(name:, description:)
|
|
35
|
-
@name = name
|
|
36
|
-
@description = description
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def call(input:, context:)
|
|
40
|
-
raise NotImplementedError, "Subclass must implement #call"
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Example Tools
|
|
45
|
-
class SearchTool < Tool
|
|
46
|
-
def initialize
|
|
47
|
-
super(name: "search", description: "Search for information")
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def call(input:, context: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
51
|
-
query = input["query"] || "default"
|
|
52
|
-
# In real code, this would call your search API
|
|
53
|
-
{
|
|
54
|
-
query: query,
|
|
55
|
-
results: [
|
|
56
|
-
"Result 1 for: #{query}",
|
|
57
|
-
"Result 2 for: #{query}",
|
|
58
|
-
"Result 3 for: #{query}"
|
|
59
|
-
],
|
|
60
|
-
count: 3
|
|
61
|
-
}
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
class CalculateTool < Tool
|
|
66
|
-
def initialize
|
|
67
|
-
super(name: "calculate", description: "Perform calculations")
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def call(input:, context: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
71
|
-
operation = input["operation"] || "add"
|
|
72
|
-
a = input["a"] || 0
|
|
73
|
-
b = input["b"] || 0
|
|
74
|
-
|
|
75
|
-
result = case operation
|
|
76
|
-
when "add" then a + b
|
|
77
|
-
when "subtract" then a - b
|
|
78
|
-
when "multiply" then a * b
|
|
79
|
-
when "divide" then b.zero? ? "Error: Division by zero" : a / b
|
|
80
|
-
else "Unknown operation: #{operation}"
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
{
|
|
84
|
-
operation: operation,
|
|
85
|
-
operands: { a: a, b: b },
|
|
86
|
-
result: result
|
|
87
|
-
}
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
class StoreTool < Tool
|
|
92
|
-
def initialize
|
|
93
|
-
super(name: "store", description: "Store data")
|
|
94
|
-
@storage = {}
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def call(input:, context: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
98
|
-
key = input["key"] || "default"
|
|
99
|
-
value = input["value"] || {}
|
|
100
|
-
@storage[key] = value
|
|
101
|
-
|
|
102
|
-
{
|
|
103
|
-
key: key,
|
|
104
|
-
stored: true,
|
|
105
|
-
message: "Data stored successfully"
|
|
106
|
-
}
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# Tool Router - matches README example exactly
|
|
111
|
-
class ToolRouter
|
|
112
|
-
def initialize(llm:, registry:)
|
|
113
|
-
@llm = llm # Ollama::Client instance
|
|
114
|
-
@registry = registry
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def step(prompt:, context: {})
|
|
118
|
-
# LLM outputs intent (not execution)
|
|
119
|
-
decision = @llm.generate(
|
|
120
|
-
prompt: prompt,
|
|
121
|
-
schema: {
|
|
122
|
-
"type" => "object",
|
|
123
|
-
"required" => ["action"],
|
|
124
|
-
"properties" => {
|
|
125
|
-
"action" => { "type" => "string" },
|
|
126
|
-
"input" => {
|
|
127
|
-
"type" => "object",
|
|
128
|
-
"additionalProperties" => true
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
return { done: true } if decision["action"] == "finish"
|
|
135
|
-
|
|
136
|
-
# Agent executes tool (deterministic)
|
|
137
|
-
tool = @registry.fetch(decision["action"])
|
|
138
|
-
output = tool.call(input: decision["input"] || {}, context: context)
|
|
139
|
-
|
|
140
|
-
{ tool: tool.name, output: output }
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# Example usage
|
|
145
|
-
if __FILE__ == $PROGRAM_NAME
|
|
146
|
-
puts "=" * 60
|
|
147
|
-
puts "Tool Calling Pattern Example"
|
|
148
|
-
puts "=" * 60
|
|
149
|
-
puts
|
|
150
|
-
|
|
151
|
-
# Setup
|
|
152
|
-
client = Ollama::Client.new
|
|
153
|
-
registry = ToolRegistry.new
|
|
154
|
-
|
|
155
|
-
# Register tools
|
|
156
|
-
registry.register("search", SearchTool.new)
|
|
157
|
-
registry.register("calculate", CalculateTool.new)
|
|
158
|
-
registry.register("store", StoreTool.new)
|
|
159
|
-
|
|
160
|
-
# Create router
|
|
161
|
-
router = ToolRouter.new(llm: client, registry: registry)
|
|
162
|
-
|
|
163
|
-
puts "Available tools: #{registry.available.join(', ')}"
|
|
164
|
-
puts
|
|
165
|
-
|
|
166
|
-
# Example 1: Search
|
|
167
|
-
puts "─" * 60
|
|
168
|
-
puts "Example 1: Search Tool"
|
|
169
|
-
puts "─" * 60
|
|
170
|
-
begin
|
|
171
|
-
result = router.step(
|
|
172
|
-
prompt: "User wants to search for 'Ruby programming'. Use the search tool with query 'Ruby programming'.",
|
|
173
|
-
context: {}
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
if result[:done]
|
|
177
|
-
puts "✅ Workflow complete"
|
|
178
|
-
else
|
|
179
|
-
puts "Tool: #{result[:tool]}"
|
|
180
|
-
puts "Output: #{JSON.pretty_generate(result[:output])}"
|
|
181
|
-
end
|
|
182
|
-
rescue Ollama::Error => e
|
|
183
|
-
puts "❌ Error: #{e.message}"
|
|
184
|
-
rescue StandardError => e
|
|
185
|
-
puts "❌ Error: #{e.class}: #{e.message}"
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
puts
|
|
189
|
-
|
|
190
|
-
# Example 2: Calculate
|
|
191
|
-
puts "─" * 60
|
|
192
|
-
puts "Example 2: Calculate Tool"
|
|
193
|
-
puts "─" * 60
|
|
194
|
-
begin
|
|
195
|
-
result = router.step(
|
|
196
|
-
prompt: "User wants to calculate 15 * 7. Use the calculate tool with operation 'multiply', a=15, b=7.",
|
|
197
|
-
context: {}
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
if result[:done]
|
|
201
|
-
puts "✅ Workflow complete"
|
|
202
|
-
else
|
|
203
|
-
puts "Tool: #{result[:tool]}"
|
|
204
|
-
puts "Output: #{JSON.pretty_generate(result[:output])}"
|
|
205
|
-
end
|
|
206
|
-
rescue Ollama::Error => e
|
|
207
|
-
puts "❌ Error: #{e.message}"
|
|
208
|
-
rescue StandardError => e
|
|
209
|
-
puts "❌ Error: #{e.class}: #{e.message}"
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
puts
|
|
213
|
-
|
|
214
|
-
# Example 3: Store
|
|
215
|
-
puts "─" * 60
|
|
216
|
-
puts "Example 3: Store Tool"
|
|
217
|
-
puts "─" * 60
|
|
218
|
-
begin
|
|
219
|
-
result = router.step(
|
|
220
|
-
prompt: "User wants to store data with key 'user_preferences' and value {'theme': 'dark'}. Use the store tool.",
|
|
221
|
-
context: {}
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
if result[:done]
|
|
225
|
-
puts "✅ Workflow complete"
|
|
226
|
-
else
|
|
227
|
-
puts "Tool: #{result[:tool]}"
|
|
228
|
-
puts "Output: #{JSON.pretty_generate(result[:output])}"
|
|
229
|
-
end
|
|
230
|
-
rescue Ollama::Error => e
|
|
231
|
-
puts "❌ Error: #{e.message}"
|
|
232
|
-
rescue StandardError => e
|
|
233
|
-
puts "❌ Error: #{e.class}: #{e.message}"
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
puts
|
|
237
|
-
|
|
238
|
-
# Example 4: Finish
|
|
239
|
-
puts "─" * 60
|
|
240
|
-
puts "Example 4: Finish Action"
|
|
241
|
-
puts "─" * 60
|
|
242
|
-
begin
|
|
243
|
-
result = router.step(
|
|
244
|
-
prompt: "The task is complete. Use action 'finish'.",
|
|
245
|
-
context: {}
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
if result[:done]
|
|
249
|
-
puts "✅ Workflow complete"
|
|
250
|
-
else
|
|
251
|
-
puts "Tool: #{result[:tool]}"
|
|
252
|
-
puts "Output: #{JSON.pretty_generate(result[:output])}"
|
|
253
|
-
end
|
|
254
|
-
rescue Ollama::Error => e
|
|
255
|
-
puts "❌ Error: #{e.message}"
|
|
256
|
-
rescue StandardError => e
|
|
257
|
-
puts "❌ Error: #{e.class}: #{e.message}"
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
puts
|
|
261
|
-
puts "=" * 60
|
|
262
|
-
puts "Pattern demonstrated:"
|
|
263
|
-
puts " 1. LLM outputs structured intent (via ollama-client)"
|
|
264
|
-
puts " 2. Agent validates and routes to tool"
|
|
265
|
-
puts " 3. Tool executes deterministically (pure Ruby)"
|
|
266
|
-
puts " 4. Results returned to agent"
|
|
267
|
-
puts "=" * 60
|
|
268
|
-
end
|
|
269
|
-
|
data/exe/dhan_console
DELETED