ollama-client 0.2.4 → 0.2.6

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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -1
  3. data/README.md +560 -106
  4. data/docs/EXAMPLE_REORGANIZATION.md +412 -0
  5. data/docs/GETTING_STARTED.md +361 -0
  6. data/docs/INTEGRATION_TESTING.md +170 -0
  7. data/docs/NEXT_STEPS_SUMMARY.md +114 -0
  8. data/docs/PERSONAS.md +383 -0
  9. data/docs/QUICK_START.md +195 -0
  10. data/docs/README.md +2 -3
  11. data/docs/RELEASE_GUIDE.md +376 -0
  12. data/docs/TESTING.md +392 -170
  13. data/docs/TEST_CHECKLIST.md +450 -0
  14. data/docs/ruby_guide.md +6232 -0
  15. data/examples/README.md +51 -66
  16. data/examples/basic_chat.rb +33 -0
  17. data/examples/basic_generate.rb +29 -0
  18. data/examples/tool_calling_parsing.rb +59 -0
  19. data/exe/ollama-client +128 -1
  20. data/lib/ollama/agent/planner.rb +7 -2
  21. data/lib/ollama/chat_session.rb +101 -0
  22. data/lib/ollama/client.rb +43 -21
  23. data/lib/ollama/config.rb +4 -1
  24. data/lib/ollama/document_loader.rb +163 -0
  25. data/lib/ollama/embeddings.rb +42 -13
  26. data/lib/ollama/errors.rb +1 -0
  27. data/lib/ollama/personas.rb +287 -0
  28. data/lib/ollama/version.rb +1 -1
  29. data/lib/ollama_client.rb +8 -0
  30. metadata +31 -53
  31. data/docs/GEM_RELEASE_GUIDE.md +0 -794
  32. data/docs/GET_RUBYGEMS_SECRET.md +0 -151
  33. data/docs/QUICK_OTP_SETUP.md +0 -80
  34. data/docs/QUICK_RELEASE.md +0 -106
  35. data/docs/RUBYGEMS_OTP_SETUP.md +0 -199
  36. data/examples/advanced_complex_schemas.rb +0 -366
  37. data/examples/advanced_edge_cases.rb +0 -241
  38. data/examples/advanced_error_handling.rb +0 -200
  39. data/examples/advanced_multi_step_agent.rb +0 -341
  40. data/examples/advanced_performance_testing.rb +0 -186
  41. data/examples/chat_console.rb +0 -143
  42. data/examples/complete_workflow.rb +0 -245
  43. data/examples/dhan_console.rb +0 -843
  44. data/examples/dhanhq/README.md +0 -236
  45. data/examples/dhanhq/agents/base_agent.rb +0 -74
  46. data/examples/dhanhq/agents/data_agent.rb +0 -66
  47. data/examples/dhanhq/agents/orchestrator_agent.rb +0 -120
  48. data/examples/dhanhq/agents/technical_analysis_agent.rb +0 -252
  49. data/examples/dhanhq/agents/trading_agent.rb +0 -81
  50. data/examples/dhanhq/analysis/market_structure.rb +0 -138
  51. data/examples/dhanhq/analysis/pattern_recognizer.rb +0 -192
  52. data/examples/dhanhq/analysis/trend_analyzer.rb +0 -88
  53. data/examples/dhanhq/builders/market_context_builder.rb +0 -67
  54. data/examples/dhanhq/dhanhq_agent.rb +0 -829
  55. data/examples/dhanhq/indicators/technical_indicators.rb +0 -158
  56. data/examples/dhanhq/scanners/intraday_options_scanner.rb +0 -492
  57. data/examples/dhanhq/scanners/swing_scanner.rb +0 -247
  58. data/examples/dhanhq/schemas/agent_schemas.rb +0 -61
  59. data/examples/dhanhq/services/base_service.rb +0 -46
  60. data/examples/dhanhq/services/data_service.rb +0 -118
  61. data/examples/dhanhq/services/trading_service.rb +0 -59
  62. data/examples/dhanhq/technical_analysis_agentic_runner.rb +0 -411
  63. data/examples/dhanhq/technical_analysis_runner.rb +0 -420
  64. data/examples/dhanhq/test_tool_calling.rb +0 -538
  65. data/examples/dhanhq/test_tool_calling_verbose.rb +0 -251
  66. data/examples/dhanhq/utils/instrument_helper.rb +0 -32
  67. data/examples/dhanhq/utils/parameter_cleaner.rb +0 -28
  68. data/examples/dhanhq/utils/parameter_normalizer.rb +0 -45
  69. data/examples/dhanhq/utils/rate_limiter.rb +0 -23
  70. data/examples/dhanhq/utils/trading_parameter_normalizer.rb +0 -72
  71. data/examples/dhanhq_agent.rb +0 -964
  72. data/examples/dhanhq_tools.rb +0 -1663
  73. data/examples/multi_step_agent_with_external_data.rb +0 -368
  74. data/examples/structured_outputs_chat.rb +0 -72
  75. data/examples/structured_tools.rb +0 -89
  76. data/examples/test_dhanhq_tool_calling.rb +0 -375
  77. data/examples/test_tool_calling.rb +0 -160
  78. data/examples/tool_calling_direct.rb +0 -124
  79. data/examples/tool_calling_pattern.rb +0 -269
  80. data/exe/dhan_console +0 -4
