confamnode 0.3.0__tar.gz → 0.3.3__tar.gz

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 (28) hide show
  1. {confamnode-0.3.0 → confamnode-0.3.3}/PKG-INFO +335 -91
  2. {confamnode-0.3.0 → confamnode-0.3.3}/README.md +333 -89
  3. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/registry.py +24 -30
  4. {confamnode-0.3.0 → confamnode-0.3.3}/pyproject.toml +1 -1
  5. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_client.py +2 -2
  6. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_embed.py +34 -33
  7. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_gist.py +48 -35
  8. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_stream.py +32 -28
  9. {confamnode-0.3.0 → confamnode-0.3.3}/uv.lock +1 -1
  10. {confamnode-0.3.0 → confamnode-0.3.3}/.gitignore +0 -0
  11. {confamnode-0.3.0 → confamnode-0.3.3}/.python-version +0 -0
  12. {confamnode-0.3.0 → confamnode-0.3.3}/LICENSE +0 -0
  13. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/__init__.py +0 -0
  14. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/ansa.py +0 -0
  15. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/builders.py +0 -0
  16. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/client.py +0 -0
  17. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/config.py +0 -0
  18. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/exceptions.py +0 -0
  19. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/models.py +0 -0
  20. {confamnode-0.3.0 → confamnode-0.3.3}/confamnode/utils.py +0 -0
  21. {confamnode-0.3.0 → confamnode-0.3.3}/tests/__init__.py +0 -0
  22. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_ansa.py +0 -0
  23. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_cache_flag.py +0 -0
  24. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_client_errors.py +0 -0
  25. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_exceptions.py +0 -0
  26. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_init.py +0 -0
  27. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_models.py +0 -0
  28. {confamnode-0.3.0 → confamnode-0.3.3}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: confamnode
3
- Version: 0.3.0
3
+ Version: 0.3.3
4
4
  Summary: The Nigerian AI inference gateway
5
5
  Project-URL: Repository, https://github.com/confamnodeai/confamnode
6
6
  Project-URL: Bug Tracker, https://github.com/confamnodeai/confamnode/issues
@@ -88,7 +88,7 @@ from confamnode import ConfamNode
88
88
  client = ConfamNode(api_key="confam-xxx")
89
89
 
90
90
  ansa = client.gist(
91
- model="confam-speed",
91
+ model="gemini/gemini-3.5-flash-lite",
92
92
  messages="How you dey?"
93
93
  )
94
94
 
@@ -108,7 +108,7 @@ from confamnode import ConfamNode
108
108
  client = ConfamNode(api_key="confam-xxx")
109
109
 
110
110
  stream = client.gist(
111
- model="confam-speed",
111
+ model="gemini/gemini-3.5-flash-lite",
112
112
  messages="Wetin be the capital of 9ja?",
113
113
  stream=True
114
114
  )
@@ -134,7 +134,7 @@ print(f"ID: {ansa.id}")
134
134
  Every `gist()` call returns an `Ansa` object:
135
135
 
136
136
  ```python
137
- ansa = client.gist(model="confam-speed", messages="How you dey?")
137
+ ansa = client.gist(model="gemini/gemini-3.5-flash-lite", messages="How you dey?")
138
138
 
139
139
  # Response
140
140
  ansa.text # response text
@@ -181,7 +181,7 @@ client = ConfamNode(api_key="confam-xxx")
181
181
 
182
182
  # Single string in → one flat vector out
183
183
  result = client.embed(
184
- model="confam-embed-local",
184
+ model="liquid/lfm-2.5-embedding-350m:free",
185
185
  input="How you dey?"
186
186
  )
187
187
 
@@ -191,22 +191,20 @@ print(f"Tokens: {result.usage.total_tokens}")
191
191
 
192
192
  # List in → list of vectors out, always — even with one item
193
193
  result = client.embed(
194
- model="confam-embed-local",
194
+ model="liquid/lfm-2.5-embedding-350m:free",
195
195
  input=["How you dey?", "Wetin dey happen?"]
196
196
  )
197
197
 
198
198
  print(len(result.embeddings)) # 2
199
199
  ```
200
200
 
201
- `confam-embed-local` is currently the only available embedding model. More coming soon.
202
-
203
201
  ### Task types
204
202
 
205
203
  Some embedding models expect a task-type hint (e.g. `"query"` vs. `"document"`) to produce better embeddings for retrieval use cases. This defaults sensibly server-side if omitted — only pass it if you need a specific one:
206
204
 
