File size: 6,649 Bytes
f8b5d42 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | const { Document } = require("../../../../models/documents");
const { safeJsonParse } = require("../../../http");
const { summarizeContent } = require("../utils/summarize");
const Provider = require("../providers/ai-provider");
const docSummarizer = {
name: "document-summarizer",
startupConfig: {
params: {},
},
plugin: function () {
return {
name: this.name,
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
controller: new AbortController(),
description:
"Can get the list of files available to search with descriptions and can select a single file to open and summarize.",
examples: [
{
prompt: "Summarize example.txt",
call: JSON.stringify({
action: "summarize",
document_filename: "example.txt",
}),
},
{
prompt: "What files can you see?",
call: JSON.stringify({ action: "list", document_filename: null }),
},
{
prompt: "Tell me about readme.md",
call: JSON.stringify({
action: "summarize",
document_filename: "readme.md",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
action: {
type: "string",
enum: ["list", "summarize"],
description:
"The action to take. 'list' will return all files available with their filename and descriptions. 'summarize' will open and summarize the file by the a document name.",
},
document_filename: {
type: "string",
"x-nullable": true,
description:
"The file name of the document you want to get the full content of.",
},
},
additionalProperties: false,
},
handler: async function ({ action, document_filename }) {
if (action === "list") return await this.listDocuments();
if (action === "summarize")
return await this.summarizeDoc(document_filename);
return "There is nothing we can do. This function call returns no information.";
},
/**
* List all documents available in a workspace
* @returns List of files and their descriptions if available.
*/
listDocuments: async function () {
try {
this.super.introspect(
`${this.caller}: Looking at the available documents.`
);
const documents = await Document.where({
workspaceId: this.super.handlerProps.invocation.workspace_id,
});
if (documents.length === 0)
return "No documents found - nothing can be done. Stop.";
this.super.introspect(
`${this.caller}: Found ${documents.length} documents`
);
const foundDocuments = documents.map((doc) => {
const metadata = safeJsonParse(doc.metadata, {});
return {
document_id: doc.docId,
filename: metadata?.title ?? "unknown.txt",
description: metadata?.description ?? "no description",
};
});
return JSON.stringify(foundDocuments);
} catch (error) {
this.super.handlerProps.log(
`document-summarizer.list raised an error. ${error.message}`
);
return `Let the user know this action was not successful. An error was raised while listing available files. ${error.message}`;
}
},
summarizeDoc: async function (filename) {
try {
const availableDocs = safeJsonParse(
await this.listDocuments(),
[]
);
if (!availableDocs.length) {
this.super.handlerProps.log(
`${this.caller}: No available documents to summarize.`
);
return "No documents were found.";
}
const docInfo = availableDocs.find(
(info) => info.filename === filename
);
if (!docInfo) {
this.super.handlerProps.log(
`${this.caller}: No available document by the name "${filename}".`
);
return `No available document by the name "${filename}".`;
}
const document = await Document.content(docInfo.document_id);
this.super.introspect(
`${this.caller}: Grabbing all content for ${
filename ?? "a discovered file."
}`
);
if (!document.content || document.content.length === 0) {
throw new Error(
"This document has no readable content that could be found."
);
}
const { TokenManager } = require("../../../helpers/tiktoken");
if (
new TokenManager(this.super.model).countFromString(
document.content
) < Provider.contextLimit(this.super.provider, this.super.model)
) {
return document.content;
}
this.super.introspect(
`${this.caller}: Summarizing ${filename ?? ""}...`
);
this.super.onAbort(() => {
this.super.handlerProps.log(
"Abort was triggered, exiting summarization early."
);
this.controller.abort();
});
return await summarizeContent({
provider: this.super.provider,
model: this.super.model,
controllerSignal: this.controller.signal,
content: document.content,
});
} catch (error) {
this.super.handlerProps.log(
`document-summarizer.summarizeDoc raised an error. ${error.message}`
);
return `Let the user know this action was not successful. An error was raised while summarizing the file. ${error.message}`;
}
},
});
},
};
},
};
module.exports = {
docSummarizer,
};
|