ruby_llm-providers-groq 2.0.0.pre.1
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 +7 -0
- data/.flayignore +1 -0
- data/.github/workflows/ci.yml +30 -0
- data/.github/workflows/gitleaks.yml +22 -0
- data/.github/workflows/release.yml +36 -0
- data/.overcommit.yml +31 -0
- data/.rspec +2 -0
- data/.rubocop.yml +29 -0
- data/Archspec.rb +14 -0
- data/LICENSE +21 -0
- data/README.md +57 -0
- data/lib/ruby_llm/providers/groq.rb +70 -0
- data/models.json +218 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_openai_gpt_oss_120b_can_handle_a_multi_turn_conversation.yml +153 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_openai_gpt_oss_120b_can_have_a_basic_conversation.yml +75 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_openai_gpt_oss_120b_can_use_tools.yml +153 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_openai_gpt_oss_120b_returns_structured_output.yml +80 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_openai_gpt_oss_120b_returns_the_raw_response.yml +79 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_openai_gpt_oss_120b_supports_streaming_responses.yml +252 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_can_handle_a_multi_turn_conversation.yml +160 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_can_have_a_basic_conversation.yml +77 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_can_use_tools.yml +152 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_returns_structured_output.yml +77 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_returns_the_raw_response.yml +77 -0
- data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_supports_streaming_responses.yml +126 -0
- data/spec/ruby_llm/chat_schema_spec.rb +30 -0
- data/spec/ruby_llm/chat_spec.rb +35 -0
- data/spec/ruby_llm/chat_streaming_spec.rb +22 -0
- data/spec/ruby_llm/chat_tools_spec.rb +31 -0
- data/spec/ruby_llm/embedding_spec.rb +49 -0
- data/spec/ruby_llm/image_spec.rb +23 -0
- data/spec/ruby_llm/models_spec.rb +11 -0
- data/spec/ruby_llm/moderation_spec.rb +22 -0
- data/spec/ruby_llm/providers/groq_spec.rb +32 -0
- data/spec/ruby_llm/rerank_spec.rb +23 -0
- data/spec/ruby_llm/speech_spec.rb +25 -0
- data/spec/ruby_llm/video_spec.rb +27 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/models.rb +22 -0
- data/spec/support/rubyllm_configuration.rb +14 -0
- data/spec/support/vcr_configuration.rb +16 -0
- metadata +105 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://api.groq.com/openai/v1/responses
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: '{"model":"qwen/qwen3.8-27b","input":[{"role":"user","content":"What''s
|
|
9
|
+
the weather in Berlin? Use 52.5200, 13.4050."}],"stream":false,"store":false,"tools":[{"type":"function","name":"weather","description":"Gets
|
|
10
|
+
current weather for a location","parameters":{"type":"object","properties":{"latitude":{"type":"string","description":"Latitude"},"longitude":{"type":"string","description":"Longitude"}},"required":["latitude","longitude"],"additionalProperties":false,"strict":true},"strict":false}]}'
|
|
11
|
+
headers:
|
|
12
|
+
User-Agent:
|
|
13
|
+
- Faraday v2.14.4
|
|
14
|
+
Authorization:
|
|
15
|
+
- Bearer <AUTH_TOKEN>
|
|
16
|
+
Content-Type:
|
|
17
|
+
- application/json
|
|
18
|
+
Accept-Encoding:
|
|
19
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
20
|
+
Accept:
|
|
21
|
+
- "*/*"
|
|
22
|
+
response:
|
|
23
|
+
status:
|
|
24
|
+
code: 200
|
|
25
|
+
message: OK
|
|
26
|
+
headers:
|
|
27
|
+
Date:
|
|
28
|
+
- Wed, 07 Oct 2026 16:48:59 GMT
|
|
29
|
+
Content-Type:
|
|
30
|
+
- application/json
|
|
31
|
+
Transfer-Encoding:
|
|
32
|
+
- chunked
|
|
33
|
+
Connection:
|
|
34
|
+
- keep-alive
|
|
35
|
+
Cache-Control:
|
|
36
|
+
- private, max-age=0, no-store, no-cache, must-revalidate
|
|
37
|
+
Server:
|
|
38
|
+
- cloudflare
|
|
39
|
+
Vary:
|
|
40
|
+
- Origin
|
|
41
|
+
X-Groq-Region:
|
|
42
|
+
- dls
|
|
43
|
+
X-Ratelimit-Limit-Requests:
|
|
44
|
+
- '1000'
|
|
45
|
+
X-Ratelimit-Limit-Tokens:
|
|
46
|
+
- '8000'
|
|
47
|
+
X-Ratelimit-Remaining-Requests:
|
|
48
|
+
- '994'
|
|
49
|
+
X-Ratelimit-Remaining-Tokens:
|
|
50
|
+
- '7281'
|
|
51
|
+
X-Ratelimit-Reset-Requests:
|
|
52
|
+
- 8m38.4s
|
|
53
|
+
X-Ratelimit-Reset-Tokens:
|
|
54
|
+
- 23.34s
|
|
55
|
+
X-Request-Id:
|
|
56
|
+
- req_01m4bm9b16ekpr23jjhgq99gdc
|
|
57
|
+
Via:
|
|
58
|
+
- 1.1 google
|
|
59
|
+
Alt-Svc:
|
|
60
|
+
- h3=":443"; ma=86400
|
|
61
|
+
Cf-Cache-Status:
|
|
62
|
+
- DYNAMIC
|
|
63
|
+
Set-Cookie:
|
|
64
|
+
- __cf_bm=6n0BSCZAb4sticznTXikANIWQ4hRD0KAdXlgDEiQg1s-1791391738.8197184-1.0.1.1-5D88MLf22WDRiQhFRiEcyUBCinTMXeWMYkWGMy50.3eUrzi._wMKyeY3A7dYYzOmKtSIMqZPoXBG7d29JP9mB9CnwJtJdaHHSfS.4UK7khx5Hw_t5.J1DSHEBagnmj.x;
|
|
65
|
+
HttpOnly; SameSite=None; Secure; Path=/; Domain=groq.com; Expires=Wed, 07
|
|
66
|
+
Oct 2026 17:18:59 GMT
|
|
67
|
+
Strict-Transport-Security:
|
|
68
|
+
- max-age=15552000
|
|
69
|
+
Cf-Ray:
|
|
70
|
+
- a46e657f9c7102ba-HEL
|
|
71
|
+
body:
|
|
72
|
+
encoding: ASCII-8BIT
|
|
73
|
+
string: '{"id":"resp_01m4bm9b82et4rkabjx8zjy7dg","object":"response","status":"completed","created_at":1791391739,"output":[{"type":"reasoning","id":"resp_01m4bm9b82et58g8q94rw0ejcc","status":"completed","summary":[]},{"type":"function_call","id":"need8cqcy","status":"completed","call_id":"need8cqcy","name":"weather","arguments":"{\"latitude\":\"52.5200\",\"longitude\":\"13.4050\"}"}],"previous_response_id":null,"model":"qwen/qwen3.8-27b","reasoning":{"effort":"none"},"max_output_tokens":null,"text":{"format":{"type":"text"}},"tools":[{"type":"function","name":"weather","description":"Gets
|
|
74
|
+
current weather for a location","parameters":{"additionalProperties":false,"properties":{"latitude":{"description":"Latitude","type":"string"},"longitude":{"description":"Longitude","type":"string"}},"required":["latitude","longitude"],"strict":true,"type":"object"},"strict":false}],"tool_choice":"auto","truncation":"disabled","metadata":{},"groq":null,"temperature":1,"top_p":1,"user":null,"service_tier":"default","background":false,"error":null,"incomplete_details":null,"usage":{"input_tokens":330,"input_tokens_details":{"cached_tokens":0},"output_tokens":50,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":380},"parallel_tool_calls":true,"store":false,"top_logprobs":null,"max_tool_calls":null}
|
|
75
|
+
|
|
76
|
+
'
|
|
77
|
+
recorded_at: Wed, 07 Oct 2026 16:48:59 GMT
|
|
78
|
+
- request:
|
|
79
|
+
method: post
|
|
80
|
+
uri: https://api.groq.com/openai/v1/responses
|
|
81
|
+
body:
|
|
82
|
+
encoding: UTF-8
|
|
83
|
+
string: '{"model":"qwen/qwen3.8-27b","input":[{"role":"user","content":"What''s
|
|
84
|
+
the weather in Berlin? Use 52.5200, 13.4050."},{"type":"function_call","call_id":"need8cqcy","name":"weather","arguments":"{\"latitude\":\"52.5200\",\"longitude\":\"13.4050\"}"},{"type":"function_call_output","call_id":"need8cqcy","output":"Current
|
|
85
|
+
weather at 52.5200, 13.4050: 15°C, Wind: 10 km/h"}],"stream":false,"store":false,"tools":[{"type":"function","name":"weather","description":"Gets
|
|
86
|
+
current weather for a location","parameters":{"type":"object","properties":{"latitude":{"type":"string","description":"Latitude"},"longitude":{"type":"string","description":"Longitude"}},"required":["latitude","longitude"],"additionalProperties":false,"strict":true},"strict":false}]}'
|
|
87
|
+
headers:
|
|
88
|
+
User-Agent:
|
|
89
|
+
- Faraday v2.14.4
|
|
90
|
+
Authorization:
|
|
91
|
+
- Bearer <AUTH_TOKEN>
|
|
92
|
+
Content-Type:
|
|
93
|
+
- application/json
|
|
94
|
+
Accept-Encoding:
|
|
95
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
96
|
+
Accept:
|
|
97
|
+
- "*/*"
|
|
98
|
+
response:
|
|
99
|
+
status:
|
|
100
|
+
code: 200
|
|
101
|
+
message: OK
|
|
102
|
+
headers:
|
|
103
|
+
Date:
|
|
104
|
+
- Wed, 07 Oct 2026 16:48:59 GMT
|
|
105
|
+
Content-Type:
|
|
106
|
+
- application/json
|
|
107
|
+
Transfer-Encoding:
|
|
108
|
+
- chunked
|
|
109
|
+
Connection:
|
|
110
|
+
- keep-alive
|
|
111
|
+
Cache-Control:
|
|
112
|
+
- private, max-age=0, no-store, no-cache, must-revalidate
|
|
113
|
+
Server:
|
|
114
|
+
- cloudflare
|
|
115
|
+
Vary:
|
|
116
|
+
- Origin
|
|
117
|
+
X-Groq-Region:
|
|
118
|
+
- dls
|
|
119
|
+
X-Ratelimit-Limit-Requests:
|
|
120
|
+
- '1000'
|
|
121
|
+
X-Ratelimit-Limit-Tokens:
|
|
122
|
+
- '8000'
|
|
123
|
+
X-Ratelimit-Remaining-Requests:
|
|
124
|
+
- '993'
|
|
125
|
+
X-Ratelimit-Remaining-Tokens:
|
|
126
|
+
- '6708'
|
|
127
|
+
X-Ratelimit-Reset-Requests:
|
|
128
|
+
- 10m4.8s
|
|
129
|
+
X-Ratelimit-Reset-Tokens:
|
|
130
|
+
- 35.699s
|
|
131
|
+
X-Request-Id:
|
|
132
|
+
- req_01m4bm9bj5e0tbrfxv3ggsc541
|
|
133
|
+
Via:
|
|
134
|
+
- 1.1 google
|
|
135
|
+
Alt-Svc:
|
|
136
|
+
- h3=":443"; ma=86400
|
|
137
|
+
Cf-Cache-Status:
|
|
138
|
+
- DYNAMIC
|
|
139
|
+
Set-Cookie:
|
|
140
|
+
- __cf_bm=sMd2yUwGBBEW3i4mnVSFWKBtbgB1nhkCWBTAqofoNL4-1791391739.3726306-1.0.1.1-_RWoeDDTaqG4pxnQ8oyitUmC_1.IGF8x8EiPyB73b7nG.De3EC_TmPxh_fYBOADgdpgQQb.lhRJdHmHxq2FABtPQDuifhYzQhU9Md76q3xQ04NQHmp5z.C.9AahrVONy;
|
|
141
|
+
HttpOnly; SameSite=None; Secure; Path=/; Domain=groq.com; Expires=Wed, 07
|
|
142
|
+
Oct 2026 17:18:59 GMT
|
|
143
|
+
Strict-Transport-Security:
|
|
144
|
+
- max-age=15552000
|
|
145
|
+
Cf-Ray:
|
|
146
|
+
- a46e65831e0d8d58-HEL
|
|
147
|
+
body:
|
|
148
|
+
encoding: ASCII-8BIT
|
|
149
|
+
string: !binary |-
|
|
150
|
+
eyJpZCI6InJlc3BfMDFtNGJtOWJucmU3ZWJheTFiNnJwbTdnY2IiLCJvYmplY3QiOiJyZXNwb25zZSIsInN0YXR1cyI6ImNvbXBsZXRlZCIsImNyZWF0ZWRfYXQiOjE3OTEzOTE3MzksIm91dHB1dCI6W3sidHlwZSI6InJlYXNvbmluZyIsImlkIjoicmVzcF8wMW00Ym05Ym5yZTdlcmYyMW1zeDgzczl5eSIsInN0YXR1cyI6ImNvbXBsZXRlZCIsInN1bW1hcnkiOltdfSx7InR5cGUiOiJtZXNzYWdlIiwiaWQiOiJtc2dfMDFtNGJtOWJucmU3ZjgxNmM1NnlyYmhycGsiLCJzdGF0dXMiOiJjb21wbGV0ZWQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6W3sidHlwZSI6Im91dHB1dF90ZXh0IiwidGV4dCI6IlRoZSBjdXJyZW50IHdlYXRoZXIgaW4gQmVybGluIGlzIDE1wrBDIHdpdGggYSB3aW5kIHNwZWVkIG9mIDEwIGttL2guIiwiYW5ub3RhdGlvbnMiOltdLCJsb2dwcm9icyI6bnVsbH1dfV0sInByZXZpb3VzX3Jlc3BvbnNlX2lkIjpudWxsLCJtb2RlbCI6InF3ZW4vcXdlbjMuOC0yN2IiLCJyZWFzb25pbmciOnsiZWZmb3J0Ijoibm9uZSJ9LCJtYXhfb3V0cHV0X3Rva2VucyI6bnVsbCwidGV4dCI6eyJmb3JtYXQiOnsidHlwZSI6InRleHQifX0sInRvb2xzIjpbeyJ0eXBlIjoiZnVuY3Rpb24iLCJuYW1lIjoid2VhdGhlciIsImRlc2NyaXB0aW9uIjoiR2V0cyBjdXJyZW50IHdlYXRoZXIgZm9yIGEgbG9jYXRpb24iLCJwYXJhbWV0ZXJzIjp7ImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjpmYWxzZSwicHJvcGVydGllcyI6eyJsYXRpdHVkZSI6eyJkZXNjcmlwdGlvbiI6IkxhdGl0dWRlIiwidHlwZSI6InN0cmluZyJ9LCJsb25naXR1ZGUiOnsiZGVzY3JpcHRpb24iOiJMb25naXR1ZGUiLCJ0eXBlIjoic3RyaW5nIn19LCJyZXF1aXJlZCI6WyJsYXRpdHVkZSIsImxvbmdpdHVkZSJdLCJzdHJpY3QiOnRydWUsInR5cGUiOiJvYmplY3QifSwic3RyaWN0IjpmYWxzZX1dLCJ0b29sX2Nob2ljZSI6ImF1dG8iLCJ0cnVuY2F0aW9uIjoiZGlzYWJsZWQiLCJtZXRhZGF0YSI6e30sImdyb3EiOm51bGwsInRlbXBlcmF0dXJlIjoxLCJ0b3BfcCI6MSwidXNlciI6bnVsbCwic2VydmljZV90aWVyIjoiZGVmYXVsdCIsImJhY2tncm91bmQiOmZhbHNlLCJlcnJvciI6bnVsbCwiaW5jb21wbGV0ZV9kZXRhaWxzIjpudWxsLCJ1c2FnZSI6eyJpbnB1dF90b2tlbnMiOjQzMCwiaW5wdXRfdG9rZW5zX2RldGFpbHMiOnsiY2FjaGVkX3Rva2VucyI6MH0sIm91dHB1dF90b2tlbnMiOjIyLCJvdXRwdXRfdG9rZW5zX2RldGFpbHMiOnsicmVhc29uaW5nX3Rva2VucyI6MH0sInRvdGFsX3Rva2VucyI6NDUyfSwicGFyYWxsZWxfdG9vbF9jYWxscyI6dHJ1ZSwic3RvcmUiOmZhbHNlLCJ0b3BfbG9ncHJvYnMiOm51bGwsIm1heF90b29sX2NhbGxzIjpudWxsfQo=
|
|
151
|
+
recorded_at: Wed, 07 Oct 2026 16:48:59 GMT
|
|
152
|
+
recorded_with: VCR 6.4.0
|
data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_returns_structured_output.yml
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://api.groq.com/openai/v1/responses
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: '{"model":"qwen/qwen3.8-27b","input":[{"role":"user","content":"Generate
|
|
9
|
+
a person named John who is 30 years old"}],"stream":false,"store":false,"text":{"format":{"type":"json_schema","name":"response","schema":{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"}},"required":["name","age"],"additionalProperties":false},"strict":true}}}'
|
|
10
|
+
headers:
|
|
11
|
+
User-Agent:
|
|
12
|
+
- Faraday v2.14.4
|
|
13
|
+
Authorization:
|
|
14
|
+
- Bearer <AUTH_TOKEN>
|
|
15
|
+
Content-Type:
|
|
16
|
+
- application/json
|
|
17
|
+
Accept-Encoding:
|
|
18
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
19
|
+
Accept:
|
|
20
|
+
- "*/*"
|
|
21
|
+
response:
|
|
22
|
+
status:
|
|
23
|
+
code: 200
|
|
24
|
+
message: OK
|
|
25
|
+
headers:
|
|
26
|
+
Date:
|
|
27
|
+
- Wed, 07 Oct 2026 16:48:53 GMT
|
|
28
|
+
Content-Type:
|
|
29
|
+
- application/json
|
|
30
|
+
Transfer-Encoding:
|
|
31
|
+
- chunked
|
|
32
|
+
Connection:
|
|
33
|
+
- keep-alive
|
|
34
|
+
Cache-Control:
|
|
35
|
+
- private, max-age=0, no-store, no-cache, must-revalidate
|
|
36
|
+
Server:
|
|
37
|
+
- cloudflare
|
|
38
|
+
Vary:
|
|
39
|
+
- Origin
|
|
40
|
+
X-Groq-Region:
|
|
41
|
+
- dls
|
|
42
|
+
X-Ratelimit-Limit-Requests:
|
|
43
|
+
- '1000'
|
|
44
|
+
X-Ratelimit-Limit-Tokens:
|
|
45
|
+
- '8000'
|
|
46
|
+
X-Ratelimit-Remaining-Requests:
|
|
47
|
+
- '999'
|
|
48
|
+
X-Ratelimit-Remaining-Tokens:
|
|
49
|
+
- '7791'
|
|
50
|
+
X-Ratelimit-Reset-Requests:
|
|
51
|
+
- 1m26.4s
|
|
52
|
+
X-Ratelimit-Reset-Tokens:
|
|
53
|
+
- 1.567s
|
|
54
|
+
X-Request-Id:
|
|
55
|
+
- req_01m4bm95h6eknbhd2g57rb86ak
|
|
56
|
+
Via:
|
|
57
|
+
- 1.1 google
|
|
58
|
+
Alt-Svc:
|
|
59
|
+
- h3=":443"; ma=86400
|
|
60
|
+
Cf-Cache-Status:
|
|
61
|
+
- DYNAMIC
|
|
62
|
+
Set-Cookie:
|
|
63
|
+
- __cf_bm=Rp.gZmJcvxYbWZDsbdfQDBTAz7DaFtywcVrwdQQSlXk-1791391733.2010832-1.0.1.1-MBeC0_FXCrPoveYPbgkP024YhTYGhnm2G8ai26jtHdCFBhXKN11v070xGxHdVs6b11ivLdL8VDl_Rkqlhfa4lE0lfIcHCiMUBNgwfgDgZ88op59V9O6YeWQYlBnkTMXH;
|
|
64
|
+
HttpOnly; SameSite=None; Secure; Path=/; Domain=groq.com; Expires=Wed, 07
|
|
65
|
+
Oct 2026 17:18:53 GMT
|
|
66
|
+
Strict-Transport-Security:
|
|
67
|
+
- max-age=15552000
|
|
68
|
+
Cf-Ray:
|
|
69
|
+
- a46e655c799e4825-HEL
|
|
70
|
+
body:
|
|
71
|
+
encoding: ASCII-8BIT
|
|
72
|
+
string: '{"id":"resp_01m4bm95k1ejrt9pm29qkr3r1w","object":"response","status":"completed","created_at":1791391733,"output":[{"type":"reasoning","id":"resp_01m4bm95k1ejs9anac75h9cntj","status":"completed","summary":[]},{"type":"message","id":"msg_01m4bm95k1ejst5m6wcxpz59xh","status":"completed","role":"assistant","content":[{"type":"output_text","text":"{\"age\":
|
|
73
|
+
30, \"name\": \"John\"}","annotations":[],"logprobs":null}]}],"previous_response_id":null,"model":"qwen/qwen3.8-27b","reasoning":{"effort":"none"},"max_output_tokens":null,"text":{"format":{"type":"json_schema","name":"response","schema":{"additionalProperties":false,"properties":{"age":{"type":"integer"},"name":{"type":"string"}},"required":["name","age"],"type":"object"},"strict":true}},"tools":[],"tool_choice":"auto","truncation":"disabled","metadata":{},"groq":null,"temperature":1,"top_p":1,"user":null,"service_tier":"default","background":false,"error":null,"incomplete_details":null,"usage":{"input_tokens":24,"input_tokens_details":{"cached_tokens":0},"output_tokens":15,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":39},"parallel_tool_calls":true,"store":false,"top_logprobs":null,"max_tool_calls":null}
|
|
74
|
+
|
|
75
|
+
'
|
|
76
|
+
recorded_at: Wed, 07 Oct 2026 16:48:53 GMT
|
|
77
|
+
recorded_with: VCR 6.4.0
|
data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_returns_the_raw_response.yml
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://api.groq.com/openai/v1/responses
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: '{"model":"qwen/qwen3.8-27b","input":[{"role":"user","content":"What
|
|
9
|
+
is the capital of France?"}],"stream":false,"store":false}'
|
|
10
|
+
headers:
|
|
11
|
+
User-Agent:
|
|
12
|
+
- Faraday v2.14.4
|
|
13
|
+
Authorization:
|
|
14
|
+
- Bearer <AUTH_TOKEN>
|
|
15
|
+
Content-Type:
|
|
16
|
+
- application/json
|
|
17
|
+
Accept-Encoding:
|
|
18
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
19
|
+
Accept:
|
|
20
|
+
- "*/*"
|
|
21
|
+
response:
|
|
22
|
+
status:
|
|
23
|
+
code: 200
|
|
24
|
+
message: OK
|
|
25
|
+
headers:
|
|
26
|
+
Date:
|
|
27
|
+
- Wed, 07 Oct 2026 16:48:57 GMT
|
|
28
|
+
Content-Type:
|
|
29
|
+
- application/json
|
|
30
|
+
Transfer-Encoding:
|
|
31
|
+
- chunked
|
|
32
|
+
Connection:
|
|
33
|
+
- keep-alive
|
|
34
|
+
Cache-Control:
|
|
35
|
+
- private, max-age=0, no-store, no-cache, must-revalidate
|
|
36
|
+
Server:
|
|
37
|
+
- cloudflare
|
|
38
|
+
Vary:
|
|
39
|
+
- Origin
|
|
40
|
+
X-Groq-Region:
|
|
41
|
+
- dls
|
|
42
|
+
X-Ratelimit-Limit-Requests:
|
|
43
|
+
- '1000'
|
|
44
|
+
X-Ratelimit-Limit-Tokens:
|
|
45
|
+
- '8000'
|
|
46
|
+
X-Ratelimit-Remaining-Requests:
|
|
47
|
+
- '995'
|
|
48
|
+
X-Ratelimit-Remaining-Tokens:
|
|
49
|
+
- '7392'
|
|
50
|
+
X-Ratelimit-Reset-Requests:
|
|
51
|
+
- 7m12s
|
|
52
|
+
X-Ratelimit-Reset-Tokens:
|
|
53
|
+
- 35.34s
|
|
54
|
+
X-Request-Id:
|
|
55
|
+
- req_01m4bm99xzedvt58x4pv2vqdtn
|
|
56
|
+
Via:
|
|
57
|
+
- 1.1 google
|
|
58
|
+
Alt-Svc:
|
|
59
|
+
- h3=":443"; ma=86400
|
|
60
|
+
Cf-Cache-Status:
|
|
61
|
+
- DYNAMIC
|
|
62
|
+
Set-Cookie:
|
|
63
|
+
- __cf_bm=XLgVqOc4BryYpxr3WtbJj06g9ruNoyrH7wPhKXTx4OY-1791391737.6914153-1.0.1.1-fvXlPgyrWk0GhH6hiMdkiKPIMQMcDI6ar4utialeFyFpzwbD6tDVU4IKhZCK6J4.WdVQT.16glOHfj5lwpSsDuVqP_E_HMKTWdaVZpxcEowI2DGTh.aCZt32QFwRjwYK;
|
|
64
|
+
HttpOnly; SameSite=None; Secure; Path=/; Domain=groq.com; Expires=Wed, 07
|
|
65
|
+
Oct 2026 17:18:57 GMT
|
|
66
|
+
Strict-Transport-Security:
|
|
67
|
+
- max-age=15552000
|
|
68
|
+
Cf-Ray:
|
|
69
|
+
- a46e65789a841ede-HEL
|
|
70
|
+
body:
|
|
71
|
+
encoding: ASCII-8BIT
|
|
72
|
+
string: '{"id":"resp_01m4bm99zeeeavesphwjm6thn2","object":"response","status":"completed","created_at":1791391737,"output":[{"type":"reasoning","id":"resp_01m4bm99zeeeb877rssymg8dbc","status":"completed","summary":[]},{"type":"message","id":"msg_01m4bm99zeeebtv8sty8x7x5qf","status":"completed","role":"assistant","content":[{"type":"output_text","text":"The
|
|
73
|
+
capital of France is **Paris**.","annotations":[],"logprobs":null}]}],"previous_response_id":null,"model":"qwen/qwen3.8-27b","reasoning":{"effort":"none"},"max_output_tokens":null,"text":{"format":{"type":"text"}},"tools":[],"tool_choice":"auto","truncation":"disabled","metadata":{},"groq":null,"temperature":1,"top_p":1,"user":null,"service_tier":"default","background":false,"error":null,"incomplete_details":null,"usage":{"input_tokens":19,"input_tokens_details":{"cached_tokens":0},"output_tokens":9,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":28},"parallel_tool_calls":true,"store":false,"top_logprobs":null,"max_tool_calls":null}
|
|
74
|
+
|
|
75
|
+
'
|
|
76
|
+
recorded_at: Wed, 07 Oct 2026 16:48:57 GMT
|
|
77
|
+
recorded_with: VCR 6.4.0
|
data/spec/fixtures/vcr_cassettes/rubyllm_chat_groq_qwen_qwen3_8_27b_supports_streaming_responses.yml
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://api.groq.com/openai/v1/responses
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: '{"model":"qwen/qwen3.8-27b","input":[{"role":"user","content":"Count
|
|
9
|
+
from 1 to 3"}],"stream":true,"store":false}'
|
|
10
|
+
headers:
|
|
11
|
+
User-Agent:
|
|
12
|
+
- Faraday v2.14.4
|
|
13
|
+
Authorization:
|
|
14
|
+
- Bearer <AUTH_TOKEN>
|
|
15
|
+
Content-Type:
|
|
16
|
+
- application/json
|
|
17
|
+
Accept-Encoding:
|
|
18
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
19
|
+
Accept:
|
|
20
|
+
- "*/*"
|
|
21
|
+
response:
|
|
22
|
+
status:
|
|
23
|
+
code: 200
|
|
24
|
+
message: OK
|
|
25
|
+
headers:
|
|
26
|
+
Date:
|
|
27
|
+
- Wed, 07 Oct 2026 16:48:53 GMT
|
|
28
|
+
Content-Type:
|
|
29
|
+
- text/event-stream
|
|
30
|
+
Transfer-Encoding:
|
|
31
|
+
- chunked
|
|
32
|
+
Connection:
|
|
33
|
+
- keep-alive
|
|
34
|
+
Cache-Control:
|
|
35
|
+
- no-cache
|
|
36
|
+
Server:
|
|
37
|
+
- cloudflare
|
|
38
|
+
Vary:
|
|
39
|
+
- Origin
|
|
40
|
+
X-Groq-Region:
|
|
41
|
+
- dls
|
|
42
|
+
X-Ratelimit-Limit-Requests:
|
|
43
|
+
- '1000'
|
|
44
|
+
X-Ratelimit-Limit-Tokens:
|
|
45
|
+
- '8000'
|
|
46
|
+
X-Ratelimit-Remaining-Requests:
|
|
47
|
+
- '998'
|
|
48
|
+
X-Ratelimit-Remaining-Tokens:
|
|
49
|
+
- '7637'
|
|
50
|
+
X-Ratelimit-Reset-Requests:
|
|
51
|
+
- 2m52.8s
|
|
52
|
+
X-Ratelimit-Reset-Tokens:
|
|
53
|
+
- 20.639s
|
|
54
|
+
X-Request-Id:
|
|
55
|
+
- req_01m4bm95xdecs8vyvydz11t9f3
|
|
56
|
+
Via:
|
|
57
|
+
- 1.1 google
|
|
58
|
+
Alt-Svc:
|
|
59
|
+
- h3=":443"; ma=86400
|
|
60
|
+
Cf-Cache-Status:
|
|
61
|
+
- DYNAMIC
|
|
62
|
+
Set-Cookie:
|
|
63
|
+
- __cf_bm=dFAMGYsleaUx5TfCxJRPrwOcHlC98BasyB4BcELoUS0-1791391733.5906844-1.0.1.1-VJy8waJsRXkDe2_7PLnqoH6bsxhgpxa9Ljjn1V_9ajfz9zPnXSkn8wH6HaVwA.WBgsiqO38cbaoVujL_7RBJlVJ0WA.DJpY3PRRDXdlX6eSBIcaTDm0uS8nmch_n5hDU;
|
|
64
|
+
HttpOnly; SameSite=None; Secure; Path=/; Domain=groq.com; Expires=Wed, 07
|
|
65
|
+
Oct 2026 17:18:53 GMT
|
|
66
|
+
Strict-Transport-Security:
|
|
67
|
+
- max-age=15552000
|
|
68
|
+
Cf-Ray:
|
|
69
|
+
- a46e655ee85cf78c-HEL
|
|
70
|
+
body:
|
|
71
|
+
encoding: UTF-8
|
|
72
|
+
string: |+
|
|
73
|
+
event: response.created
|
|
74
|
+
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_01m4bm95y7eb28tghetrch4vgh","object":"response","status":"in_progress","created_at":1791391733,"output":[],"previous_response_id":null,"model":"qwen/qwen3.8-27b","reasoning":{"effort":"none"},"max_output_tokens":null,"text":{"format":{"type":"text"}},"tools":[],"tool_choice":"auto","truncation":"disabled","metadata":{},"groq":null,"temperature":1,"top_p":1,"user":null,"service_tier":"default","background":false,"error":null,"incomplete_details":null,"parallel_tool_calls":true,"store":false,"top_logprobs":null,"max_tool_calls":null}}
|
|
75
|
+
|
|
76
|
+
event: response.in_progress
|
|
77
|
+
data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_01m4bm95y7eb28tghetrch4vgh","object":"response","status":"in_progress","created_at":1791391733,"output":[],"previous_response_id":null,"model":"qwen/qwen3.8-27b","reasoning":{"effort":"none"},"max_output_tokens":null,"text":{"format":{"type":"text"}},"tools":[],"tool_choice":"auto","truncation":"disabled","metadata":{},"groq":null,"temperature":1,"top_p":1,"user":null,"service_tier":"default","background":false,"error":null,"incomplete_details":null,"parallel_tool_calls":true,"store":false,"top_logprobs":null,"max_tool_calls":null}}
|
|
78
|
+
|
|
79
|
+
event: response.output_item.added
|
|
80
|
+
data: {"type":"response.output_item.added","sequence_number":2,"output_index":1,"item":{"type":"message","id":"msg_01m4bm95y8ezvtt1mwca86he3j","role":"assistant","content":[]}}
|
|
81
|
+
|
|
82
|
+
event: response.content_part.added
|
|
83
|
+
data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"part":{"type":"output_text","text":"","annotations":[],"logprobs":null}}
|
|
84
|
+
|
|
85
|
+
event: response.output_text.delta
|
|
86
|
+
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"delta":"1","logprobs":[]}
|
|
87
|
+
|
|
88
|
+
event: response.output_text.delta
|
|
89
|
+
data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"delta":",","logprobs":[]}
|
|
90
|
+
|
|
91
|
+
event: response.output_text.delta
|
|
92
|
+
data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"delta":" ","logprobs":[]}
|
|
93
|
+
|
|
94
|
+
event: response.output_text.delta
|
|
95
|
+
data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"delta":"2","logprobs":[]}
|
|
96
|
+
|
|
97
|
+
event: response.output_text.delta
|
|
98
|
+
data: {"type":"response.output_text.delta","sequence_number":8,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"delta":",","logprobs":[]}
|
|
99
|
+
|
|
100
|
+
event: response.output_text.delta
|
|
101
|
+
data: {"type":"response.output_text.delta","sequence_number":9,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"delta":" ","logprobs":[]}
|
|
102
|
+
|
|
103
|
+
event: response.output_text.delta
|
|
104
|
+
data: {"type":"response.output_text.delta","sequence_number":10,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"delta":"3","logprobs":[]}
|
|
105
|
+
|
|
106
|
+
event: response.output_item.added
|
|
107
|
+
data: {"type":"response.output_item.added","sequence_number":11,"output_index":0,"item":{"type":"reasoning","id":"resp_01m4bm95y7eb2tjx9hqns9d3pg","content":[{"type":"reasoning_text","text":""}],"summary":[]}}
|
|
108
|
+
|
|
109
|
+
event: response.output_item.done
|
|
110
|
+
data: {"type":"response.output_item.done","sequence_number":12,"output_index":0,"item":{"type":"reasoning","id":"resp_01m4bm95y7eb2tjx9hqns9d3pg","content":[{"type":"reasoning_text","text":""}],"summary":[]}}
|
|
111
|
+
|
|
112
|
+
event: response.output_text.done
|
|
113
|
+
data: {"type":"response.output_text.done","sequence_number":13,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"text":"1, 2, 3","logprobs":[]}
|
|
114
|
+
|
|
115
|
+
event: response.content_part.done
|
|
116
|
+
data: {"type":"response.content_part.done","sequence_number":14,"item_id":"msg_01m4bm95y8ezvtt1mwca86he3j","output_index":1,"content_index":0,"part":{"type":"output_text","text":"1, 2, 3","annotations":[],"logprobs":null}}
|
|
117
|
+
|
|
118
|
+
event: response.output_item.done
|
|
119
|
+
data: {"type":"response.output_item.done","sequence_number":15,"output_index":1,"item":{"type":"message","id":"msg_01m4bm95y8ezvtt1mwca86he3j","status":"completed","role":"assistant","content":[{"type":"output_text","text":"1, 2, 3","annotations":[],"logprobs":[]}]}}
|
|
120
|
+
|
|
121
|
+
event: response.completed
|
|
122
|
+
data: {"type":"response.completed","sequence_number":16,"response":{"id":"resp_01m4bm95y7eb28tghetrch4vgh","object":"response","status":"completed","created_at":1791391733,"output":[{"type":"reasoning","id":"resp_01m4bm95y7eb2tjx9hqns9d3pg","content":[{"type":"reasoning_text","text":""}],"summary":[]},{"type":"message","id":"msg_01m4bm95y8ezvtt1mwca86he3j","status":"completed","role":"assistant","content":[{"type":"output_text","text":"1, 2, 3","annotations":[],"logprobs":[]}]}],"previous_response_id":null,"model":"qwen/qwen3.8-27b","reasoning":{"effort":"none"},"max_output_tokens":null,"text":{"format":{"type":"text"}},"tools":[],"tool_choice":"auto","truncation":"disabled","metadata":{},"groq":null,"temperature":1,"top_p":1,"user":null,"service_tier":"default","background":false,"error":null,"incomplete_details":null,"usage":{"input_tokens":19,"input_tokens_details":{"cached_tokens":0},"output_tokens":8,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":27},"parallel_tool_calls":true,"store":false,"top_logprobs":null,"max_tool_calls":null}}
|
|
123
|
+
|
|
124
|
+
recorded_at: Wed, 07 Oct 2026 16:48:53 GMT
|
|
125
|
+
recorded_with: VCR 6.4.0
|
|
126
|
+
...
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyLLM::Chat, :live do
|
|
6
|
+
include_context 'with configured RubyLLM'
|
|
7
|
+
|
|
8
|
+
let(:person_schema) do
|
|
9
|
+
{
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
name: { type: 'string' },
|
|
13
|
+
age: { type: 'integer' }
|
|
14
|
+
},
|
|
15
|
+
required: %w[name age],
|
|
16
|
+
additionalProperties: false
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
each_model(STRUCTURED_OUTPUT_MODELS) do |provider, model|
|
|
21
|
+
it "#{provider}/#{model} returns structured output" do
|
|
22
|
+
response = RubyLLM.chat(model: model, provider: provider, assume_model_exists: true)
|
|
23
|
+
.with_schema(person_schema)
|
|
24
|
+
.ask('Generate a person named John who is 30 years old')
|
|
25
|
+
|
|
26
|
+
expect(response.content).to be_a(String)
|
|
27
|
+
expect(response.parsed).to include('name' => 'John', 'age' => 30)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyLLM::Chat, :live do
|
|
6
|
+
include_context 'with configured RubyLLM'
|
|
7
|
+
|
|
8
|
+
each_model(CHAT_MODELS) do |provider, model|
|
|
9
|
+
it "#{provider}/#{model} can have a basic conversation" do
|
|
10
|
+
response = RubyLLM.chat(model: model, provider: provider, assume_model_exists: true).ask("What's 2 + 2?")
|
|
11
|
+
|
|
12
|
+
expect(response.content).to include('4')
|
|
13
|
+
expect(response.role).to eq(:assistant)
|
|
14
|
+
expect(response.tokens.input.to_i).to be_positive
|
|
15
|
+
expect(response.tokens.output.to_i).to be_positive
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "#{provider}/#{model} returns the raw response" do
|
|
19
|
+
response = RubyLLM.chat(model: model, provider: provider, assume_model_exists: true)
|
|
20
|
+
.ask('What is the capital of France?')
|
|
21
|
+
|
|
22
|
+
expect(response.raw.status).to eq(200)
|
|
23
|
+
expect(response.raw.headers).not_to be_empty
|
|
24
|
+
expect(response.raw.body).not_to be_empty
|
|
25
|
+
expect(response.raw.env.request_body).not_to be_empty
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "#{provider}/#{model} can handle a multi-turn conversation" do
|
|
29
|
+
chat = RubyLLM.chat(model: model, provider: provider, assume_model_exists: true)
|
|
30
|
+
|
|
31
|
+
expect(chat.ask('Who created the programming language Ruby?').content).to match(/Matz|Matsumoto/i)
|
|
32
|
+
expect(chat.ask('What year was Ruby first released?').content).to include('199')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyLLM::Chat, :live do
|
|
6
|
+
include_context 'with configured RubyLLM'
|
|
7
|
+
|
|
8
|
+
each_model(CHAT_MODELS) do |provider, model|
|
|
9
|
+
it "#{provider}/#{model} supports streaming responses" do
|
|
10
|
+
chunks = []
|
|
11
|
+
chat = RubyLLM.chat(model: model, provider: provider, assume_model_exists: true)
|
|
12
|
+
|
|
13
|
+
response = chat.ask('Count from 1 to 3') { |chunk| chunks << chunk }
|
|
14
|
+
|
|
15
|
+
expect(chunks).not_to be_empty
|
|
16
|
+
expect(chunks.first).to be_a(RubyLLM::Chunk)
|
|
17
|
+
expect(response.raw.status).to eq(200)
|
|
18
|
+
expect(response.raw.headers).not_to be_empty
|
|
19
|
+
expect(response.raw.env.request_body).not_to be_empty
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyLLM::Chat, :live do
|
|
6
|
+
include_context 'with configured RubyLLM'
|
|
7
|
+
|
|
8
|
+
let(:weather_tool) do
|
|
9
|
+
Class.new(RubyLLM::Tool) do
|
|
10
|
+
def self.name = 'WeatherTool'
|
|
11
|
+
description 'Gets current weather for a location'
|
|
12
|
+
parameter :latitude, description: 'Latitude'
|
|
13
|
+
parameter :longitude, description: 'Longitude'
|
|
14
|
+
|
|
15
|
+
def execute(latitude:, longitude:)
|
|
16
|
+
"Current weather at #{latitude}, #{longitude}: 15°C, Wind: 10 km/h"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
each_model(TOOL_MODELS) do |provider, model|
|
|
22
|
+
it "#{provider}/#{model} can use tools" do
|
|
23
|
+
chat = RubyLLM.chat(model: model, provider: provider, assume_model_exists: true).with_tools(weather_tool)
|
|
24
|
+
response = chat.ask("What's the weather in Berlin? Use 52.5200, 13.4050.")
|
|
25
|
+
|
|
26
|
+
expect(response.content).to include('15')
|
|
27
|
+
expect(response.content).to include('10')
|
|
28
|
+
expect(chat.messages.any?(&:tool_call?)).to be(true)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyLLM::Embedding, :live do
|
|
6
|
+
include_context 'with configured RubyLLM'
|
|
7
|
+
|
|
8
|
+
each_model(EMBEDDING_MODELS) do |provider, model, model_info|
|
|
9
|
+
it "#{provider}/#{model} embeds one text" do
|
|
10
|
+
embedding = RubyLLM.embed(
|
|
11
|
+
"Ruby is a programmer's best friend",
|
|
12
|
+
model: model,
|
|
13
|
+
provider: provider,
|
|
14
|
+
assume_model_exists: true
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
expect(embedding.vectors).to be_an(Array)
|
|
18
|
+
expect(embedding.vectors.first).to be_a(Numeric)
|
|
19
|
+
expect(embedding.model).to eq(model)
|
|
20
|
+
expect(embedding.tokens.input.to_i).to be >= 0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "#{provider}/#{model} embeds several texts" do
|
|
24
|
+
embeddings = RubyLLM.embed(
|
|
25
|
+
%w[Ruby Python JavaScript],
|
|
26
|
+
model: model,
|
|
27
|
+
provider: provider,
|
|
28
|
+
assume_model_exists: true
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
expect(embeddings.vectors.size).to eq(3)
|
|
32
|
+
expect(embeddings.vectors).to all(be_an(Array))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
next unless model_info[:dimensions]
|
|
36
|
+
|
|
37
|
+
it "#{provider}/#{model} supports custom dimensions" do
|
|
38
|
+
embedding = RubyLLM.embed(
|
|
39
|
+
'Ruby',
|
|
40
|
+
model: model,
|
|
41
|
+
provider: provider,
|
|
42
|
+
assume_model_exists: true,
|
|
43
|
+
dimensions: model_info[:dimensions]
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
expect(embedding.vectors.length).to eq(model_info[:dimensions])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyLLM::Image, :live do
|
|
6
|
+
include_context 'with configured RubyLLM'
|
|
7
|
+
|
|
8
|
+
each_model(IMAGE_GENERATION_MODELS) do |provider, model, model_info|
|
|
9
|
+
it "#{provider}/#{model} paints an image" do
|
|
10
|
+
image = RubyLLM.paint(
|
|
11
|
+
'a siamese cat',
|
|
12
|
+
model: model,
|
|
13
|
+
provider: provider,
|
|
14
|
+
assume_model_exists: true,
|
|
15
|
+
provider_options: model_info.fetch(:provider_options, {})
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
expect(image.mime_type).to include('image')
|
|
19
|
+
expect(image.model).to eq(model)
|
|
20
|
+
expect(image.to_blob.bytesize).to be > 1000
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe RubyLLM::Models do
|
|
6
|
+
include_context 'with configured RubyLLM'
|
|
7
|
+
|
|
8
|
+
it 'expects generated providers to add registry metadata before use' do
|
|
9
|
+
expect(RubyLLM::Providers::Groq.assume_models_exist?).to be(false)
|
|
10
|
+
end
|
|
11
|
+
end
|