Update hyperbolic.js

Fixed reasoning in hyperbolic.js
This commit is contained in:
Sweaterdog 2025-02-28 12:07:27 -08:00 committed by GitHub
parent ae7b1d9650
commit a9eadb6ccd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,13 +1,7 @@
// hyperbolic-no-logger.js
import { getKey } from '../utils/keys.js'; import { getKey } from '../utils/keys.js';
export class Hyperbolic {
/*
*
* Yes, this code was written by an Ai. It was written by GPT-o1 and tested :)
*
*/
export class hyperbolic {
constructor(modelName, apiUrl) { constructor(modelName, apiUrl) {
this.modelName = modelName || "deepseek-ai/DeepSeek-V3"; this.modelName = modelName || "deepseek-ai/DeepSeek-V3";
this.apiUrl = apiUrl || "https://api.hyperbolic.xyz/v1/chat/completions"; this.apiUrl = apiUrl || "https://api.hyperbolic.xyz/v1/chat/completions";
@ -24,14 +18,14 @@ export class hyperbolic {
* *
* @param {Array} turns - An array of message objects, e.g. [{role: 'user', content: 'Hi'}]. * @param {Array} turns - An array of message objects, e.g. [{role: 'user', content: 'Hi'}].
* @param {string} systemMessage - The system prompt or instruction. * @param {string} systemMessage - The system prompt or instruction.
* @param {string} stopSeq - A string that represents a stopping sequence, default '***'. * @param {string} stopSeq - A stopping sequence, default '***'.
* @returns {Promise<string>} - The content of the model's reply. * @returns {Promise<string>} - The model's reply.
*/ */
async sendRequest(turns, systemMessage, stopSeq = '***') { async sendRequest(turns, systemMessage, stopSeq = '***') {
// Prepare the messages with a system prompt at the beginning // Prepare the messages with a system prompt at the beginning
const messages = [{ role: 'system', content: systemMessage }, ...turns]; const messages = [{ role: 'system', content: systemMessage }, ...turns];
// Build the request payload (mirroring your original structure) // Build the request payload
const payload = { const payload = {
model: this.modelName, model: this.modelName,
messages: messages, messages: messages,
@ -41,12 +35,18 @@ export class hyperbolic {
stream: false stream: false
}; };
const maxAttempts = 5;
let attempt = 0;
let finalRes = null;
while (attempt < maxAttempts) {
attempt++;
console.log(`Awaiting Hyperbolic API response... (attempt: ${attempt})`);
console.log('Messages:', messages);
let completionContent = null; let completionContent = null;
try { try {
console.log('Awaiting Hyperbolic API response...');
console.log('Messages:', messages);
const response = await fetch(this.apiUrl, { const response = await fetch(this.apiUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -61,31 +61,53 @@ export class hyperbolic {
} }
const data = await response.json(); const data = await response.json();
if ( if (data?.choices?.[0]?.finish_reason === 'length') {
data?.choices?.[0]?.finish_reason &&
data.choices[0].finish_reason === 'length'
) {
throw new Error('Context length exceeded'); throw new Error('Context length exceeded');
} }
completionContent = data?.choices?.[0]?.message?.content || ''; completionContent = data?.choices?.[0]?.message?.content || '';
console.log('Received response from Hyperbolic.'); console.log('Received response from Hyperbolic.');
} catch (err) { } catch (err) {
if ( if (
(err.message === 'Context length exceeded' || (err.message === 'Context length exceeded' || err.code === 'context_length_exceeded') &&
err.code === 'context_length_exceeded') &&
turns.length > 1 turns.length > 1
) { ) {
console.log('Context length exceeded, trying again with a shorter context...'); console.log('Context length exceeded, trying again with a shorter context...');
return await this.sendRequest(turns.slice(1), systemMessage, stopSeq); return await this.sendRequest(turns.slice(1), systemMessage, stopSeq);
} else { } else {
console.log(err); console.error(err);
completionContent = 'My brain disconnected, try again.'; completionContent = 'My brain disconnected, try again.';
} }
} }
return completionContent.replace(/<\|separator\|>/g, '*no response*');
// Check for <think> blocks
const hasOpenTag = completionContent.includes("<think>");
const hasCloseTag = completionContent.includes("</think>");
if ((hasOpenTag && !hasCloseTag)) {
console.warn("Partial <think> block detected. Re-generating...");
continue; // Retry the request
} }
if (hasCloseTag && !hasOpenTag) {
completionContent = '<think>' + completionContent;
}
if (hasOpenTag && hasCloseTag) {
completionContent = completionContent.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
}
finalRes = completionContent.replace(/<\|separator\|>/g, '*no response*');
break; // Valid response obtained—exit loop
}
if (finalRes == null) {
console.warn("Could not get a valid <think> block or normal response after max attempts.");
finalRes = 'I thought too hard, sorry, try again.';
}
return finalRes;
}
async embed(text) { async embed(text) {
throw new Error('Embeddings are not supported by Hyperbolic.'); throw new Error('Embeddings are not supported by Hyperbolic.');
} }