207
205
  ```python
208
206
  result = client.embed(
209
- model="confam-embed-local",
207
+ model="liquid/lfm-2.5-embedding-350m:free",
210
208
  input="find me a good jollof rice recipe",
211
209
  task_type="query"
212
210
  )
@@ -219,7 +217,7 @@ print(result.task_type_applied) # confirms what actually happened for this call
219
217
  ### The EmbeddingResult Object
220
218
 
221
219
  ```python
222
- result = client.embed(model="confam-embed-local", input="How you dey?")
220
+ result = client.embed(model="liquid/lfm-2.5-embedding-350m:free", input="How you dey?")
223
221
 
224
222
  result.embeddings # vector(s) — shape matches your input shape
225
223
  result.model # model that served the request
@@ -234,46 +232,41 @@ result.id # unique request ID
234
232
  result.raw # full raw response
235
233
  ```
236
234
 
237
- ### Batch limits (`confam-embed-local`)
238
-
239
- Self-hosted embedding requests to `confam-embed-local` are served in batches of up to 4 concurrent requests at a time. If you're embedding a large number of documents, being aware of this batching ceiling will give you a more predictable sense of total time than assuming unlimited concurrency.
240
-
241
235
  ---
242
236
 
243
237
  ## Models
244
238
 
245
- ### Free Tier
239
+ #### Free Tier
246
240
 
247
- | Model | Description | Modality | Price |
248
- |---|---|---|---|
249
- | `confam-speed` | Fast, high quality responses | Image-Text-to-Text | Free |
250
- | `confam-reasoning` | Standard reasoning and analysis | Text-to-Text | Free |
241
+ | Model | Modality | Input ₦/1M | Output ₦/1M | Input ₦/1K | Output ₦/1K |
242
+ |---|---|---|---|---|---|
243
+ | `gemini/gemini-3.1-flash-lite` | Text/Image/Video/File/Audio -> Text | ₦0 | ₦0| ₦0 | ₦0 |
244
+ | `gemini/gemini-3.5-flash-lite` | Text/Image/Video/File/Audio -> Text | ₦0 | ₦0| ₦0 | ₦0 |
245
+ | `nvidia/nemotron-3-super-120b-a12b:free` | Text -> Text | ₦0 | ₦0| ₦0 | ₦0 |
246
+ | `nvidia/nemotron-3-ultra-550b-a55b:free` | Text -> Text | ₦0 | ₦0| ₦0 | ₦0 |
251
247
 
252
- ### Paid Tier
248
+ #### Paid Tier
253
249
 
254
- | Model | Description | Modality | Input ₦/1M | Output ₦/1M | Input ₦/1K | Output ₦/1K |
255
- |---|---|---|---|---|---|---|
256
- | `confam-intelligence` | General smart tasks, 1M context | Image-Text-to-Text | ₦596 | ₦3,571 | ₦0.596 | ₦3.571 |
257
- | `confam-deep-reasoning` | Complex thinking, multi-step analysis | Image-Text-to-Text | ₦234 | ₦468 | ₦0.234 | ₦0.468 |
258
- | `confam-code` | Coding assistance, 1M context | Image-Text-to-Text | ₦234 | ₦468 | ₦0.234 | ₦0.468 |
250
+ | Model | Modality | Input ₦/1M | Output ₦/1M | Input ₦/1K | Output ₦/1K |
251
+ |---|---|---|---|---|---|
252
+ | `deepseek/deepseek-v4.1-flash` | Text/Image -> Text | ₦704 | ₦2,813 | ₦0.704 | ₦2.813 |
259
253
 
260
- ### Local Models — Nigerian Data Residency
254
+ ### Embeddings
261
255
 
262
- | Model | Description | Modality | Input ₦/1M | Output ₦/1M | Input ₦/1K | Output ₦/1K |
263
- |---|---|---|---|---|---|---|
264
- | `confam-health` | Local model, health information use cases — data stays in Nigeria | Image-Text-to-Text | ₦500 | ₦1,500 | ₦0.500 | ₦1.500 |
265
- | `confam-local` | Local model, general-purpose — data stays in Nigeria | Text-to-Text | ₦500 | ₦1,500 | ₦0.500 | ₦1.500 |
256
+ #### Free Tier
266
257
 
267
- ### Embeddings
258
+ | Model | Modality | Input ₦/1M | Output ₦/1M | Input ₦/1K | Output ₦/1K |
259
+ |---|---|---|---|---|---|
260
+ | `liquid/lfm-2.5-embedding-350m:free` | Text -> Embeddings | ₦0 | ₦0 | ₦0 | ₦0 |
268
261
 
269
- | Model | Description | Where it runs |
270
- |---|---|---|
271
- | `confam-embed-local` | Self-hosted text embeddings — data stays in Nigeria | Local |
262
+ #### Paid Tier
272
263
 
273
- More embedding models coming soon.
264
+ | Model | Modality | Input ₦/1M | Output ₦/1M | Input ₦/1K | Output ₦/1K |
265
+ |---|---|---|---|---|---|
266
+ | `google/gemini-embedding-001` | Text -> Embeddings | ₦352 | ₦0 | ₦0.352 | ₦0 |
267
+ | `google/gemini-embedding-2` | Text/Image/File/Audio/Video -> Text | ₦469 | ₦0 | ₦0.469 | ₦0 |
274
268
 
275
- Local models run entirely on Nigerian hardware. Data never transmitted abroad.
276
- Ideal for banks, fintechs, hospitals, law firms, and government agencies.
269
+ More embedding models coming soon.
277
270
 
278
271
  More models coming soon. Contact [hello@confamnode.com](mailto:hello@confamnode.com) for early access.
279
272
 
@@ -299,7 +292,6 @@ Rate limits vary by plan. Contact [hello@confamnode.com](mailto:hello@confamnode
299
292
 
300
293
  - **Free tier** — shared capacity with lower limits
301
294
  - **Paid tier** — dedicated higher limits
302
- - **Local models** (`confam-health`, `confam-local`) — deployed on dedicated Nigerian hardware (Jetson AGX Orin), with a shared concurrency cap across both models. Under heavy simultaneous load, requests queue briefly rather than failing outright.
303
295
 
304
296
  ---
305
297
 
@@ -310,21 +302,21 @@ ConfamNode adds a default system message to every request giving the model a Nig
310
302
  ```python
