437 lines
11 KiB
Markdown
437 lines
11 KiB
Markdown
# Examples
|
|
|
|
## Basic Usage
|
|
|
|
### Simple Chat
|
|
|
|
```javascript
|
|
import { SecureChatCompletion } from 'nomyo-js';
|
|
|
|
const client = new SecureChatCompletion({ apiKey: process.env.NOMYO_API_KEY });
|
|
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: 'Hello, how are you?' }],
|
|
temperature: 0.7,
|
|
});
|
|
|
|
console.log(response.choices[0].message.content);
|
|
client.dispose();
|
|
```
|
|
|
|
### Chat with System Message
|
|
|
|
```javascript
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [
|
|
{ role: 'system', content: 'You are a concise technical assistant.' },
|
|
{ role: 'user', content: 'What is the capital of France?' },
|
|
],
|
|
temperature: 0.7,
|
|
});
|
|
|
|
console.log(response.choices[0].message.content);
|
|
```
|
|
|
|
---
|
|
|
|
## Security Tiers
|
|
|
|
```javascript
|
|
// Standard — general use (GPU)
|
|
const r1 = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: 'General query' }],
|
|
security_tier: 'standard',
|
|
});
|
|
|
|
// High — sensitive business data
|
|
const r2 = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: 'Review this contract clause...' }],
|
|
security_tier: 'high',
|
|
});
|
|
|
|
// Maximum — HIPAA PHI / classified data (CPU-only)
|
|
const r3 = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: 'Patient record summary...' }],
|
|
security_tier: 'maximum',
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Tool / Function Calling
|
|
|
|
```javascript
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: "What's the weather in Paris?" }],
|
|
tools: [
|
|
{
|
|
type: 'function',
|
|
function: {
|
|
name: 'get_weather',
|
|
description: 'Get weather information for a location',
|
|
parameters: {
|
|
type: 'object',
|
|
properties: {
|
|
location: { type: 'string', description: 'City name' },
|
|
},
|
|
required: ['location'],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
tool_choice: 'auto',
|
|
});
|
|
|
|
const message = response.choices[0].message;
|
|
if (message.tool_calls?.length) {
|
|
const call = message.tool_calls[0];
|
|
const args = JSON.parse(call.function.arguments);
|
|
console.log(`Call ${call.function.name}(location="${args.location}")`);
|
|
// → Call get_weather(location="Paris")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
```javascript
|
|
import {
|
|
SecureChatCompletion,
|
|
AuthenticationError,
|
|
RateLimitError,
|
|
ForbiddenError,
|
|
InvalidRequestError,
|
|
ServerError,
|
|
ServiceUnavailableError,
|
|
APIConnectionError,
|
|
SecurityError,
|
|
} from 'nomyo-js';
|
|
|
|
const client = new SecureChatCompletion({ apiKey: process.env.NOMYO_API_KEY });
|
|
|
|
try {
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: 'Hello' }],
|
|
});
|
|
console.log(response.choices[0].message.content);
|
|
|
|
} catch (err) {
|
|
if (err instanceof AuthenticationError) {
|
|
console.error('Check your API key:', err.message);
|
|
} else if (err instanceof RateLimitError) {
|
|
console.error('Rate limit hit after all retries:', err.message);
|
|
} else if (err instanceof ForbiddenError) {
|
|
console.error('Model not allowed for this security tier:', err.message);
|
|
} else if (err instanceof InvalidRequestError) {
|
|
console.error('Bad request:', err.message, err.errorDetails);
|
|
} else if (err instanceof ServerError || err instanceof ServiceUnavailableError) {
|
|
console.error('Server error after retries:', err.message);
|
|
} else if (err instanceof APIConnectionError) {
|
|
console.error('Network error after retries:', err.message);
|
|
} else if (err instanceof SecurityError) {
|
|
console.error('Security/crypto failure:', err.message);
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Real-World Scenarios
|
|
|
|
### Chat Application with History
|
|
|
|
```javascript
|
|
import { SecureChatCompletion } from 'nomyo-js';
|
|
|
|
class SecureChatApp {
|
|
constructor(apiKey) {
|
|
this.client = new SecureChatCompletion({ apiKey });
|
|
this.history = [];
|
|
}
|
|
|
|
async chat(userMessage) {
|
|
this.history.push({ role: 'user', content: userMessage });
|
|
|
|
const response = await this.client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: this.history,
|
|
temperature: 0.7,
|
|
});
|
|
|
|
const assistantMessage = response.choices[0].message;
|
|
this.history.push({ role: assistantMessage.role, content: assistantMessage.content });
|
|
return assistantMessage.content;
|
|
}
|
|
|
|
dispose() {
|
|
this.client.dispose();
|
|
}
|
|
}
|
|
|
|
const app = new SecureChatApp(process.env.NOMYO_API_KEY);
|
|
|
|
const r1 = await app.chat("What's your name?");
|
|
console.log('Assistant:', r1);
|
|
|
|
const r2 = await app.chat('What did I just ask you?');
|
|
console.log('Assistant:', r2);
|
|
|
|
app.dispose();
|
|
```
|
|
|
|
### Per-Request Base URL Override
|
|
|
|
For multi-tenant setups or testing against different router instances from a single client:
|
|
|
|
```javascript
|
|
const client = new SecureChatCompletion({
|
|
baseUrl: 'https://primary.nomyo.ai:12435',
|
|
apiKey: process.env.NOMYO_API_KEY,
|
|
});
|
|
|
|
// This single request goes to a different router; a temporary client is
|
|
// created, used, and disposed automatically — the main client is unchanged
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: 'Hello from secondary router' }],
|
|
base_url: 'https://secondary.nomyo.ai:12435',
|
|
});
|
|
```
|
|
|
|
### Environment-Based Configuration
|
|
|
|
```javascript
|
|
import 'dotenv/config';
|
|
import { SecureChatCompletion } from 'nomyo-js';
|
|
|
|
const client = new SecureChatCompletion({
|
|
baseUrl: process.env.NOMYO_SERVER_URL ?? 'https://api.nomyo.ai',
|
|
apiKey: process.env.NOMYO_API_KEY,
|
|
keyDir: process.env.NOMYO_KEY_DIR ?? 'client_keys',
|
|
maxRetries: Number(process.env.NOMYO_MAX_RETRIES ?? '2'),
|
|
debug: process.env.NODE_ENV === 'development',
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Batch Processing
|
|
|
|
### Sequential (Rate-Limit-Safe)
|
|
|
|
```javascript
|
|
const queries = [
|
|
'Summarise document A',
|
|
'Summarise document B',
|
|
'Summarise document C',
|
|
];
|
|
|
|
const summaries = [];
|
|
for (const query of queries) {
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: query }],
|
|
});
|
|
summaries.push(response.choices[0].message.content);
|
|
// Optional: add a small delay to stay within rate limits
|
|
await new Promise(r => setTimeout(r, 600));
|
|
}
|
|
```
|
|
|
|
### Concurrent (With Throttling)
|
|
|
|
```javascript
|
|
// Process in batches of 2 (the default rate limit)
|
|
async function batchN(items, batchSize, fn) {
|
|
const results = [];
|
|
for (let i = 0; i < items.length; i += batchSize) {
|
|
const batch = items.slice(i, i + batchSize);
|
|
const batchResults = await Promise.all(batch.map(fn));
|
|
results.push(...batchResults);
|
|
if (i + batchSize < items.length) {
|
|
await new Promise(r => setTimeout(r, 1100)); // wait >1 s between batches
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
const summaries = await batchN(documents, 2, async (doc) => {
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: `Summarise: ${doc}` }],
|
|
});
|
|
return response.choices[0].message.content;
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Thinking Models
|
|
|
|
```javascript
|
|
const response = await client.create({
|
|
model: 'LiquidAI/LFM2.5-1.2B-Thinking',
|
|
messages: [{ role: 'user', content: 'Is 9.9 larger than 9.11?' }],
|
|
});
|
|
|
|
const { content, reasoning_content } = response.choices[0].message;
|
|
console.log('Reasoning:', reasoning_content); // internal chain-of-thought
|
|
console.log('Answer:', content); // final answer to the user
|
|
```
|
|
|
|
---
|
|
|
|
## Browser Usage
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>NOMYO Secure Chat</title>
|
|
</head>
|
|
<body>
|
|
<textarea id="input" placeholder="Ask something..."></textarea>
|
|
<button id="send">Send</button>
|
|
<div id="output"></div>
|
|
|
|
<script type="module">
|
|
import { SecureChatCompletion } from 'https://unpkg.com/nomyo-js/dist/browser/index.js';
|
|
|
|
// In production, proxy through your backend instead of exposing the API key
|
|
const client = new SecureChatCompletion({
|
|
baseUrl: 'https://api.nomyo.ai',
|
|
apiKey: 'your-api-key', // see note above
|
|
});
|
|
|
|
document.getElementById('send').addEventListener('click', async () => {
|
|
const text = document.getElementById('input').value.trim();
|
|
if (!text) return;
|
|
|
|
document.getElementById('output').textContent = 'Thinking...';
|
|
try {
|
|
const response = await client.create({
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages: [{ role: 'user', content: text }],
|
|
});
|
|
document.getElementById('output').textContent =
|
|
response.choices[0].message.content;
|
|
} catch (err) {
|
|
document.getElementById('output').textContent = `Error: ${err.message}`;
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
---
|
|
|
|
## Advanced Key Management
|
|
|
|
### Custom Key Directory
|
|
|
|
```javascript
|
|
const client = new SecureChatCompletion({
|
|
apiKey: process.env.NOMYO_API_KEY,
|
|
keyDir: '/var/lib/myapp/nomyo-keys', // outside project directory
|
|
keyRotationDir: '/var/lib/myapp/nomyo-keys',
|
|
keyRotationPassword: process.env.NOMYO_KEY_PASSWORD,
|
|
});
|
|
```
|
|
|
|
### Generating Keys Manually
|
|
|
|
```javascript
|
|
import { SecureCompletionClient } from 'nomyo-js';
|
|
|
|
const client = new SecureCompletionClient({
|
|
routerUrl: 'https://api.nomyo.ai',
|
|
});
|
|
|
|
// Generate a new 4096-bit key pair and save it with password protection
|
|
await client.generateKeys({
|
|
saveToFile: true,
|
|
keyDir: 'client_keys',
|
|
password: process.env.NOMYO_KEY_PASSWORD,
|
|
});
|
|
|
|
console.log('Keys generated and saved to client_keys/');
|
|
client.dispose();
|
|
```
|
|
|
|
### Loading Keys Explicitly
|
|
|
|
```javascript
|
|
import { SecureCompletionClient } from 'nomyo-js';
|
|
|
|
const client = new SecureCompletionClient({ routerUrl: 'https://api.nomyo.ai' });
|
|
|
|
await client.loadKeys(
|
|
'client_keys/private_key.pem',
|
|
'client_keys/public_key.pem',
|
|
process.env.NOMYO_KEY_PASSWORD
|
|
);
|
|
|
|
// Now send requests using the loaded keys
|
|
const result = await client.sendSecureRequest(
|
|
{ model: 'Qwen/Qwen3-0.6B', messages: [{ role: 'user', content: 'Hello' }] },
|
|
crypto.randomUUID()
|
|
);
|
|
client.dispose();
|
|
```
|
|
|
|
---
|
|
|
|
## Inspecting Memory Protection
|
|
|
|
```javascript
|
|
import { getMemoryProtectionInfo } from 'nomyo-js';
|
|
|
|
const info = getMemoryProtectionInfo();
|
|
|
|
console.log(`Memory method: ${info.method}`); // 'zero-only' or 'mlock'
|
|
console.log(`Can lock: ${info.canLock}`); // true if native addon present
|
|
console.log(`Details: ${info.details}`);
|
|
```
|
|
|
|
---
|
|
|
|
## TypeScript
|
|
|
|
Full type safety out of the box:
|
|
|
|
```typescript
|
|
import {
|
|
SecureChatCompletion,
|
|
ChatCompletionRequest,
|
|
ChatCompletionResponse,
|
|
Message,
|
|
} from 'nomyo-js';
|
|
|
|
const client = new SecureChatCompletion({ apiKey: process.env.NOMYO_API_KEY! });
|
|
|
|
const messages: Message[] = [
|
|
{ role: 'user', content: 'Hello!' },
|
|
];
|
|
|
|
const request: ChatCompletionRequest = {
|
|
model: 'Qwen/Qwen3-0.6B',
|
|
messages,
|
|
temperature: 0.7,
|
|
};
|
|
|
|
const response: ChatCompletionResponse = await client.create(request);
|
|
const content = response.choices[0].message.content;
|
|
|
|
client.dispose();
|
|
```
|