phonegpu-space / sdk /javascript /m5-client.js
josephrw's picture
Upload folder using huggingface_hub
d958e80 verified
Raw
History Blame Contribute Delete
3.39 kB
/**
* M5 JavaScript SDK
*/
class M5Client {
constructor(apiKey, baseUrl = 'https://m5.hf.space') {
this.apiKey = apiKey;
this.baseUrl = baseUrl.replace(/\/$/, '');
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
}
async chatCompletion(options) {
const {
model,
messages,
temperature = 0.7,
maxTokens = null,
stream = false,
ollamaUrl = null
} = options;
const payload = {
model,
messages,
temperature,
stream
};
if (maxTokens) payload.max_tokens = maxTokens;
if (ollamaUrl) payload.ollama_url = ollamaUrl;
const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
async *chatCompletionStream(options) {
const {
model,
messages,
temperature = 0.7,
maxTokens = null,
ollamaUrl = null
} = options;
const payload = {
model,
messages,
temperature,
stream: true
};
if (maxTokens) payload.max_tokens = maxTokens;
if (ollamaUrl) payload.ollama_url = ollamaUrl;
const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
const lines = chunk.split('\n');
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const data = line.slice(6).trim();
if (data === '[DONE]') break;
try {
const parsed = JSON.parse(data);
if (parsed.choices && parsed.choices[0]) {
const delta = parsed.choices[0].delta;
if (delta && delta.content) {
yield delta.content;
}
}
} catch (e) {
// Skip invalid JSON
}
}
}
}
async listModels() {
const response = await fetch(`${this.baseUrl}/v1/models`, {
headers: this.headers
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.data || [];
}
}
// Convenience classes
class Chat {
constructor(client) {
this.client = client;
}
async create(options) {
return await this.client.chatCompletion(options);
}
async *createStream(options) {
yield* this.client.chatCompletionStream(options);
}
}
class M5 {
constructor(apiKey, baseUrl = 'https://m5.hf.space') {
this.client = new M5Client(apiKey, baseUrl);
this.chat = new Chat(this.client);
}
}
// Export for Node.js
if (typeof module !== 'undefined' && module.exports) {
module.exports = { M5, M5Client, Chat };
}
// Export for browser
if (typeof window !== 'undefined') {
window.M5 = M5;
window.M5Client = M5Client;
window.Chat = Chat;
}