311
303
  # Use ConfamNode default identity (default)
312
304
  ansa = client.gist(
313
- model="confam-speed",
305
+ model="gemini/gemini-3.5-flash-lite",
314
306
  messages="Who are you?"
315
307
  )
316
308
  # "I am ConfamNode, Nigeria's AI inference gateway..."
317
309
 
318
310
  # Override with your own system message
319
311
  ansa = client.gist(
320
- model="confam-speed",
312
+ model="gemini/gemini-3.5-flash-lite",
321
313
  messages="Who are you?",
322
314
  system="You are a helpful customer service agent for Konga."
323
315
  )
324
316
 
325
317
  # Disable system message entirely
326
318
  ansa = client.gist(
327
- model="confam-speed",
319
+ model="gemini/gemini-3.5-flash-lite",
328
320
  messages="Who you be?",
329
321
  system=None
330
322
  )
@@ -341,14 +333,14 @@ Pass `cache=True` to let the gateway serve and store a cached response — usefu
341
333
  ```python
342
334
  # Default — caching off, fresh response every call
343
335
  ansa = client.gist(
344
- model="confam-speed",
336
+ model="deepseek/deepseek-v4.1-flash",
345
337
  messages="How you dey?"
346
338
  )
347
339
 
348
340
  # Enable caching — the gateway may return a stored response for a
349
341
  # matching request, and store this one for next time
350
342
  ansa = client.gist(
351
- model="confam-speed",
343
+ model="deepseek/deepseek-v4.1-flash",
352
344
  messages="How you dey?",
353
345
  cache=True
354
346
  )
@@ -362,25 +354,31 @@ Caching must be enabled for your account for `cache=True` to take effect. A cach
362
354
 
363
355
  ## Reasoning Models
364
356
 
357
+ - nvidia/nemotron-3-super-120b-a12b:free
358
+ - nvidia/nemotron-3-ultra-550b-a55b:free
359
+ - gemini/gemini-3.1-flash-lite
360
+ - gemini/gemini-3.5-flash-lite
361
+ - deepseek/deepseek-v4.1-flash
362
+
365
363
  Enable extended thinking for complex problems:
366
364
 
367
365
  ```python
368
366
  ansa = client.gist(
369
- model="confam-reasoning",
367
+ model="nvidia/nemotron-3-ultra-550b-a55b:free",
370
368
  messages="One trader buy goods for ₦50,000 sell am for ₦75,000. After e pay ₦5,000 for transport and ₦3,000 for market, wetin be the real profit? Show how you calculate am.",
371
369
  reasoning_effort="low"
372
- # one of: "xhigh", "high", "medium", "low", "minimal", "none"
370
+ # one of: "high", "medium", "low", "minimal", "none"
373
371
  )