@@ -1,366 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Advanced Example: Complex Nested Schemas and Validation
5
- # Demonstrates: Deep nesting, arrays of objects, conditional validation, real-world data structures
6
-
7
- require "json"
8
- require_relative "../lib/ollama_client"
9
-
10
- # Example 1: Financial Analysis Schema
11
- class FinancialAnalyzer
12
- def initialize(client:)
13
- @client = client
14
- @schema = {
15
- "type" => "object",
16
- "required" => ["analysis_date", "summary", "metrics", "recommendations"],
17
- "properties" => {
18
- "analysis_date" => {
19
- "type" => "string",
20
- "format" => "date-time"
21
- },
22
- "summary" => {
23
- "type" => "string",
24
- "minLength" => 50,
25
- "maxLength" => 500
26
- },
27
- "metrics" => {
28
- "type" => "object",
29
- "required" => ["revenue", "profit_margin", "growth_rate"],
30
- "properties" => {
31
- "revenue" => {
32
- "type" => "number",
33
- "minimum" => 0
34
- },
35
- "profit_margin" => {
36
- "type" => "number",
37
- "minimum" => 0,
38
- "maximum" => 100,
39
- "description" => "Profit margin as percentage (0 to 100)"
40
- },
41
- "growth_rate" => {
42
- "type" => "number"
43
- },
44
- "trend" => {
45
- "type" => "string",
46
- "enum" => ["increasing", "stable", "decreasing"]
47
- }
48
- }
49
- },
50
- "recommendations" => {
51
- "type" => "array",
52
- "minItems" => 1,
53
- "maxItems" => 10,
54
- "items" => {
55
- "type" => "object",
56
- "required" => ["action", "priority", "rationale"],
57
- "properties" => {
58
- "action" => {
59
- "type" => "string"
60
- },
61
- "priority" => {
62
- "type" => "string",
63
- "enum" => ["low", "medium", "high", "critical"]
64
- },
65
- "rationale" => {
66
- "type" => "string"
67
- },
68
- "estimated_impact" => {
69
- "type" => "object",
70
- "properties" => {
71
- "revenue_impact" => {
72
- "type" => "number"
73
- },
74
- "risk_level" => {
75
- "type" => "string",
76
- "enum" => ["low", "medium", "high"]
77
- }
78
- }
79
- }
80
- }
81
- }
82
- },
83
- "risk_factors" => {
84
- "type" => "array",
85
- "items" => {
86
- "type" => "object",
87
- "required" => ["factor", "severity"],
88
- "properties" => {
89
- "factor" => { "type" => "string" },
90
- "severity" => {
91
- "type" => "string",
92
- "enum" => ["low", "medium", "high", "critical"]
93
- },
94
- "mitigation" => { "type" => "string" }
95
- }
96
- }
97
- }
98
- }
99
- }
100
- end
101
-
102
- def analyze(data:)
103
- prompt = <<~PROMPT
104
- Analyze this financial data: #{data}
105
-
106
- Return JSON with: summary (50-500 chars), metrics (revenue, profit_margin, growth_rate, trend),
107
- recommendations array (action, priority, rationale), and optional risk_factors array.
108
- PROMPT
109
-
110
- @client.generate(prompt: prompt, schema: @schema)
111
- end
112
- end
113
-
114
- # Example 2: Code Review Schema
115
- class CodeReviewer
116
- def initialize(client:)
117
- @client = client
118
- @schema = {
119
- "type" => "object",
120
- "required" => ["overall_score", "issues", "suggestions"],
121
- "properties" => {
122
- "overall_score" => {
123
- "type" => "integer",
124
- "minimum" => 0,
125
- "maximum" => 100,
126
- "description" => "Overall quality score (0 to 100)"
127
- },
128
- "issues" => {
129
- "type" => "array",
130
- "items" => {
131
- "type" => "object",
132
- "required" => ["type", "severity", "location", "description"],
133
- "properties" => {
134
- "type" => {
135
- "type" => "string",
136
- "enum" => ["bug", "security", "performance", "style", "maintainability"]
137
- },
138
- "severity" => {
139
- "type" => "string",
140
- "enum" => ["low", "medium", "high", "critical"]
141
- },
142
- "location" => {
143
- "type" => "object",
144
- "properties" => {
145
- "file" => { "type" => "string" },
146
- "line" => { "type" => "integer" },
147
- "column" => { "type" => "integer" }
148
- }
149
- },
150
- "description" => { "type" => "string" },
151
- "suggestion" => { "type" => "string" }
152
- }
153
- }
154
- },
155
- "suggestions" => {
156
- "type" => "array",
157
- "items" => {
158
- "type" => "object",
159
- "required" => ["category", "description"],
160
- "properties" => {
161
- "category" => {
162
- "type" => "string",
163
- "enum" => ["refactoring", "optimization", "documentation", "testing"]
164
- },
165
- "description" => { "type" => "string" },
166
- "priority" => {
167
- "type" => "string",
168
- "enum" => ["low", "medium", "high"]
169
- }
170
- }
171
- }
172
- },
173
- "strengths" => {
174
- "type" => "array",
175
- "items" => { "type" => "string" }
176
- },
177
- "estimated_effort" => {
178
- "type" => "object",
179
- "properties" => {
180
- "hours" => { "type" => "number", "minimum" => 0 },
181
- "complexity" => {
182
- "type" => "string",
183
- "enum" => ["simple", "moderate", "complex"]
184
- }
185
- }
186
- }
187
- }
188
- }
189
- end
190
-
191
- def review(code:)
192
- prompt = <<~PROMPT
193
- Review this Ruby code: #{code}
194
-
195
- Return JSON with: overall_score (0-100), issues array (type, severity, location, description),
196
- suggestions array (category, description, priority), optional strengths array, optional estimated_effort.
197
- PROMPT
198
-
199
- @client.generate(prompt: prompt, schema: @schema)
200
- end
201
- end
202
-
203
- # Example 3: Research Paper Analysis Schema
204
- class ResearchAnalyzer
205
- def initialize(client:)
206
- @client = client
207
- @schema = {
208
- "type" => "object",
209
- "required" => ["title", "key_findings", "methodology", "citations"],
210
- "properties" => {
211
- "title" => { "type" => "string" },
212
- "key_findings" => {
213
- "type" => "array",
214
- "minItems" => 3,
215
- "maxItems" => 10,
216
- "items" => {
217
- "type" => "object",
218
- "required" => ["finding", "significance"],
219
- "properties" => {
220
- "finding" => { "type" => "string" },
221
- "significance" => {
222
- "type" => "string",
223
- "enum" => ["low", "medium", "high", "breakthrough"]
224
- },
225
- "evidence" => { "type" => "string" }
226
- }
227
- }
228
- },
229
- "methodology" => {
230
- "type" => "object",
231
- "required" => ["type", "description"],
232
- "properties" => {
233
- "type" => {
234
- "type" => "string",
235
- "enum" => ["experimental", "observational", "theoretical", "computational", "mixed"]
236
- },
237
- "description" => { "type" => "string" },
238
- "limitations" => {
239
- "type" => "array",
240
- "items" => { "type" => "string" }
241
- }
242
- }
243
- },
244
- "citations" => {
245
- "type" => "array",
246
- "items" => {
247
- "type" => "object",
248
- "required" => ["author", "title", "year"],
249
- "properties" => {
250
- "author" => { "type" => "string" },
251
- "title" => { "type" => "string" },
252
- "year" => {
253
- "type" => "integer",
254
- "minimum" => 1900,
255
- "maximum" => 2100
256
- },
257
- "relevance" => {
258
- "type" => "string",
259
- "enum" => ["low", "medium", "high"]
260
- }
261
- }
262
- }
263
- },
264
- "reproducibility_score" => {
265
- "type" => "number",
266
- "minimum" => 0,
267
- "maximum" => 1,
268
- "description" => "Reproducibility score (0.0 to 1.0, where 1.0 means fully reproducible)"
269
- }
270
- }
271
- }
272
- end
273
-
274
- def analyze(paper_text:)
275
- prompt = <<~PROMPT
276
- Analyze this research paper: #{paper_text}
277
-
278
- Return JSON with: title, key_findings array (3-10 items: finding, significance, evidence),
279
- methodology (type, description, limitations), citations array (author, title, year, relevance),
280
- optional reproducibility_score (0-1).
281
- PROMPT
282
-
283
- @client.generate(prompt: prompt, schema: @schema)
284
- end
285
- end
286
-
287
- # Run examples
288
- if __FILE__ == $PROGRAM_NAME
289
- # Use longer timeout for complex schemas
290
- config = Ollama::Config.new
291
- config.timeout = 60 # 60 seconds for complex operations
292
- client = Ollama::Client.new(config: config)
293
-
294
- puts "=" * 60
295
- puts "Example 1: Financial Analysis"
296
- puts "=" * 60
297
- financial_data = <<~DATA
298
- Q4 2024 Financial Report:
299
- - Revenue: $2.5M (up 15% from Q3)
300
- - Operating expenses: $1.8M
301
- - Net profit: $700K
302
- - Customer base: 5,000 (up 20%)
303
- - Churn rate: 2% (down from 3%)
304
- DATA
305
-
306
- analyzer = FinancialAnalyzer.new(client: client)
307
- begin
308
- puts "⏳ Analyzing financial data (this may take 30-60 seconds)..."
309
- result = analyzer.analyze(data: financial_data)
310
- puts JSON.pretty_generate(result)
311
- rescue Ollama::TimeoutError => e
312
- puts "⏱️ Timeout: #{e.message}"
313
- puts " Try increasing timeout or using a faster model"
314
- rescue Ollama::Error => e
315
- puts "❌ Error: #{e.message}"
316
- end
317
-
318
- puts "\n" + "=" * 60
319
- puts "Example 2: Code Review"
320
- puts "=" * 60
321
- code_sample = <<~RUBY
322
- def calculate_total(items)
323
- total = 0
324
- items.each do |item|
325
- total += item.price
326
- end
327
- total
328
- end
329
- RUBY
330
-
331
- reviewer = CodeReviewer.new(client: client)
332
- begin
333
- puts "⏳ Reviewing code (this may take 30-60 seconds)..."
334
- result = reviewer.review(code: code_sample)
335
- puts JSON.pretty_generate(result)
336
- rescue Ollama::TimeoutError => e
337
- puts "⏱️ Timeout: #{e.message}"
338
- puts " Try increasing timeout or using a faster model"
339
- rescue Ollama::Error => e
340
- puts "❌ Error: #{e.message}"
341
- end
342
-
343
- puts "\n" + "=" * 60
344
- puts "Example 3: Research Paper Analysis"
345
- puts "=" * 60
346
- paper_abstract = <<~TEXT
347
- This study investigates the impact of machine learning on financial forecasting.
348
- We analyzed 10 years of market data using neural networks and found a 23% improvement
349
- in prediction accuracy. The methodology involved training on historical data and
350
- validating on out-of-sample periods. Key limitations include data quality and
351
- model interpretability challenges.
352
- TEXT
353
-
354
- research_analyzer = ResearchAnalyzer.new(client: client)
355
- begin
356
- puts "⏳ Analyzing research paper (this may take 30-60 seconds)..."
357
- result = research_analyzer.analyze(paper_text: paper_abstract)
358
- puts JSON.pretty_generate(result)
359
- rescue Ollama::TimeoutError => e
360
- puts "⏱️ Timeout: #{e.message}"
361
- puts " Try increasing timeout or using a faster model"
362
- rescue Ollama::Error => e
363
- puts "❌ Error: #{e.message}"
364
- end
365
- end
366
-
@@ -1,241 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Advanced Example: Edge Cases and Boundary Testing
5
- # Demonstrates: Empty responses, malformed schemas, extreme values, special characters
6
-
7
- require "json"
8
- require_relative "../lib/ollama_client"
9
-
10
- class EdgeCaseTester
11
- def initialize(client:)
12
- @client = client
13
- end
14
-
15
- def test_empty_prompt
16
- puts "Test 1: Empty prompt"
17
- schema = {
18
- "type" => "object",
19
- "properties" => {
20
- "response" => { "type" => "string" }
21
- }
22
- }
23
-
24
- begin
25
- result = @client.generate(prompt: "", schema: schema)
26
- puts " ✅ Handled empty prompt: #{result.inspect[0..100]}"
27
- rescue Ollama::Error => e
28
- puts " ❌ Error: #{e.class} - #{e.message}"
29
- end
30
- puts
31
- end
32
-
33
- def test_very_long_prompt
34
- puts "Test 2: Very long prompt (10KB+)"
35
- long_prompt = "Repeat this sentence. " * 500
36
- schema = {
37
- "type" => "object",
38
- "properties" => {
39
- "summary" => { "type" => "string" }
40
- }
41
- }
42
-
43
- begin
44
- @client.generate(prompt: long_prompt, schema: schema)
45
- puts " ✅ Handled long prompt (#{long_prompt.length} chars)"
46
- rescue Ollama::Error => e
47
- puts " ❌ Error: #{e.class} - #{e.message}"
48
- end
49
- puts
50
- end
51
-
52
- def test_special_characters
53
- puts "Test 3: Special characters in prompt"
54
- special_prompt = "Analyze: !@#$%^&*()_+-=[]{}|;':\",./<>?`~"
55
- schema = {
56
- "type" => "object",
57
- "properties" => {
58
- "analysis" => { "type" => "string" }
59
- }
60
- }
61
-
62
- begin
63
- @client.generate(prompt: special_prompt, schema: schema)
64
- puts " ✅ Handled special characters"
65
- rescue Ollama::Error => e
66
- puts " ❌ Error: #{e.class} - #{e.message}"
67
- end
68
- puts
69
- end
70
-
71
- def test_unicode_characters
72
- puts "Test 4: Unicode characters"
73
- unicode_prompt = "Analyze: 你好世界 🌍 🚀 émojis and spéciál chäracters"
74
- schema = {
75
- "type" => "object",
76
- "properties" => {
77
- "analysis" => { "type" => "string" }
78
- }
79
- }
80
-
81
- begin
82
- @client.generate(prompt: unicode_prompt, schema: schema)
83
- puts " ✅ Handled unicode characters"
84
- rescue Ollama::Error => e
85
- puts " ❌ Error: #{e.class} - #{e.message}"
86
- end
87
- puts
88
- end
89
-
90
- def test_minimal_schema
91
- puts "Test 5: Minimal schema (no required fields)"
92
- schema = {
93
- "type" => "object",
94
- "additionalProperties" => true
95
- }
96
-
97
- begin
98
- result = @client.generate(
99
- prompt: "Return any JSON object",
100
- schema: schema
101
- )
102
- puts " ✅ Handled minimal schema: #{result.keys.join(', ')}"
103
- rescue Ollama::Error => e
104
- puts " ❌ Error: #{e.class} - #{e.message}"
105
- end
106
- puts
107
- end
108
-
109
- def test_strict_schema
110
- puts "Test 6: Strict schema with many constraints"
111
- strict_schema = {
112
- "type" => "object",
113
- "required" => ["id", "name", "values"],
114
- "properties" => {
115
- "id" => {
116
- "type" => "integer",
117
- "minimum" => 1,
118
- "maximum" => 1000
119
- },
120
- "name" => {
121
- "type" => "string",
122
- "minLength" => 3,
123
- "maxLength" => 20,
124
- "pattern" => "^[A-Za-z0-9_]+$"
125
- },
126
- "values" => {
127
- "type" => "array",
128
- "minItems" => 2,
129
- "maxItems" => 5,
130
- "items" => {
131
- "type" => "number",
132
- "minimum" => 0,
133
- "maximum" => 100
134
- }
135
- }
136
- }
137
- }
138
-
139
- begin
140
- prompt_text = "Generate a valid object with id (1-1000), " \
141
- "name (3-20 alphanumeric chars), " \
142
- "and values (2-5 numbers 0-100)"
143
- result = @client.generate(
144
- prompt: prompt_text,
145
- schema: strict_schema
146
- )
147
- puts " ✅ Handled strict schema"
148
- puts " ID: #{result['id']}, Name: #{result['name']}, Values: #{result['values']}"
149
- rescue Ollama::Error => e
150
- puts " ❌ Error: #{e.class} - #{e.message}"
151
- end
152
- puts
153
- end
154
-
155
- def test_nested_arrays
156
- puts "Test 7: Deeply nested arrays"
157
- nested_schema = {
158
- "type" => "object",
159
- "properties" => {
160
- "matrix" => {
161
- "type" => "array",
162
- "items" => {
163
- "type" => "array",
164
- "items" => {
165
- "type" => "array",
166
- "items" => { "type" => "integer" }
167
- }
168
- }
169
- }
170
- }
171
- }
172
-
173
- begin
174
- @client.generate(
175
- prompt: "Generate a 2x2x2 matrix of integers",
176
- schema: nested_schema
177
- )
178
- puts " ✅ Handled nested arrays"
179
- rescue Ollama::Error => e
180
- puts " ❌ Error: #{e.class} - #{e.message}"
181
- end
182
- puts
183
- end
184
-
185
- def test_enum_constraints
186
- puts "Test 8: Strict enum constraints"
187
- enum_schema = {
188
- "type" => "object",
189
- "required" => ["status", "priority"],
190
- "properties" => {
191
- "status" => {
192
- "type" => "string",
193
- "enum" => ["pending", "in_progress", "completed", "failed"]
194
- },
195
- "priority" => {
196
- "type" => "string",
197
- "enum" => ["low", "medium", "high", "urgent"]
198
- }
199
- }
200
- }
201
-
202
- begin
203
- result = @client.generate(
204
- prompt: "Choose a status and priority from the allowed values",
205
- schema: enum_schema
206
- )
207
- puts " ✅ Handled enum constraints: status=#{result['status']}, priority=#{result['priority']}"
208
- rescue Ollama::Error => e
209
- puts " ❌ Error: #{e.class} - #{e.message}"
210
- end
211
- puts
212
- end
213
-
214
- def run_all_tests
215
- puts "=" * 60
216
- puts "Edge Case Testing Suite"
217
- puts "=" * 60
218
- puts
219
-
220
- test_empty_prompt
221
- test_very_long_prompt
222
- test_special_characters
223
- test_unicode_characters
224
- test_minimal_schema
225
- test_strict_schema
226
- test_nested_arrays
227
- test_enum_constraints
228
-
229
- puts "=" * 60
230
- puts "Edge case testing complete!"
231
- puts "=" * 60
232
- end
233
- end
234
-
235
- # Run tests
236
- if __FILE__ == $PROGRAM_NAME
237
- client = Ollama::Client.new
238
- tester = EdgeCaseTester.new(client: client)
239
- tester.run_all_tests
240
- end
241
-