sambanova 1.0.2 → 1.0.4
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.
- package/README.md +48 -4
- package/dist/client.js +21 -4
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +26 -1
- package/package.json +4 -3
- package/src/client.ts +27 -5
- package/src/types.ts +1 -1
- package/src/utils.ts +20 -0
package/README.md
CHANGED
|
@@ -33,14 +33,14 @@ async function textExample() {
|
|
|
33
33
|
console.log(response.choices[0].message.content);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
// Vision analysis
|
|
36
|
+
// Vision analysis (supports online image URLs and local file paths)
|
|
37
37
|
async function visionExample() {
|
|
38
38
|
const response = await client.chat([
|
|
39
39
|
{
|
|
40
40
|
role: 'user',
|
|
41
41
|
content: [
|
|
42
42
|
{ type: 'text', text: 'What is in this image?' },
|
|
43
|
-
{ type: 'image_url', image_url: { url: '
|
|
43
|
+
{ type: 'image_url', image_url: { url: 'https://example.com/sample.jpg' }} // Online image URL
|
|
44
44
|
]
|
|
45
45
|
}
|
|
46
46
|
], {
|
|
@@ -56,7 +56,7 @@ async function visionExample() {
|
|
|
56
56
|
- TypeScript support with full type definitions
|
|
57
57
|
- Error handling and automatic retries
|
|
58
58
|
- Streaming support
|
|
59
|
-
- Vision model integration
|
|
59
|
+
- Vision model integration with **online image URLs** and **local file paths**
|
|
60
60
|
|
|
61
61
|
## Supported Models
|
|
62
62
|
|
|
@@ -71,6 +71,44 @@ async function visionExample() {
|
|
|
71
71
|
- `Meta-Llama-3.2-1B-Instruct`
|
|
72
72
|
- `Meta-Llama-3.2-3B-Instruct`
|
|
73
73
|
|
|
74
|
+
## Vision Model Details
|
|
75
|
+
|
|
76
|
+
The vision models support both **online image URLs** and **local file paths**. The client automatically converts images to base64 format before sending the request.
|
|
77
|
+
|
|
78
|
+
### Online Image URL Example
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
const response = await client.chat([
|
|
82
|
+
{
|
|
83
|
+
role: 'user',
|
|
84
|
+
content: [
|
|
85
|
+
{ type: 'text', text: 'What is in this image?' },
|
|
86
|
+
{ type: 'image_url', image_url: { url: 'https://example.com/sample.jpg' }} // Online URL
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
], {
|
|
90
|
+
model: 'Llama-3.2-11B-Vision-Instruct'
|
|
91
|
+
});
|
|
92
|
+
console.log(response.choices[0].message.content);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Local Image File Example
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const response = await client.chat([
|
|
99
|
+
{
|
|
100
|
+
role: 'user',
|
|
101
|
+
content: [
|
|
102
|
+
{ type: 'text', text: 'What is in this image?' },
|
|
103
|
+
{ type: 'image_url', image_url: { url: './path/to/image.jpg' }} // Local file path
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
], {
|
|
107
|
+
model: 'Llama-3.2-11B-Vision-Instruct'
|
|
108
|
+
});
|
|
109
|
+
console.log(response.choices[0].message.content);
|
|
110
|
+
```
|
|
111
|
+
|
|
74
112
|
## Advanced Usage
|
|
75
113
|
|
|
76
114
|
### Streaming
|
|
@@ -117,4 +155,10 @@ const client = new SambanovaClient('YOUR_API_KEY', {
|
|
|
117
155
|
defaultRetryCount: 3,
|
|
118
156
|
defaultRetryDelay: 1000
|
|
119
157
|
});
|
|
120
|
-
```
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Changes in Vision Model Usage
|
|
161
|
+
|
|
162
|
+
- **Online Image URL Support:** Provide a direct image URL (e.g., `https://example.com/image.jpg`).
|
|
163
|
+
- **Local File Path Support:** Provide a local file path (e.g., `./path/to/image.jpg`).
|
|
164
|
+
- The client automatically processes the image, converting it to base64 format before sending the request.
|
package/dist/client.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SambanovaClient = void 0;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
|
+
const utils_2 = require("./utils");
|
|
6
7
|
class SambanovaClient {
|
|
7
8
|
constructor(apiKey, options = {}) {
|
|
8
9
|
this.apiKey = apiKey;
|
|
@@ -43,16 +44,32 @@ class SambanovaClient {
|
|
|
43
44
|
throw lastError || new Error('Request failed after retries');
|
|
44
45
|
}
|
|
45
46
|
async chat(messages, options = {}) {
|
|
46
|
-
var _a, _b, _c;
|
|
47
|
+
var _a, _b, _c, _d;
|
|
47
48
|
const model = options.model || this.defaultModel;
|
|
49
|
+
if ((0, utils_1.isVisionModel)(model)) {
|
|
50
|
+
for (const msg of messages) {
|
|
51
|
+
if (Array.isArray(msg.content)) {
|
|
52
|
+
for (const content of msg.content) {
|
|
53
|
+
if (content.type === 'image_url' && ((_a = content.image_url) === null || _a === void 0 ? void 0 : _a.url)) {
|
|
54
|
+
try {
|
|
55
|
+
content.image_url.url = await (0, utils_2.getBase64Image)(content.image_url.url);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw new types_1.SambanovaError(`Failed to process image: ${error}`, 400, 'INVALID_IMAGE_FORMAT');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
48
65
|
messages.forEach(msg => (0, utils_1.validateMessage)(msg, (0, utils_1.isVisionModel)(model)));
|
|
49
66
|
const payload = {
|
|
50
67
|
model,
|
|
51
68
|
messages,
|
|
52
|
-
temperature: (
|
|
53
|
-
top_p: (
|
|
69
|
+
temperature: (_b = options.temperature) !== null && _b !== void 0 ? _b : 0.1,
|
|
70
|
+
top_p: (_c = options.top_p) !== null && _c !== void 0 ? _c : 0.1,
|
|
54
71
|
max_tokens: options.max_tokens,
|
|
55
|
-
stream: (
|
|
72
|
+
stream: (_d = options.stream) !== null && _d !== void 0 ? _d : false
|
|
56
73
|
};
|
|
57
74
|
const response = await this.makeRequest('/chat/completions', payload, options.retry_count, payload.stream);
|
|
58
75
|
if (payload.stream && response instanceof Response) {
|
package/dist/utils.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ import { ModelType, ChatMessage } from './types';
|
|
|
2
2
|
export declare const sleep: (ms: number) => Promise<unknown>;
|
|
3
3
|
export declare const isVisionModel: (model: ModelType) => boolean;
|
|
4
4
|
export declare const validateMessage: (message: ChatMessage, isVision: boolean) => void;
|
|
5
|
+
export declare const getBase64Image: (pathOrUrl: string) => Promise<string>;
|
package/dist/utils.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateMessage = exports.isVisionModel = exports.sleep = void 0;
|
|
6
|
+
exports.getBase64Image = exports.validateMessage = exports.isVisionModel = exports.sleep = void 0;
|
|
4
7
|
const types_1 = require("./types");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
5
10
|
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
6
11
|
exports.sleep = sleep;
|
|
7
12
|
const isVisionModel = (model) => {
|
|
@@ -19,3 +24,23 @@ const validateMessage = (message, isVision) => {
|
|
|
19
24
|
}
|
|
20
25
|
};
|
|
21
26
|
exports.validateMessage = validateMessage;
|
|
27
|
+
const getBase64Image = async (pathOrUrl) => {
|
|
28
|
+
try {
|
|
29
|
+
if (pathOrUrl.startsWith('http')) {
|
|
30
|
+
const response = await axios_1.default.get(pathOrUrl, { responseType: 'arraybuffer' });
|
|
31
|
+
const base64Image = Buffer.from(response.data, 'binary').toString('base64');
|
|
32
|
+
const mimeType = response.headers['content-type'];
|
|
33
|
+
return `data:${mimeType};base64,${base64Image}`;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const image = fs_1.default.readFileSync(pathOrUrl);
|
|
37
|
+
const base64Image = image.toString('base64');
|
|
38
|
+
const mimeType = 'image/jpeg';
|
|
39
|
+
return `data:${mimeType};base64,${base64Image}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw new Error(`Failed to process image: ${pathOrUrl}. Error: ${error}`);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
exports.getBase64Image = getBase64Image;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sambanova",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "TypeScript/Javascript client for Sambanova AI API with comprehensive model support",
|
|
5
|
-
"main": "dist/
|
|
6
|
-
"types": "dist/
|
|
5
|
+
"main": "dist/client.js",
|
|
6
|
+
"types": "dist/client.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc",
|
|
9
9
|
"test": "jest",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"author": "Aaditya Srivastava",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"axios": "^1.7.7",
|
|
24
25
|
"node-fetch": "^2.7.0"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
package/src/client.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
SambanovaError
|
|
8
8
|
} from './types';
|
|
9
9
|
|
|
10
|
+
import { getBase64Image } from './utils';
|
|
11
|
+
|
|
10
12
|
export class SambanovaClient {
|
|
11
13
|
private readonly baseUrl: string;
|
|
12
14
|
private readonly defaultModel: ModelType;
|
|
@@ -79,9 +81,29 @@ export class SambanovaClient {
|
|
|
79
81
|
options: ChatOptions = {}
|
|
80
82
|
): Promise<APIResponse> {
|
|
81
83
|
const model = options.model || this.defaultModel;
|
|
82
|
-
|
|
84
|
+
|
|
85
|
+
if (isVisionModel(model)) {
|
|
86
|
+
for (const msg of messages) {
|
|
87
|
+
if (Array.isArray(msg.content)) {
|
|
88
|
+
for (const content of msg.content) {
|
|
89
|
+
if (content.type === 'image_url' && content.image_url?.url) {
|
|
90
|
+
try {
|
|
91
|
+
content.image_url.url = await getBase64Image(content.image_url.url);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
throw new SambanovaError(
|
|
94
|
+
`Failed to process image: ${error}`,
|
|
95
|
+
400,
|
|
96
|
+
'INVALID_IMAGE_FORMAT'
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
83
105
|
messages.forEach(msg => validateMessage(msg, isVisionModel(model)));
|
|
84
|
-
|
|
106
|
+
|
|
85
107
|
const payload = {
|
|
86
108
|
model,
|
|
87
109
|
messages,
|
|
@@ -90,18 +112,18 @@ export class SambanovaClient {
|
|
|
90
112
|
max_tokens: options.max_tokens,
|
|
91
113
|
stream: options.stream ?? false
|
|
92
114
|
};
|
|
93
|
-
|
|
115
|
+
|
|
94
116
|
const response = await this.makeRequest(
|
|
95
117
|
'/chat/completions',
|
|
96
118
|
payload,
|
|
97
119
|
options.retry_count,
|
|
98
120
|
payload.stream
|
|
99
121
|
);
|
|
100
|
-
|
|
122
|
+
|
|
101
123
|
if (payload.stream && response instanceof Response) {
|
|
102
124
|
throw new Error('Stream response received in chat method. Use streamChat instead.');
|
|
103
125
|
}
|
|
104
|
-
|
|
126
|
+
|
|
105
127
|
return response as APIResponse;
|
|
106
128
|
}
|
|
107
129
|
|
package/src/types.ts
CHANGED
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ModelType, ChatMessage, SambanovaError } from './types';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import axios from 'axios';
|
|
2
4
|
|
|
3
5
|
export const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
|
4
6
|
|
|
@@ -22,4 +24,22 @@ export const validateMessage = (message: ChatMessage, isVision: boolean) => {
|
|
|
22
24
|
'INVALID_MESSAGE_FORMAT'
|
|
23
25
|
);
|
|
24
26
|
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const getBase64Image = async (pathOrUrl: string): Promise<string> => {
|
|
30
|
+
try {
|
|
31
|
+
if (pathOrUrl.startsWith('http')) {
|
|
32
|
+
const response = await axios.get(pathOrUrl, { responseType: 'arraybuffer' });
|
|
33
|
+
const base64Image = Buffer.from(response.data, 'binary').toString('base64');
|
|
34
|
+
const mimeType = response.headers['content-type'];
|
|
35
|
+
return `data:${mimeType};base64,${base64Image}`;
|
|
36
|
+
} else {
|
|
37
|
+
const image = fs.readFileSync(pathOrUrl);
|
|
38
|
+
const base64Image = image.toString('base64');
|
|
39
|
+
const mimeType = 'image/jpeg';
|
|
40
|
+
return `data:${mimeType};base64,${base64Image}`;
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
throw new Error(`Failed to process image: ${pathOrUrl}. Error: ${error}`);
|
|
44
|
+
}
|
|
25
45
|
};
|