374
372
 
375
373
  print(ansa.reasoning) # thinking trace
376
374
  print(ansa.text) # final answer
377
375
  ```
378
376
 
379
- Also available on `confam-deep-reasoning` for more complex multi-step problems:
377
+ Also available on reasoning models for more complex multi-step problems:
380
378
 
381
379
  ```python
382
380
  ansa = client.gist(
383
- model="confam-deep-reasoning",
381
+ model="nvidia/nemotron-3-ultra-550b-a55b:free",
384
382
  messages="Analyse the financial risk of a Nigerian fintech expanding to Ghana...",
385
383
  reasoning_effort="high"
386
384
  )
@@ -389,58 +387,50 @@ print(ansa.reasoning) # full thinking trace
389
387
  print(ansa.text) # final analysis
390
388
  ```
391
389
 
392
- ### Controlling reasoning mode (`confam-local`)
393
-
394
- `confam-local` reasons in `<think>` blocks by default. To disable this per-request, pass `enable_thinking` nested under `chat_template_kwargs` via `extra_body` — this must be nested this way rather than passed as a top-level kwarg, or it will be silently ignored:
395
-
396
- ```python
397
- result = client.gist(
398
- model="confam-local",
399
- messages="How you dey?",
400
- extra_body={"chat_template_kwargs": {"enable_thinking": False}}
401
- )
402
- ```
403
-
404
390
  ---
405
391
 
406
- ## RAG (Retrieval-Augmented Generation)
407
-
408
- ### Best models for RAG
409
-
410
- | Model | Why | Context |
411
- |---|---|---|
412
- | `confam-intelligence` | General RAG, reliable, long context | 1M tokens |
413
- | `confam-code` | Code search, documentation RAG | 1M tokens |
414
- | `confam-deep-reasoning` | Complex RAG, multi-hop reasoning | 1M tokens |
415
-
416
- `confam-embed-local` pairs well with any of the above for retrieval — see [Embeddings](#embeddings).
417
-
418
- ---
419
-
420
- ## Data Residency
421
-
422
- Nigerian businesses handling sensitive data can use local models that run entirely on Nigerian hardware — data is never transmitted abroad:
392
+ ## Working with Images
423
393
 
424
394
  ```python
395
+ def encode_image_b64(image_path: Path) -> tuple[str, str]:
396
+ """Returns (base64_data, mime_type)."""
397
+ mime = "image/jpeg"
398
+ suffix = image_path.suffix.lower()
399
+ if suffix == ".png":
400
+ mime = "image/png"
401
+ elif suffix == ".webp":
402
+ mime = "image/webp"
403
+ elif suffix in (".jpg", ".jpeg"):
404
+ mime = "image/jpeg"
405
+ data = base64.b64encode(image_path.read_bytes()).decode("utf-8")
406
+ return data, mime
407
+
408
+ image_path = Path("<image_path>")
409
+ img_b64, mime = encode_image_b64(image_path)
410
+
411
+ messages = [
412
+ {
413
+ "role": "user",
414
+ "content": [
415
+ {"type": "text", "text": "Describe this image"},
416
+ {
417
+ "type": "image_url",
418
+ "image_url": {"url": f"data:{mime};base64,{img_b64}"}
419
+ }
420
+ ],
421
+ },
422
+ ]
423
+
425
424
  ansa = client.gist(
426
- model="confam-local",
427
- messages="Analyse this sensitive document..."
425
+ model="gemini/gemini-3.5-flash-lite",
426
+ messages=messages
428
427
  )
429
428
 
430
- print(ansa.is_local) # True — runs on Nigerian hardware
431
- print(ansa.is_ngn_data_residency) # True — data never leaves Nigeria
429
+ if ansa.reasoning:
430
+ print(f"***Reasoning Start***\n{ansa.reasoning}\n***Reasoning End***")
432
431
  print(ansa.text)
