2024-03-12 23:21:27 +01:00
const {
2024-04-30 21:33:42 +02:00
handleDefaultStreamResponseV2 ,
2024-03-12 23:21:27 +01:00
} = require ( "../../helpers/chat/responses" ) ;
2024-01-10 21:35:30 +01:00
function togetherAiModels ( ) {
const { MODELS } = require ( "./models.js" ) ;
return MODELS || { } ;
}
class TogetherAiLLM {
2024-01-17 21:59:25 +01:00
constructor ( embedder = null , modelPreference = null ) {
2024-01-10 21:35:30 +01:00
if ( ! process . env . TOGETHER _AI _API _KEY )
throw new Error ( "No TogetherAI API key was set." ) ;
2024-04-30 21:33:42 +02:00
const { OpenAI : OpenAIApi } = require ( "openai" ) ;
this . openai = new OpenAIApi ( {
baseURL : "https://api.together.xyz/v1" ,
apiKey : process . env . TOGETHER _AI _API _KEY ? ? null ,
2024-01-10 21:35:30 +01:00
} ) ;
2024-01-17 21:59:25 +01:00
this . model = modelPreference || process . env . TOGETHER _AI _MODEL _PREF ;
2024-01-10 21:35:30 +01:00
this . limits = {
history : this . promptWindowLimit ( ) * 0.15 ,
system : this . promptWindowLimit ( ) * 0.15 ,
user : this . promptWindowLimit ( ) * 0.7 ,
} ;
if ( ! embedder )
throw new Error (
"INVALID TOGETHER AI SETUP. No embedding engine has been set. Go to instance settings and set up an embedding interface to use Together AI as your LLM."
) ;
this . embedder = embedder ;
2024-01-17 23:42:05 +01:00
this . defaultTemp = 0.7 ;
2024-01-10 21:35:30 +01:00
}
# appendContext ( contextTexts = [ ] ) {
if ( ! contextTexts || ! contextTexts . length ) return "" ;
return (
"\nContext:\n" +
contextTexts
. map ( ( text , i ) => {
return ` [CONTEXT ${ i } ]: \n ${ text } \n [END CONTEXT ${ i } ] \n \n ` ;
} )
. join ( "" )
) ;
}
allModelInformation ( ) {
return togetherAiModels ( ) ;
}
streamingEnabled ( ) {
2024-05-02 01:52:28 +02:00
return "streamGetChatCompletion" in this ;
2024-01-10 21:35:30 +01:00
}
// Ensure the user set a value for the token limit
// and if undefined - assume 4096 window.
promptWindowLimit ( ) {
const availableModels = this . allModelInformation ( ) ;
return availableModels [ this . model ] ? . maxLength || 4096 ;
}
async isValidChatCompletionModel ( model = "" ) {
const availableModels = this . allModelInformation ( ) ;
return availableModels . hasOwnProperty ( model ) ;
}
constructPrompt ( {
systemPrompt = "" ,
contextTexts = [ ] ,
chatHistory = [ ] ,
userPrompt = "" ,
} ) {
const prompt = {
role : "system" ,
content : ` ${ systemPrompt } ${ this . # appendContext ( contextTexts ) } ` ,
} ;
return [ prompt , ... chatHistory , { role : "user" , content : userPrompt } ] ;
}
async isSafe ( _input = "" ) {
// Not implemented so must be stubbed
return { safe : true , reasons : [ ] } ;
}
async getChatCompletion ( messages = null , { temperature = 0.7 } ) {
if ( ! ( await this . isValidChatCompletionModel ( this . model ) ) )
throw new Error (
` TogetherAI chat: ${ this . model } is not valid for chat completion! `
) ;
2024-04-30 21:33:42 +02:00
const result = await this . openai . chat . completions . create ( {
2024-01-10 21:35:30 +01:00
model : this . model ,
messages ,
temperature ,
} ) ;
2024-04-30 21:33:42 +02:00
if ( ! result . hasOwnProperty ( "choices" ) || result . choices . length === 0 )
return null ;
return result . choices [ 0 ] . message . content ;
2024-01-10 21:35:30 +01:00
}
async streamGetChatCompletion ( messages = null , { temperature = 0.7 } ) {
if ( ! ( await this . isValidChatCompletionModel ( this . model ) ) )
throw new Error (
` TogetherAI chat: ${ this . model } is not valid for chat completion! `
) ;
2024-04-30 21:33:42 +02:00
const streamRequest = await this . openai . chat . completions . create ( {
model : this . model ,
stream : true ,
messages ,
temperature ,
} ) ;
2024-02-07 17:15:14 +01:00
return streamRequest ;
}
handleStream ( response , stream , responseProps ) {
2024-04-30 21:33:42 +02:00
return handleDefaultStreamResponseV2 ( response , stream , responseProps ) ;
2024-01-10 21:35:30 +01:00
}
// Simple wrapper for dynamic embedder & normalize interface for all LLM implementations
async embedTextInput ( textInput ) {
return await this . embedder . embedTextInput ( textInput ) ;
}
async embedChunks ( textChunks = [ ] ) {
return await this . embedder . embedChunks ( textChunks ) ;
}
async compressMessages ( promptArgs = { } , rawHistory = [ ] ) {
const { messageArrayCompressor } = require ( "../../helpers/chat" ) ;
const messageArray = this . constructPrompt ( promptArgs ) ;
return await messageArrayCompressor ( this , messageArray , rawHistory ) ;
}
}
module . exports = {
TogetherAiLLM ,
togetherAiModels ,
} ;