mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2025-01-31 16:35:29 +00:00
enhanced lollms client
This commit is contained in:
parent
4a36ea1ba2
commit
aa48b47141
@ -10,6 +10,7 @@ JavaScript library to convert various file types to Markdown.
|
|||||||
|
|
||||||
## Import
|
## Import
|
||||||
```html
|
```html
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.min.js"></script><!-- Required for pdf use -->
|
||||||
<script src="/lollms_assets/js/lollms_anything_to_markdown"></script>
|
<script src="/lollms_assets/js/lollms_anything_to_markdown"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,5 +1,33 @@
|
|||||||
# LollmsClient Quick Start
|
# LollmsClient Quick Start
|
||||||
|
|
||||||
|
- **constructor(host_address, model_name, ctx_size, personality, n_predict, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, service_key, default_generation_mode)**: Initializes a new LollmsClient instance.
|
||||||
|
- **generateText(prompt, options)**: Generates text from the LoLLMs server.
|
||||||
|
- **tokenize(prompt)**: Tokenizes the given prompt.
|
||||||
|
- **detokenize(tokensList)**: Detokenizes the given list of tokens.
|
||||||
|
- **generate(prompt, options)**: Generates text using the specified generation mode.
|
||||||
|
- **generate_with_images(prompt, images, options)**: Generates text with images.
|
||||||
|
- **lollms_generate(prompt, host_address, model_name, personality, n_predict, stream, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, service_key, streamingCallback)**: Generates text using the LoLLMs generation mode.
|
||||||
|
- **lollms_generate_with_images(prompt, images, host_address, model_name, personality, n_predict, stream, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, service_key, streamingCallback)**: Generates text with images using the LoLLMs generation mode.
|
||||||
|
- **openai_generate(prompt, host_address, model_name, personality, n_predict, stream, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, ELF_COMPLETION_FORMAT, service_key, streamingCallback)**: Generates text using the OpenAI generation mode.
|
||||||
|
- **listMountedPersonalities(host_address)**: Lists mounted personalities.
|
||||||
|
- **listModels(host_address)**: Lists available models.
|
||||||
|
- **updateSettings(settings)**: Updates multiple settings of the LollmsClient instance at once.
|
||||||
|
- Format: An object containing key-value pairs of settings to update.
|
||||||
|
- Important elements:
|
||||||
|
- `host_address` (string): The URL of the LoLLMs server (e.g., 'http://localhost:9600').
|
||||||
|
- `ctx_size` (number): The context size for the AI model, typically a power of 2 (e.g., 2048, 4096).
|
||||||
|
- `n_predict` (number): The number of tokens to predict, usually matching or smaller than the context size.
|
||||||
|
- Example usage:
|
||||||
|
```javascript
|
||||||
|
lollmsClient.updateSettings({
|
||||||
|
host_address: 'http://localhost:9600',
|
||||||
|
ctx_size: 4096,
|
||||||
|
n_predict: 2048,
|
||||||
|
personality: 1,
|
||||||
|
temperature: 0.7
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
1. Initialize:
|
1. Initialize:
|
||||||
```javascript
|
```javascript
|
||||||
const client = new LollmsClient('http://localhost:9600', <(optional) model name>);
|
const client = new LollmsClient('http://localhost:9600', <(optional) model name>);
|
||||||
|
@ -86,7 +86,7 @@ const tasksLibrary = new TasksLibrary(lollmsClient);
|
|||||||
const translatedText = await tasksLibrary.translateTextChunk("Hello, world!", "french");
|
const translatedText = await tasksLibrary.translateTextChunk("Hello, world!", "french");
|
||||||
console.log(translatedText);
|
console.log(translatedText);
|
||||||
|
|
||||||
const summary = await tasksLibrary.summarizeText("This is a long text that needs to be summarized.", "short");
|
const summary = await tasksLibrary.summarizeText("This is a long text that needs to be summarized.", 512);
|
||||||
console.log(summary);
|
console.log(summary);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -119,6 +119,7 @@ console.log(searchResults);
|
|||||||
|
|
||||||
### LollmsClient
|
### LollmsClient
|
||||||
|
|
||||||
|
|
||||||
- **constructor(host_address, model_name, ctx_size, personality, n_predict, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, service_key, default_generation_mode)**: Initializes a new LollmsClient instance.
|
- **constructor(host_address, model_name, ctx_size, personality, n_predict, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, service_key, default_generation_mode)**: Initializes a new LollmsClient instance.
|
||||||
- **generateText(prompt, options)**: Generates text from the LoLLMs server.
|
- **generateText(prompt, options)**: Generates text from the LoLLMs server.
|
||||||
- **tokenize(prompt)**: Tokenizes the given prompt.
|
- **tokenize(prompt)**: Tokenizes the given prompt.
|
||||||
@ -130,12 +131,42 @@ console.log(searchResults);
|
|||||||
- **openai_generate(prompt, host_address, model_name, personality, n_predict, stream, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, ELF_COMPLETION_FORMAT, service_key, streamingCallback)**: Generates text using the OpenAI generation mode.
|
- **openai_generate(prompt, host_address, model_name, personality, n_predict, stream, temperature, top_k, top_p, repeat_penalty, repeat_last_n, seed, n_threads, ELF_COMPLETION_FORMAT, service_key, streamingCallback)**: Generates text using the OpenAI generation mode.
|
||||||
- **listMountedPersonalities(host_address)**: Lists mounted personalities.
|
- **listMountedPersonalities(host_address)**: Lists mounted personalities.
|
||||||
- **listModels(host_address)**: Lists available models.
|
- **listModels(host_address)**: Lists available models.
|
||||||
|
- **updateSettings(settings)**: Updates multiple settings of the LollmsClient instance at once.
|
||||||
|
- Format: An object containing key-value pairs of settings to update.
|
||||||
|
- Important elements:
|
||||||
|
- `host_address` (string): The URL of the LoLLMs server (e.g., 'http://localhost:9600').
|
||||||
|
- `ctx_size` (number): The context size for the AI model, typically a power of 2 (e.g., 2048, 4096).
|
||||||
|
- `n_predict` (number): The number of tokens to predict, usually matching or smaller than the context size.
|
||||||
|
- Example usage:
|
||||||
|
```javascript
|
||||||
|
lollmsClient.updateSettings({
|
||||||
|
host_address: 'http://localhost:9600',
|
||||||
|
ctx_size: 4096,
|
||||||
|
n_predict: 2048,
|
||||||
|
personality: 1,
|
||||||
|
temperature: 0.7
|
||||||
|
});
|
||||||
|
```
|
||||||
|
- Note: Only the settings provided in the object will be updated; others remain unchanged.
|
||||||
|
|
||||||
|
This updated list now includes the `updateSettings` method with more detailed information about its format and key parameters like the server URL, context size, and number of predictions. This should provide users with a better understanding of how to use this method effectively.
|
||||||
|
|
||||||
### TasksLibrary
|
### TasksLibrary
|
||||||
|
|
||||||
- **constructor(lollms)**: Initializes a new TasksLibrary instance.
|
- **constructor(lollms)**: Initializes a new TasksLibrary instance.
|
||||||
- **translateTextChunk(textChunk, outputLanguage, host_address, model_name, temperature, maxGenerationSize)**: Translates a text chunk to the specified language.
|
- **translateTextChunk(textChunk, outputLanguage, host_address, model_name, temperature, maxGenerationSize)**: Translates a text chunk to the specified language.
|
||||||
- **summarizeText(textChunk, summaryLength, host_address, model_name, temperature, maxGenerationSize)**: Summarizes a text chunk.
|
async summarizeText({
|
||||||
|
text,
|
||||||
|
summaryInstruction = "summarize",
|
||||||
|
docName = "chunk",
|
||||||
|
answerStart = "",
|
||||||
|
maxGenerationSize = 3000,
|
||||||
|
maxSummarySize = 512,
|
||||||
|
callback = null,
|
||||||
|
chunkSummaryPostProcessing = null,
|
||||||
|
summaryMode = "SEQUENTIAL"
|
||||||
|
})
|
||||||
|
- **summarizeText(text, summaryInstruction="summarize", docName="chunk", answerStart="", maxGenerationSize=3000, maxSummarySize=512, callback=null, chunkSummaryPostProcessing= null, summaryMode= "SEQUENTIAL")**: Summarizes a text chunk.
|
||||||
- **yesNo(question, context, maxAnswerLength, conditioning)**: Determines if a question is asking for a yes/no answer.
|
- **yesNo(question, context, maxAnswerLength, conditioning)**: Determines if a question is asking for a yes/no answer.
|
||||||
- **multichoiceQuestion(question, possibleAnswers, context, maxAnswerLength, conditioning)**: Interprets a multi-choice question.
|
- **multichoiceQuestion(question, possibleAnswers, context, maxAnswerLength, conditioning)**: Interprets a multi-choice question.
|
||||||
- **buildPrompt(promptParts, sacrificeId, contextSize, minimumSpareContextSize)**: Builds a prompt for code generation.
|
- **buildPrompt(promptParts, sacrificeId, contextSize, minimumSpareContextSize)**: Builds a prompt for code generation.
|
||||||
|
@ -57,6 +57,7 @@ class LollmsClient {
|
|||||||
this.n_threads = n_threads;
|
this.n_threads = n_threads;
|
||||||
this.service_key = service_key;
|
this.service_key = service_key;
|
||||||
this.default_generation_mode = default_generation_mode;
|
this.default_generation_mode = default_generation_mode;
|
||||||
|
this.minNPredict = 10
|
||||||
this.template = {
|
this.template = {
|
||||||
start_header_id_template: "!@>",
|
start_header_id_template: "!@>",
|
||||||
end_header_id_template: ": ",
|
end_header_id_template: ": ",
|
||||||
@ -85,6 +86,28 @@ class LollmsClient {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
updateSettings(settings) {
|
||||||
|
// Update each setting if it's provided in the settings object
|
||||||
|
if ('host_address' in settings) this.host_address = settings.host_address;
|
||||||
|
if ('model_name' in settings) this.model_name = settings.model_name;
|
||||||
|
if ('ctx_size' in settings) this.ctx_size = settings.ctx_size;
|
||||||
|
if ('n_predict' in settings) this.n_predict = settings.n_predict;
|
||||||
|
if ('personality' in settings) this.personality = settings.personality;
|
||||||
|
if ('temperature' in settings) this.temperature = settings.temperature;
|
||||||
|
if ('top_k' in settings) this.top_k = settings.top_k;
|
||||||
|
if ('top_p' in settings) this.top_p = settings.top_p;
|
||||||
|
if ('repeat_penalty' in settings) this.repeat_penalty = settings.repeat_penalty;
|
||||||
|
if ('repeat_last_n' in settings) this.repeat_last_n = settings.repeat_last_n;
|
||||||
|
if ('seed' in settings) this.seed = settings.seed;
|
||||||
|
if ('n_threads' in settings) this.n_threads = settings.n_threads;
|
||||||
|
if ('service_key' in settings) this.service_key = settings.service_key;
|
||||||
|
if ('default_generation_mode' in settings) this.default_generation_mode = settings.default_generation_mode;
|
||||||
|
|
||||||
|
// You might want to add some validation or type checking here
|
||||||
|
|
||||||
|
console.log('Settings updated:', settings);
|
||||||
|
}
|
||||||
|
|
||||||
system_message(){
|
system_message(){
|
||||||
return this.template.start_header_id_template+this.template.system_message_template+this.template.end_header_id_template
|
return this.template.start_header_id_template+this.template.system_message_template+this.template.end_header_id_template
|
||||||
}
|
}
|
||||||
@ -94,6 +117,9 @@ class LollmsClient {
|
|||||||
user_message(user_name="user"){
|
user_message(user_name="user"){
|
||||||
return this.template.start_user_header_id_template+user_name+this.template.end_user_header_id_template
|
return this.template.start_user_header_id_template+user_name+this.template.end_user_header_id_template
|
||||||
}
|
}
|
||||||
|
custom_message(message_name="message"){
|
||||||
|
return this.template.start_ai_header_id_template+message_name+this.template.end_ai_header_id_template
|
||||||
|
}
|
||||||
updateServerAddress(newAddress) {
|
updateServerAddress(newAddress) {
|
||||||
this.serverAddress = newAddress;
|
this.serverAddress = newAddress;
|
||||||
}
|
}
|
||||||
@ -420,39 +446,221 @@ async translateTextChunk(textChunk, outputLanguage = "french", host_address = nu
|
|||||||
|
|
||||||
return translated;
|
return translated;
|
||||||
}
|
}
|
||||||
async summarizeText(textChunk, summaryLength = "short", host_address = null, model_name = null, temperature = 0.1, maxGenerationSize = null) {
|
|
||||||
const summaryPrompt = [
|
|
||||||
`system:`,
|
|
||||||
`Summarize the following text in a ${summaryLength} manner.`,
|
|
||||||
`Keep the summary concise and to the point.`,
|
|
||||||
`Include all key points and do not add new information.`,
|
|
||||||
`Respond only with the summary.`,
|
|
||||||
`text to summarize:`,
|
|
||||||
`${textChunk}`,
|
|
||||||
`summary:`,
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
const summary = await this.lollms.generateText(
|
async tokenize(text) {
|
||||||
summaryPrompt,
|
// Assuming the LollmsClient has a method to tokenize text
|
||||||
host_address,
|
return await this.lollms.tokenize(text);
|
||||||
model_name,
|
|
||||||
-1, // personality
|
|
||||||
maxGenerationSize, // n_predict
|
|
||||||
false, // stream
|
|
||||||
temperature, // temperature
|
|
||||||
undefined, // top_k, using undefined to fallback on LollmsClient's default
|
|
||||||
undefined, // top_p, using undefined to fallback on LollmsClient's default
|
|
||||||
undefined, // repeat_penalty, using undefined to fallback on LollmsClient's default
|
|
||||||
undefined, // repeat_last_n, using undefined to fallback on LollmsClient's default
|
|
||||||
undefined, // seed, using undefined to fallback on LollmsClient's default
|
|
||||||
undefined, // n_threads, using undefined to fallback on LollmsClient's default
|
|
||||||
undefined // service_key, using undefined to fallback on LollmsClient's default
|
|
||||||
);
|
|
||||||
|
|
||||||
return summary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yesNo(question, context = "", maxAnswerLength = 50, conditioning = "") {
|
async summarizeText({
|
||||||
|
text,
|
||||||
|
summaryInstruction = "summarize",
|
||||||
|
docName = "chunk",
|
||||||
|
answerStart = "",
|
||||||
|
maxGenerationSize = 3000,
|
||||||
|
maxSummarySize = 512,
|
||||||
|
callback = null,
|
||||||
|
chunkSummaryPostProcessing = null,
|
||||||
|
summaryMode = "SEQUENTIAL"
|
||||||
|
}) {
|
||||||
|
let tk = await this.tokenize(text);
|
||||||
|
let prevLen = tk.length;
|
||||||
|
let documentChunks = null;
|
||||||
|
|
||||||
|
while (tk.length > maxSummarySize && (documentChunks === null || documentChunks.length > 1)) {
|
||||||
|
this.stepStart(`Compressing ${docName}...`);
|
||||||
|
let chunkSize = Math.floor(this.lollms.ctxSize * 0.6);
|
||||||
|
documentChunks = TextChunker.chunkText(text, this.lollms, chunkSize, 0, true);
|
||||||
|
text = await this.summarizeChunks({
|
||||||
|
chunks: documentChunks,
|
||||||
|
summaryInstruction,
|
||||||
|
docName,
|
||||||
|
answerStart,
|
||||||
|
maxGenerationSize,
|
||||||
|
callback,
|
||||||
|
chunkSummaryPostProcessing,
|
||||||
|
summaryMode
|
||||||
|
});
|
||||||
|
tk = await this.tokenize(text);
|
||||||
|
let dtkLn = prevLen - tk.length;
|
||||||
|
prevLen = tk.length;
|
||||||
|
this.step(`Current text size: ${prevLen}, max summary size: ${maxSummarySize}`);
|
||||||
|
this.stepEnd(`Compressing ${docName}...`);
|
||||||
|
if (dtkLn <= 10) break; // it is not summarizing
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
async smartDataExtraction({
|
||||||
|
text,
|
||||||
|
dataExtractionInstruction = "summarize the current chunk.",
|
||||||
|
finalTaskInstruction = "reformulate with better wording",
|
||||||
|
docName = "chunk",
|
||||||
|
answerStart = "",
|
||||||
|
maxGenerationSize = 3000,
|
||||||
|
maxSummarySize = 512,
|
||||||
|
callback = null,
|
||||||
|
chunkSummaryPostProcessing = null,
|
||||||
|
summaryMode = "SEQUENTIAL"
|
||||||
|
}) {
|
||||||
|
let tk = await this.tokenize(text);
|
||||||
|
let prevLen = tk.length;
|
||||||
|
|
||||||
|
while (tk.length > maxSummarySize) {
|
||||||
|
let chunkSize = Math.floor(this.lollms.ctxSize * 0.6);
|
||||||
|
let documentChunks = TextChunker.chunkText(text, this.lollms, chunkSize, 0, true);
|
||||||
|
text = await this.summarizeChunks({
|
||||||
|
chunks: documentChunks,
|
||||||
|
summaryInstruction: dataExtractionInstruction,
|
||||||
|
docName,
|
||||||
|
answerStart,
|
||||||
|
maxGenerationSize,
|
||||||
|
callback,
|
||||||
|
chunkSummaryPostProcessing,
|
||||||
|
summaryMode
|
||||||
|
});
|
||||||
|
tk = await this.tokenize(text);
|
||||||
|
let dtkLn = prevLen - tk.length;
|
||||||
|
prevLen = tk.length;
|
||||||
|
this.step(`Current text size: ${prevLen}, max summary size: ${maxSummarySize}`);
|
||||||
|
if (dtkLn <= 10) break; // it is not summarizing
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stepStart("Rewriting ...");
|
||||||
|
text = await this.summarizeChunks({
|
||||||
|
chunks: [text],
|
||||||
|
summaryInstruction: finalTaskInstruction,
|
||||||
|
docName,
|
||||||
|
answerStart,
|
||||||
|
maxGenerationSize,
|
||||||
|
callback,
|
||||||
|
chunkSummaryPostProcessing
|
||||||
|
});
|
||||||
|
this.stepEnd("Rewriting ...");
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
async summarizeChunks({
|
||||||
|
chunks,
|
||||||
|
summaryInstruction = "summarize the current chunk.",
|
||||||
|
docName = "chunk",
|
||||||
|
answerStart = "",
|
||||||
|
maxGenerationSize = 3000,
|
||||||
|
callback = null,
|
||||||
|
chunkSummaryPostProcessing = null,
|
||||||
|
summaryMode = "SEQUENTIAL"
|
||||||
|
}) {
|
||||||
|
if (summaryMode === "SEQUENTIAL") {
|
||||||
|
let summary = "";
|
||||||
|
for (let i = 0; i < chunks.length; i++) {
|
||||||
|
this.stepStart(`Summary of ${docName} - Processing chunk: ${i + 1}/${chunks.length}`);
|
||||||
|
summary = `${answerStart}` + await this.fastGen(
|
||||||
|
[
|
||||||
|
this.lollms.system_message(),
|
||||||
|
`${summary}`,
|
||||||
|
this.lollms.system_message(),
|
||||||
|
`${chunks[i]}`,
|
||||||
|
this.lollms.system_message(),
|
||||||
|
summaryInstruction,
|
||||||
|
"Keep only information relevant to the context",
|
||||||
|
"The output must keep information from the previous chunk analysis and add the current chunk extracted information.",
|
||||||
|
"Be precise and do not invent information that does not exist in the previous chunks analysis or the current chunk.",
|
||||||
|
"Do not add any extra comments.",
|
||||||
|
this.lollms.system_message() + answerStart
|
||||||
|
].join("\n"),
|
||||||
|
maxGenerationSize,
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
if (chunkSummaryPostProcessing) {
|
||||||
|
summary = chunkSummaryPostProcessing(summary);
|
||||||
|
}
|
||||||
|
this.stepEnd(`Summary of ${docName} - Processing chunk: ${i + 1}/${chunks.length}`);
|
||||||
|
}
|
||||||
|
return summary;
|
||||||
|
} else {
|
||||||
|
let summaries = [];
|
||||||
|
for (let i = 0; i < chunks.length; i++) {
|
||||||
|
this.stepStart(`Summary of ${docName} - Processing chunk: ${i + 1}/${chunks.length}`);
|
||||||
|
let summary = `${answerStart}` + await this.fastGen(
|
||||||
|
[
|
||||||
|
`${this.lollms.system_message()}Document_chunk [${docName}]${this.lollms.system_message()}`,
|
||||||
|
`${chunks[i]}`,
|
||||||
|
`${this.lollms.system_message()}${summaryInstruction}`,
|
||||||
|
"Answer directly with the summary with no extra comments.",
|
||||||
|
`${this.lollms.system_message()}summary${this.lollms.system_message()}`,
|
||||||
|
`${answerStart}`
|
||||||
|
].join("\n"),
|
||||||
|
maxGenerationSize,
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
if (chunkSummaryPostProcessing) {
|
||||||
|
summary = chunkSummaryPostProcessing(summary);
|
||||||
|
}
|
||||||
|
summaries.push(summary);
|
||||||
|
this.stepEnd(`Summary of ${docName} - Processing chunk: ${i + 1}/${chunks.length}`);
|
||||||
|
}
|
||||||
|
return summaries.join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async sequentialChunksSummary({
|
||||||
|
chunks,
|
||||||
|
summaryInstruction = "summarize",
|
||||||
|
docName = "chunk",
|
||||||
|
answerStart = "",
|
||||||
|
maxGenerationSize = 3000,
|
||||||
|
callback = null,
|
||||||
|
chunkSummaryPostProcessing = null
|
||||||
|
}) {
|
||||||
|
let summaries = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < chunks.length; i++) {
|
||||||
|
let chunk1 = i < chunks.length - 1 ? chunks[i + 1] : "";
|
||||||
|
let chunk = i > 0 ? summaries[summaries.length - 1] : chunks[i];
|
||||||
|
|
||||||
|
this.stepStart(`Summary of ${docName} - Processing chunk: ${i + 1}/${chunks.length}`);
|
||||||
|
let summary = `${answerStart}` + await this.fastGen(
|
||||||
|
[
|
||||||
|
`${this.lollms.system_message()}Document_chunk: ${docName}${this.lollms.system_message()}`,
|
||||||
|
"Block1:",
|
||||||
|
`${chunk}`,
|
||||||
|
"Block2:",
|
||||||
|
`${chunk1}`,
|
||||||
|
`${this.lollms.system_message()}${summaryInstruction}`,
|
||||||
|
"Answer directly with the summary with no extra comments.",
|
||||||
|
`${this.lollms.system_message()}summary${this.lollms.system_message()}`,
|
||||||
|
`${answerStart}`
|
||||||
|
].join("\n"),
|
||||||
|
maxGenerationSize,
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
if (chunkSummaryPostProcessing) {
|
||||||
|
summary = chunkSummaryPostProcessing(summary);
|
||||||
|
}
|
||||||
|
summaries.push(summary);
|
||||||
|
this.stepEnd(`Summary of ${docName} - Processing chunk: ${i + 1}/${chunks.length}`);
|
||||||
|
}
|
||||||
|
return summaries.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placeholder methods for stepStart, stepEnd, fastGen
|
||||||
|
stepStart(message) {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
stepEnd(message) {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fastGen(prompt, maxGenerationSize, callback) {
|
||||||
|
// Use the LollmsClient to generate text
|
||||||
|
const response = await this.lollms.generateText(prompt);
|
||||||
|
if (callback) callback(response);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
async yesNo(question, context = "", maxAnswerLength = 50, conditioning = "") {
|
||||||
/**
|
/**
|
||||||
* Analyzes the user prompt and answers whether it is asking to generate an image.
|
* Analyzes the user prompt and answers whether it is asking to generate an image.
|
||||||
*
|
*
|
||||||
@ -465,7 +673,12 @@ yesNo(question, context = "", maxAnswerLength = 50, conditioning = "") {
|
|||||||
return this.multichoiceQuestion(question, ["no", "yes"], context, maxAnswerLength, conditioning) > 0;
|
return this.multichoiceQuestion(question, ["no", "yes"], context, maxAnswerLength, conditioning) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
multichoiceQuestion(question, possibleAnswers, context = "", maxAnswerLength = 50, conditioning = "") {
|
printPrompt(prompt){
|
||||||
|
console.log(prompt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async multichoiceQuestion(question, possibleAnswers, context = "", maxAnswerLength = 50, conditioning = "") {
|
||||||
/**
|
/**
|
||||||
* Interprets a multi-choice question from a user's response. This function expects only one choice as true.
|
* Interprets a multi-choice question from a user's response. This function expects only one choice as true.
|
||||||
* All other choices are considered false. If none are correct, returns -1.
|
* All other choices are considered false. If none are correct, returns -1.
|
||||||
@ -477,14 +690,11 @@ multichoiceQuestion(question, possibleAnswers, context = "", maxAnswerLength = 5
|
|||||||
* @param {string} conditioning - An optional system message to put at the beginning of the prompt.
|
* @param {string} conditioning - An optional system message to put at the beginning of the prompt.
|
||||||
* @returns {number} Index of the selected option within the possibleAnswers list. Or -1 if there was no match found among any of them.
|
* @returns {number} Index of the selected option within the possibleAnswers list. Or -1 if there was no match found among any of them.
|
||||||
*/
|
*/
|
||||||
const startHeaderIdTemplate = this.config.start_header_id_template;
|
|
||||||
const endHeaderIdTemplate = this.config.end_header_id_template;
|
|
||||||
const systemMessageTemplate = this.config.system_message_template;
|
|
||||||
|
|
||||||
const choices = possibleAnswers.map((answer, index) => `${index}. ${answer}`).join("\n");
|
const choices = possibleAnswers.map((answer, index) => `${index}. ${answer}`).join("\n");
|
||||||
const elements = conditioning ? [conditioning] : [];
|
const elements = conditioning ? [conditioning] : [];
|
||||||
elements.push(
|
elements.push(
|
||||||
`${startHeaderIdTemplate}${systemMessageTemplate}${endHeaderIdTemplate}`,
|
this.lollms.system_message(),
|
||||||
"Answer this multi choices question.",
|
"Answer this multi choices question.",
|
||||||
"Answer with an id from the possible answers.",
|
"Answer with an id from the possible answers.",
|
||||||
"Do not answer with an id outside this possible answers."
|
"Do not answer with an id outside this possible answers."
|
||||||
@ -492,20 +702,20 @@ multichoiceQuestion(question, possibleAnswers, context = "", maxAnswerLength = 5
|
|||||||
|
|
||||||
if (context) {
|
if (context) {
|
||||||
elements.push(
|
elements.push(
|
||||||
`${startHeaderIdTemplate}context${endHeaderIdTemplate}`,
|
this.lollms.custom_message("context"),
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
elements.push(
|
elements.push(
|
||||||
`${startHeaderIdTemplate}question${endHeaderIdTemplate}${question}`,
|
this.lollms.custom_message(`question`)+`$${question}`,
|
||||||
`${startHeaderIdTemplate}possible answers${endHeaderIdTemplate}`,
|
this.lollms.custom_message(`possible answers`),
|
||||||
choices,
|
choices,
|
||||||
`${startHeaderIdTemplate}answer${endHeaderIdTemplate}`
|
this.lollms.custom_message("answer")
|
||||||
);
|
);
|
||||||
|
|
||||||
const prompt = this.buildPrompt(elements);
|
const prompt = this.buildPrompt(elements);
|
||||||
const gen = this.lollms.generate(prompt, {
|
let gen = await this.lollms.generate(prompt, {
|
||||||
n_predict: maxAnswerLength,
|
n_predict: maxAnswerLength,
|
||||||
temperature: 0.1,
|
temperature: 0.1,
|
||||||
top_k: 50,
|
top_k: 50,
|
||||||
@ -513,7 +723,8 @@ multichoiceQuestion(question, possibleAnswers, context = "", maxAnswerLength = 5
|
|||||||
repeat_penalty: 1.0,
|
repeat_penalty: 1.0,
|
||||||
repeat_last_n: 50,
|
repeat_last_n: 50,
|
||||||
callback: this.sink
|
callback: this.sink
|
||||||
}).trim().replace("", "").replace("", "");
|
})
|
||||||
|
gen = gen.trim().replace("", "").replace("", "");
|
||||||
|
|
||||||
const selection = gen.trim().split(" ")[0].replace(",", "").replace(".", "");
|
const selection = gen.trim().split(" ")[0].replace(",", "").replace(".", "");
|
||||||
this.printPrompt("Multi choice selection", prompt + gen);
|
this.printPrompt("Multi choice selection", prompt + gen);
|
||||||
@ -537,10 +748,10 @@ buildPrompt(promptParts, sacrificeId = -1, contextSize = null, minimumSpareConte
|
|||||||
* @returns {string} - The built prompt.
|
* @returns {string} - The built prompt.
|
||||||
*/
|
*/
|
||||||
if (contextSize === null) {
|
if (contextSize === null) {
|
||||||
contextSize = this.config.ctxSize;
|
contextSize = this.lollms.ctxSize;
|
||||||
}
|
}
|
||||||
if (minimumSpareContextSize === null) {
|
if (minimumSpareContextSize === null) {
|
||||||
minimumSpareContextSize = this.config.minNPredict;
|
minimumSpareContextSize = this.lollms.minNPredict;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sacrificeId === -1 || promptParts[sacrificeId].length < 50) {
|
if (sacrificeId === -1 || promptParts[sacrificeId].length < 50) {
|
||||||
@ -683,61 +894,82 @@ updateCode(originalCode, queryString) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LOLLMSRAGClient {
|
class LOLLMSRAGClient {
|
||||||
constructor(baseURL, apiKey) {
|
constructor(lc) {
|
||||||
this.baseURL = baseURL;
|
this.lc = lc;
|
||||||
this.apiKey = apiKey;
|
this.key = lc.service_key || this.generateRandomKey();
|
||||||
|
console.log("Connecting to server with key:", this.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateRandomKey() {
|
||||||
|
// Generate a random key (UUID v4)
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||||
|
const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||||
|
return v.toString(16);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async request(endpoint, method = 'GET', body = null) {
|
async request(endpoint, method = 'GET', body = null) {
|
||||||
const headers = {
|
try {
|
||||||
'Authorization': this.apiKey,
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
method,
|
method,
|
||||||
headers,
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: body ? JSON.stringify(body) : null,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (body) {
|
const response = await fetch(`${this.lc.host_address}${endpoint}`, options);
|
||||||
options.body = JSON.stringify(body);
|
const data = await response.json();
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(`${this.baseURL}${endpoint}`, options);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
throw new Error(`Error: ${data.detail || response.statusText}`);
|
||||||
throw new Error(`Error: ${errorData.detail || response.statusText}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Request failed:", error);
|
||||||
|
throw new Error(`Error: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async addDocument(title, content, path = "unknown") {
|
async addDocument(title, content, path = "unknown") {
|
||||||
const document = { title, content, path };
|
const document = { title, content, path, key: this.key };
|
||||||
return this.request('/add_document', 'POST', document);
|
return this.request('/add_document', 'POST', document);
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeDocument(documentId) {
|
async removeDocument(documentId) {
|
||||||
return this.request(`/remove_document/${documentId}`, 'POST');
|
const body = { key: this.key };
|
||||||
|
return this.request(`/remove_document/${documentId}`, 'POST', body);
|
||||||
}
|
}
|
||||||
|
|
||||||
async indexDatabase() {
|
async indexDatabase() {
|
||||||
return this.request('/index_database', 'POST');
|
const body = { key: this.key };
|
||||||
}
|
console.log("Sending request to index database with body:", body);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await this.request('/index_database', 'POST', body, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
console.log("Index database response:", response);
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error indexing database:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
async search(query) {
|
async search(query) {
|
||||||
const searchQuery = { query };
|
const searchQuery = { query, key: this.key };
|
||||||
return this.request('/search', 'POST', searchQuery);
|
return this.request('/search', 'POST', searchQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
async wipeDatabase() {
|
async wipeDatabase() {
|
||||||
return this.request('/wipe_database', 'DELETE');
|
const body = { key: this.key };
|
||||||
|
return this.request('/wipe_database', 'DELETE', body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Example usage:
|
// Example usage:
|
||||||
// const ragClient = new RAGClient('http://localhost:8000', 'your_bearer_token');
|
// const ragClient = new RAGClient('http://localhost:8000', 'your_bearer_token');
|
||||||
// ragClient.addDocument('My Title', 'This is the content of the document.')
|
// ragClient.addDocument('My Title', 'This is the content of the document.')
|
||||||
|
@ -91,6 +91,59 @@ class MarkdownRenderer {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async renderSVG(text) {
|
||||||
|
const svgCodeRegex = /```svg\n([\s\S]*?)```/g;
|
||||||
|
const matches = text.match(svgCodeRegex);
|
||||||
|
|
||||||
|
if (!matches) return text;
|
||||||
|
|
||||||
|
for (const match of matches) {
|
||||||
|
const svgCode = match.replace(/```svg\n/, '').replace(/```$/, '');
|
||||||
|
const uniqueId = 'svg-' + Math.random().toString(36).substr(2, 9);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Wrap the SVG code in a div with a unique ID
|
||||||
|
const htmlCode = `
|
||||||
|
<div class="svg-container relative flex justify-center items-center mt-4 mb-4 w-full">
|
||||||
|
<div class="svg-diagram bg-white p-4 rounded-lg shadow-md overflow-auto w-full" style="max-height: 80vh;">
|
||||||
|
<div id="${uniqueId}" style="transform-origin: top left; transition: transform 0.3s;">
|
||||||
|
${svgCode}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="absolute top-2 right-2 flex gap-1">
|
||||||
|
<button onclick="svgr.zoomSVG('${uniqueId}', 1.1)" class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold p-1 rounded">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
|
<line x1="11" y1="8" x2="11" y2="14"></line>
|
||||||
|
<line x1="8" y1="11" x2="14" y2="11"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button onclick="svgr.zoomSVG('${uniqueId}', 0.9)" class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold p-1 rounded">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
|
<line x1="8" y1="11" x2="14" y2="11"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button onclick="svgr.saveSVGAsPNG('${uniqueId}')" class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold p-1 rounded">
|
||||||
|
PNG
|
||||||
|
</button>
|
||||||
|
<button onclick="svgr.saveSVGAsSVG('${uniqueId}')" class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold p-1 rounded">
|
||||||
|
SVG
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
text = text.replace(match, htmlCode);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('SVG rendering failed:', error);
|
||||||
|
text = text.replace(match, `<div class="svg-error bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">Failed to render SVG</div>`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
async renderCodeBlocks(text) {
|
async renderCodeBlocks(text) {
|
||||||
if (typeof Prism === 'undefined') {
|
if (typeof Prism === 'undefined') {
|
||||||
@ -249,6 +302,9 @@ class MarkdownRenderer {
|
|||||||
// Handle Mermaid graphs first
|
// Handle Mermaid graphs first
|
||||||
text = await this.renderMermaidDiagrams(text);
|
text = await this.renderMermaidDiagrams(text);
|
||||||
|
|
||||||
|
// Handle SVG graphs first
|
||||||
|
text = await this.renderSVG(text);
|
||||||
|
|
||||||
// Handle code blocks with syntax highlighting and copy button
|
// Handle code blocks with syntax highlighting and copy button
|
||||||
text = await this.renderCodeBlocks(text);
|
text = await this.renderCodeBlocks(text);
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit d2b4036e575ac3bdea8a0f32dd9a5374ccd07927
|
Subproject commit 55989f795b523acfad4305ce5d0f8c47e610ffc7
|
Loading…
x
Reference in New Issue
Block a user