433
432
  ```
434
433
 
435
- For health information use cases, `confam-health` offers the same data-residency guarantee on a model tuned for that domain.
436
-
437
- **Ideal for:**
438
- - Nigerian banks and fintechs
439
- - Healthcare companies
440
- - Law firms
441
- - Government agencies
442
- - Any business with strict data residency requirements
443
-
444
434
  ---
445
435
 
446
436
  ## Environment Variable
@@ -484,7 +474,7 @@ from confamnode import (
484
474
 
485
475
  try:
486
476
  ansa = client.gist(
487
- model="confam-speed",
477
+ model="gemini/gemini-3.5-flash-lite",
488
478
  messages="How you dey?"
489
479
  )
490
480
  except ConfamAuthError:
@@ -507,6 +497,260 @@ All specific exceptions above are subclasses of `ConfamNodeError` — catching t
507
497
 
508
498
  ---
509
499
 
500
+ ## REST API
501
+
502
+ ConfamNode provides an OpenAI-compatible REST API that you can call from any programming language or HTTP client without installing the ConfamNode SDK.
503
+
504
+ **Base URL:** `https://api.confamnode.com/v1`
505
+
506
+ ### Authentication
507
+
508
+ Set your API key as an environment variable:
509
+
510
+ ```bash
511
+ export CONFAMNODE_API_KEY="confam-xxx"
512
+ ```
513
+
514
+ All requests require Bearer-token authentication and a JSON content type.
515
+
516
+ ---
517
+
518
+ ### 1. Chat Completions
519
+
520
+ **Endpoint:** `POST https://api.confamnode.com/v1/chat/completions`
521
+
522
+ #### cURL
523
+
524
+ ```bash
525
+ curl -X POST https://api.confamnode.com/v1/chat/completions \
526
+ -H "Authorization: Bearer $CONFAMNODE_API_KEY" \
527
+ -H "Content-Type: application/json" \
528
+ -d '{
529
+ "model": "gemini/gemini-3.5-flash-lite",
530
+ "messages": [
531
+ {
532
+ "role": "user",
533
+ "content": "How you dey?"
534
+ }
535
+ ]
536
+ }'
537
+ ```
538
+
539
+ #### Python — HTTPX (Synchronous)
540
+
541
+ Install HTTPX:
542
+
543
+ ```bash
544
+ pip install httpx
545
+ ```
546
+
547
+ ```python
548
+ import os
549
+ import httpx
550
+
551
+ response = httpx.post(
552
+ "https://api.confamnode.com/v1/chat/completions",
553
+ headers={
554
+ "Authorization": f"Bearer {os.environ['CONFAMNODE_API_KEY']}",
555
+ "Content-Type": "application/json",
556
+ },
557
+ json={
558
+ "model": "gemini/gemini-3.5-flash-lite",
559
+ "messages": [
560
+ {"role": "user", "content": "How you dey?"}
561
+ ],
562
+ },
563
+ timeout=60.0,
564
+ )
565
+
566
+ response.raise_for_status()
567
+ ansa = response.json()
568
+
569
+ print(ansa["choices"][0]["message"]["content"])
570
+ ```
571
+
572
+ #### Python — HTTPX (Asynchronous)
573
+
574
+ Use `httpx.AsyncClient` when working with async applications, such as FastAPI services or asynchronous workers.
575
+
576
+ ```python
577
+ import os
578
+ import asyncio
579
+ import httpx
580
+
581
+ async def main():
582
+ async with httpx.AsyncClient(timeout=60.0) as client:
583
+ response = await client.post(
584
+ "https://api.confamnode.com/v1/chat/completions",
585
+ headers={
586
+ "Authorization": f"Bearer {os.environ['CONFAMNODE_API_KEY']}",
587
+ "Content-Type": "application/json",
588
+ },
589
+ json={
590
+ "model": "gemini/gemini-3.5-flash-lite",
591
+ "messages": [
592
+ {"role": "user", "content": "How you dey?"}
593
+ ],
594
+ },
595
+ )
596
+
597
+ response.raise_for_status()
598
+ ansa = response.json()
599
+
600
+ print(ansa["choices"][0]["message"]["content"])
601
+
602
+ asyncio.run(main())
603
+ ```
604
+
605
+ **Note:** In an existing async application, use `await main()` or await the request from your existing async function instead of calling `asyncio.run()`.
606
+
607
+ #### JavaScript — Fetch API
608
+
609
+ Works in modern browsers and Node.js environments that support `fetch`. This example uses Node.js environment variables.
610
+
611
+ ```javascript
612
+ const response = await fetch(
613
+ "https://api.confamnode.com/v1/chat/completions",
614
+ {
615
+ method: "POST",
616
+ headers: {
617
+ Authorization: `Bearer ${process.env.CONFAMNODE_API_KEY}`,
618
+ "Content-Type": "application/json",
619
+ },
620
+ body: JSON.stringify({
621
+ model: "gemini/gemini-3.5-flash-lite",
622
+ messages: [
623
+ { role: "user", content: "How you dey?" },
624
+ ],
625
+ }),
626
+ }
627
+ );
628
+
629
+ if (!response.ok) {
630
+ throw new Error(
631
+ `HTTP ${response.status}: ${await response.text()}`
632
+ );
633
+ }
634
+
635
+ const ansa = await response.json();
636
+ console.log(ansa.choices[0].message.content);
637
+ ```
638
+
639
+ ---
640
+
641
+ ### 2. Embeddings
642
+
643
+ Generate vector embeddings for semantic search, retrieval-augmented generation (RAG), and other machine-learning applications.
644
+
645
+ **Endpoint:** `POST https://api.confamnode.com/v1/embeddings`
646
+
647
+ #### cURL
648
+
649
+ ```bash
650
+ curl -X POST https://api.confamnode.com/v1/embeddings \
651
+ -H "Authorization: Bearer $CONFAMNODE_API_KEY" \
652
+ -H "Content-Type: application/json" \
653
+ -d '{
654
+ "model": "liquid/lfm-2.5-embedding-350m:free",
655
+ "input": "How you dey?"
656
+ }'
657
+ ```
658
+
659
+ #### Python — HTTPX (Synchronous)
660
+
661
+ ```python
662
+ import os
663
+ import httpx
664
+
665
+ response = httpx.post(
666
+ "https://api.confamnode.com/v1/embeddings",
667
+ headers={
668
+ "Authorization": f"Bearer {os.environ['CONFAMNODE_API_KEY']}",
669
+ "Content-Type": "application/json",
670
+ },
671
+ json={
672
+ "model": "liquid/lfm-2.5-embedding-350m:free",
673
+ "input": "How you dey?",
674
+ },
675
+ timeout=60.0,
676
+ )
677
+
678
+ response.raise_for_status()
679
+ result = response.json()
680
+
681
+ print(result)
682
+ ```
683
+
684
+ #### Python — HTTPX (Asynchronous)
685
+
686
+ ```python
687
+ import os
688
+ import asyncio
689
+ import httpx
690
+
691
+ async def main():
692
+ async with httpx.AsyncClient(timeout=60.0) as client:
693
+ response = await client.post(
694
+ "https://api.confamnode.com/v1/embeddings",
695
+ headers={
696
+ "Authorization": f"Bearer {os.environ['CONFAMNODE_API_KEY']}",
697
+ "Content-Type": "application/json",
698
+ },
699
+ json={
700
+ "model": "liquid/lfm-2.5-embedding-350m:free",
701
+ "input": "How you dey?",
702
+ },
703
+ )
704
+
705
+ response.raise_for_status()
706
+ result = response.json()
707
+
708
+ print(result)
709
+
710
+ asyncio.run(main())
711
+ ```
712
+
713
+ #### JavaScript — Fetch API
714
+
715
+ ```javascript
716
+ const response = await fetch(
717
+ "https://api.confamnode.com/v1/embeddings",
718
+ {
719
+ method: "POST",
720
+ headers: {
721
+ Authorization: `Bearer ${process.env.CONFAMNODE_API_KEY}`,
722
+ "Content-Type": "application/json",
723
+ },
724
+ body: JSON.stringify({
725
+ model: "liquid/lfm-2.5-embedding-350m:free",
726
+ input: "How you dey?",
727
+ }),
728
+ }
729
+ );
730
+
731
+ if (!response.ok) {
732
+ throw new Error(
733
+ `HTTP ${response.status}: ${await response.text()}`
734
+ );
735
+ }
736
+
737
+ const result = await response.json();
738
+ console.log(result);
739
+ ```
740
+
741
+ ---
742
+
743
+ ### Notes
744
+
745
+ - **Authentication:** Include your API key in the `Authorization: Bearer` header for every request.
746
+ - **Content type:** Send JSON requests using `Content-Type: application/json`.
747
+ - **Synchronous vs. asynchronous:** Use `httpx.post()` for synchronous code and `httpx.AsyncClient` with `await` for asynchronous code.
748
+ - **API key security:** Never expose your API key in public repositories or browser-side code. For frontend applications, make authenticated requests through your backend.
749
+ - **No SDK required:** These examples call the REST API directly.
750
+ - **Pricing:** Applicable API charges are calculated in Nigerian Naira (₦).
751
+
752
+ ---
753
+
510
754
  ## Private AI Deployment
511
755
 
512
756
  Need data-residential private AI on your own infrastructure?