plugin-docpixie 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.d.ts +1 -0
- package/client.js +1 -0
- package/dist/client/index.js +10 -0
- package/dist/externalVersion.js +17 -0
- package/dist/index.js +48 -0
- package/dist/locale/en-US.json +21 -0
- package/dist/locale/vi-VN.json +21 -0
- package/dist/server/collections/docpixie-config.js +61 -0
- package/dist/server/collections/docpixie-documents.js +71 -0
- package/dist/server/collections/docpixie-pages.js +59 -0
- package/dist/server/exceptions.js +127 -0
- package/dist/server/index.js +49 -0
- package/dist/server/plugin.js +178 -0
- package/dist/server/prompts.js +388 -0
- package/dist/server/providers/index.js +36 -0
- package/dist/server/providers/llm-adapter.js +253 -0
- package/dist/server/services/DocPixieService.js +1300 -0
- package/dist/server/types.js +24 -0
- package/package.json +40 -0
- package/server.d.ts +1 -0
- package/server.js +1 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
var plugin_exports = {};
|
|
38
|
+
__export(plugin_exports, {
|
|
39
|
+
PluginDocPixieServer: () => PluginDocPixieServer,
|
|
40
|
+
default: () => plugin_default
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(plugin_exports);
|
|
43
|
+
var import_server = require("@nocobase/server");
|
|
44
|
+
var import_path = __toESM(require("path"));
|
|
45
|
+
var import_DocPixieService = require("./services/DocPixieService");
|
|
46
|
+
class PluginDocPixieServer extends import_server.Plugin {
|
|
47
|
+
service;
|
|
48
|
+
async afterAdd() {
|
|
49
|
+
}
|
|
50
|
+
async beforeLoad() {
|
|
51
|
+
}
|
|
52
|
+
async load() {
|
|
53
|
+
await this.importCollections(import_path.default.resolve(__dirname, "collections"));
|
|
54
|
+
this.service = new import_DocPixieService.DocPixieService(this.app, this.db, this.app.logger);
|
|
55
|
+
this.registerActions();
|
|
56
|
+
this.setPermissions();
|
|
57
|
+
this.app.on("afterStart", async () => {
|
|
58
|
+
try {
|
|
59
|
+
await this.service.initialize();
|
|
60
|
+
} catch (err) {
|
|
61
|
+
this.app.logger.warn("DocPixie: Service initialization deferred \u2014 configure settings first.", err);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// ═══════════════════════════════════════════
|
|
66
|
+
// REST API Actions
|
|
67
|
+
// ═══════════════════════════════════════════
|
|
68
|
+
registerActions() {
|
|
69
|
+
this.app.resourceManager.define({
|
|
70
|
+
name: "docpixie",
|
|
71
|
+
actions: {
|
|
72
|
+
// GET /api/docpixie:listDocuments
|
|
73
|
+
listDocuments: async (ctx, next) => {
|
|
74
|
+
const { limit, offset, status } = ctx.action.params;
|
|
75
|
+
ctx.body = await this.service.listDocuments({ limit, offset, status });
|
|
76
|
+
await next();
|
|
77
|
+
},
|
|
78
|
+
// GET /api/docpixie:getDocument?filterByTk=<id>
|
|
79
|
+
getDocument: async (ctx, next) => {
|
|
80
|
+
const { filterByTk } = ctx.action.params;
|
|
81
|
+
const doc = await this.service.getDocument(Number(filterByTk));
|
|
82
|
+
if (!doc) {
|
|
83
|
+
ctx.throw(404, "Document not found");
|
|
84
|
+
}
|
|
85
|
+
ctx.body = doc;
|
|
86
|
+
await next();
|
|
87
|
+
},
|
|
88
|
+
// POST /api/docpixie:processDocument
|
|
89
|
+
processDocument: async (ctx, next) => {
|
|
90
|
+
var _a, _b;
|
|
91
|
+
const { filePath, name } = ctx.action.params.values || {};
|
|
92
|
+
if (!filePath) {
|
|
93
|
+
ctx.throw(400, "filePath is required");
|
|
94
|
+
}
|
|
95
|
+
const userId = (_b = (_a = ctx.state) == null ? void 0 : _a.currentUser) == null ? void 0 : _b.id;
|
|
96
|
+
const documentId = await this.service.processDocument(filePath, { name, userId });
|
|
97
|
+
ctx.body = { id: documentId, status: "processing" };
|
|
98
|
+
await next();
|
|
99
|
+
},
|
|
100
|
+
// DELETE /api/docpixie:deleteDocument?filterByTk=<id>
|
|
101
|
+
deleteDocument: async (ctx, next) => {
|
|
102
|
+
const { filterByTk } = ctx.action.params;
|
|
103
|
+
const deleted = await this.service.deleteDocument(Number(filterByTk));
|
|
104
|
+
ctx.body = { deleted };
|
|
105
|
+
await next();
|
|
106
|
+
},
|
|
107
|
+
// POST /api/docpixie:query
|
|
108
|
+
query: async (ctx, next) => {
|
|
109
|
+
const { query, documentIds, strategy, conversationHistory } = ctx.action.params.values || {};
|
|
110
|
+
if (!query) {
|
|
111
|
+
ctx.throw(400, "query is required");
|
|
112
|
+
}
|
|
113
|
+
const result = await this.service.query({
|
|
114
|
+
query,
|
|
115
|
+
documentIds,
|
|
116
|
+
strategy,
|
|
117
|
+
conversationHistory
|
|
118
|
+
});
|
|
119
|
+
ctx.body = result;
|
|
120
|
+
await next();
|
|
121
|
+
},
|
|
122
|
+
// GET /api/docpixie:getConfig
|
|
123
|
+
getConfig: async (ctx, next) => {
|
|
124
|
+
ctx.body = await this.service.getConfig();
|
|
125
|
+
await next();
|
|
126
|
+
},
|
|
127
|
+
// POST /api/docpixie:updateConfig
|
|
128
|
+
updateConfig: async (ctx, next) => {
|
|
129
|
+
const config = ctx.action.params.values || {};
|
|
130
|
+
await this.service.updateConfig(config);
|
|
131
|
+
ctx.body = { ok: true };
|
|
132
|
+
await next();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// ═══════════════════════════════════════════
|
|
138
|
+
// ACL Permissions
|
|
139
|
+
// ═══════════════════════════════════════════
|
|
140
|
+
setPermissions() {
|
|
141
|
+
this.app.acl.registerSnippet({
|
|
142
|
+
name: `pm.${this.name}.docpixie`,
|
|
143
|
+
actions: ["docpixie:*"]
|
|
144
|
+
});
|
|
145
|
+
this.app.acl.allow("docpixie", "listDocuments", "loggedIn");
|
|
146
|
+
this.app.acl.allow("docpixie", "getDocument", "loggedIn");
|
|
147
|
+
this.app.acl.allow("docpixie", "query", "loggedIn");
|
|
148
|
+
this.app.acl.allow("docpixie", "getConfig", "loggedIn");
|
|
149
|
+
}
|
|
150
|
+
// ═══════════════════════════════════════════
|
|
151
|
+
// Lifecycle
|
|
152
|
+
// ═══════════════════════════════════════════
|
|
153
|
+
async install() {
|
|
154
|
+
const configRepo = this.db.getRepository("docpixie_config");
|
|
155
|
+
const existing = await configRepo.findOne({});
|
|
156
|
+
if (!existing) {
|
|
157
|
+
await configRepo.create({
|
|
158
|
+
values: {
|
|
159
|
+
analysisStrategy: "hybrid",
|
|
160
|
+
ocrProvider: "none",
|
|
161
|
+
maxPagesPerTask: 5,
|
|
162
|
+
maxTasksPerPlan: 4
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async afterEnable() {
|
|
168
|
+
}
|
|
169
|
+
async afterDisable() {
|
|
170
|
+
}
|
|
171
|
+
async remove() {
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
var plugin_default = PluginDocPixieServer;
|
|
175
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
176
|
+
0 && (module.exports = {
|
|
177
|
+
PluginDocPixieServer
|
|
178
|
+
});
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var prompts_exports = {};
|
|
28
|
+
__export(prompts_exports, {
|
|
29
|
+
ADAPTIVE_INITIAL_PLANNING_PROMPT: () => ADAPTIVE_INITIAL_PLANNING_PROMPT,
|
|
30
|
+
ADAPTIVE_PLAN_UPDATE_PROMPT: () => ADAPTIVE_PLAN_UPDATE_PROMPT,
|
|
31
|
+
CONVERSATION_SUMMARIZATION_PROMPT: () => CONVERSATION_SUMMARIZATION_PROMPT,
|
|
32
|
+
QUERY_CLASSIFICATION_PROMPT: () => QUERY_CLASSIFICATION_PROMPT,
|
|
33
|
+
QUERY_REFORMULATION_PROMPT: () => QUERY_REFORMULATION_PROMPT,
|
|
34
|
+
SYNTHESIS_PROMPT: () => SYNTHESIS_PROMPT,
|
|
35
|
+
SYSTEM_ADAPTIVE_PLANNER: () => SYSTEM_ADAPTIVE_PLANNER,
|
|
36
|
+
SYSTEM_DIRECT_ANSWER: () => SYSTEM_DIRECT_ANSWER,
|
|
37
|
+
SYSTEM_DOCPIXIE: () => SYSTEM_DOCPIXIE,
|
|
38
|
+
SYSTEM_PAGE_SELECTOR: () => SYSTEM_PAGE_SELECTOR,
|
|
39
|
+
SYSTEM_QUERY_CLASSIFIER: () => SYSTEM_QUERY_CLASSIFIER,
|
|
40
|
+
SYSTEM_QUERY_REFORMULATOR: () => SYSTEM_QUERY_REFORMULATOR,
|
|
41
|
+
SYSTEM_SUMMARIZER: () => SYSTEM_SUMMARIZER,
|
|
42
|
+
SYSTEM_SYNTHESIS: () => SYSTEM_SYNTHESIS,
|
|
43
|
+
SYSTEM_TASK_PLANNER: () => SYSTEM_TASK_PLANNER,
|
|
44
|
+
SYSTEM_VISION_EXPERT: () => SYSTEM_VISION_EXPERT,
|
|
45
|
+
TASK_PROCESSING_PROMPT: () => TASK_PROCESSING_PROMPT,
|
|
46
|
+
TEXT_PAGE_SELECTION_PROMPT: () => TEXT_PAGE_SELECTION_PROMPT,
|
|
47
|
+
VISION_PAGE_SELECTION_PROMPT: () => VISION_PAGE_SELECTION_PROMPT,
|
|
48
|
+
fillPrompt: () => fillPrompt
|
|
49
|
+
});
|
|
50
|
+
module.exports = __toCommonJS(prompts_exports);
|
|
51
|
+
const SYSTEM_DOCPIXIE = `You are DocPixie, an AI assistant that helps users understand and analyze their documents.
|
|
52
|
+
You will be shown actual document pages as images. Analyze these images carefully and provide accurate, helpful responses based on what you see.
|
|
53
|
+
Always cite which documents/pages you're referencing in your response.`;
|
|
54
|
+
const SYSTEM_VISION_EXPERT = "You are a document analysis expert using vision capabilities to analyze document images.";
|
|
55
|
+
const SYSTEM_DIRECT_ANSWER = `You are DocPixie, a helpful AI assistant.
|
|
56
|
+
Answer the user's question directly without referring to any documents.
|
|
57
|
+
Be concise and accurate.`;
|
|
58
|
+
const SYSTEM_SYNTHESIS = `You are DocPixie, an expert at synthesizing complex document analysis results.
|
|
59
|
+
You excel at combining multiple findings into coherent, comprehensive responses that address all aspects of the user's query.`;
|
|
60
|
+
const SYSTEM_SUMMARIZER = "You are a helpful assistant that creates concise summaries.";
|
|
61
|
+
const SYSTEM_QUERY_REFORMULATOR = "You are a query reformulation expert.";
|
|
62
|
+
const SYSTEM_QUERY_CLASSIFIER = "You are a query classification expert. Always respond with valid JSON.";
|
|
63
|
+
const SYSTEM_TASK_PLANNER = `You are an expert task planning assistant specializing in breaking down complex queries.
|
|
64
|
+
You understand how to decompose multi-faceted questions into simpler, focused tasks that can be executed independently.`;
|
|
65
|
+
const SYSTEM_ADAPTIVE_PLANNER = `You are an adaptive task planning agent. Based on new information you gather, you can modify your task plan by adding new tasks, removing unnecessary tasks, or updating existing ones. You are pragmatic and efficient - you stop when you have enough information to answer the user's query.`;
|
|
66
|
+
const SYSTEM_PAGE_SELECTOR = `You are a document page selection expert. You analyze document summaries and page information to select the most relevant pages for answering specific questions using vision analysis.`;
|
|
67
|
+
const TASK_PROCESSING_PROMPT = `You are DocPixie, analyzing specific documents to complete a focused task as part of a larger analysis.
|
|
68
|
+
|
|
69
|
+
CURRENT TASK: {task_description}
|
|
70
|
+
|
|
71
|
+
SEARCH QUERY USED: {search_queries}
|
|
72
|
+
|
|
73
|
+
{memory_summary}
|
|
74
|
+
|
|
75
|
+
ANALYSIS GUIDELINES:
|
|
76
|
+
1. Focus ONLY on information relevant to this specific task
|
|
77
|
+
2. Extract concrete data, facts, and findings from the documents
|
|
78
|
+
3. Be specific - include numbers, dates, names, and other precise details
|
|
79
|
+
4. If the documents don't contain relevant information, clearly state that
|
|
80
|
+
5. Organize your findings in a structured way
|
|
81
|
+
|
|
82
|
+
IMPORTANT:
|
|
83
|
+
- This is one task in a multi-step analysis - stay focused on just this task
|
|
84
|
+
- Your findings will be combined with other task results later
|
|
85
|
+
- Be thorough but concise - extract key information without unnecessary detail
|
|
86
|
+
- Always cite which document pages you're referencing
|
|
87
|
+
|
|
88
|
+
Please analyze the document images below and provide a detailed answer for this specific task.`;
|
|
89
|
+
const SYNTHESIS_PROMPT = `You are DocPixie. Your job is to answer the user's specific question using the analysis results provided.
|
|
90
|
+
|
|
91
|
+
ORIGINAL USER QUERY: {original_query}
|
|
92
|
+
|
|
93
|
+
ANALYSIS RESULTS:
|
|
94
|
+
{results_text}
|
|
95
|
+
|
|
96
|
+
INSTRUCTIONS:
|
|
97
|
+
- Answer ONLY what the user asked
|
|
98
|
+
- Use ONLY information from the analysis results
|
|
99
|
+
- Be conversational and natural in your response
|
|
100
|
+
- Be direct and concise - don't over-explain
|
|
101
|
+
- Never mention sources, citations, documents, or where information came from
|
|
102
|
+
- If the analysis doesn't contain enough information to answer the query, say so clearly
|
|
103
|
+
- Don't add extra context or background unless directly relevant to the query
|
|
104
|
+
- Write as if you naturally know this information
|
|
105
|
+
|
|
106
|
+
Answer the user's question now.`;
|
|
107
|
+
const ADAPTIVE_INITIAL_PLANNING_PROMPT = `You are creating an initial task plan for a document analysis query. Create the MINIMUM number of tasks (1-3) needed to gather distinct information to answer the user's question.
|
|
108
|
+
|
|
109
|
+
TASK CREATION RULES:
|
|
110
|
+
1. Create the FEWEST tasks possible - only create multiple tasks if they require fundamentally different information
|
|
111
|
+
2. Each task should retrieve DISTINCT information that cannot be found together
|
|
112
|
+
3. Avoid creating similar or overlapping tasks
|
|
113
|
+
4. Keep task names clear and under 30 characters
|
|
114
|
+
5. Task descriptions should be specific about what information to retrieve
|
|
115
|
+
6. For each task, specify which documents are most relevant to search
|
|
116
|
+
7. Prefer one comprehensive task over multiple similar tasks
|
|
117
|
+
8. Do not mention the document name in the Task's name or description
|
|
118
|
+
|
|
119
|
+
OUTPUT FORMAT:
|
|
120
|
+
Return a JSON object with a "tasks" array. Each task should have:
|
|
121
|
+
- "name": Short, clear task name
|
|
122
|
+
- "description": Specific description of what single piece of information to find
|
|
123
|
+
- "document": Single document ID that is most relevant for this task
|
|
124
|
+
- Do not add \`\`\`json to your response under any circumstances
|
|
125
|
+
|
|
126
|
+
EXAMPLE 1 (Single Task):
|
|
127
|
+
Query: "What is the current CEO's name?"
|
|
128
|
+
Available Documents:
|
|
129
|
+
doc_1: Company Leadership Directory
|
|
130
|
+
Summary: Contains current organizational chart, executive team profiles, board member information.
|
|
131
|
+
|
|
132
|
+
Output:
|
|
133
|
+
{
|
|
134
|
+
"tasks": [
|
|
135
|
+
{
|
|
136
|
+
"name": "Find Current CEO Name",
|
|
137
|
+
"description": "Locate the name of the current Chief Executive Officer",
|
|
138
|
+
"document": "doc_1"
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
EXAMPLE 2 (Two Distinct Information Sources):
|
|
144
|
+
Query: "How do we implement user authentication and what are the security requirements?"
|
|
145
|
+
Available Documents:
|
|
146
|
+
doc_1: Security Implementation Manual
|
|
147
|
+
doc_2: User Management API Documentation
|
|
148
|
+
|
|
149
|
+
Output:
|
|
150
|
+
{
|
|
151
|
+
"tasks": [
|
|
152
|
+
{
|
|
153
|
+
"name": "Get Auth Implementation",
|
|
154
|
+
"description": "Retrieve technical implementation details for user authentication system",
|
|
155
|
+
"document": "doc_2"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "Get Security Requirements",
|
|
159
|
+
"description": "Retrieve security standards and requirements for authentication",
|
|
160
|
+
"document": "doc_1"
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
----------------
|
|
166
|
+
User's query: {query}
|
|
167
|
+
|
|
168
|
+
AVAILABLE DOCUMENTS:
|
|
169
|
+
{documents}
|
|
170
|
+
----------------
|
|
171
|
+
|
|
172
|
+
Create your initial task plan now. Remember: use the MINIMUM number of tasks needed. Only create multiple tasks if they require fundamentally different information from different sources. Output only valid JSON.`;
|
|
173
|
+
const ADAPTIVE_PLAN_UPDATE_PROMPT = `You are an adaptive agent updating your task plan based on new information. Analyze what you've learned and decide if you need to modify your remaining tasks.
|
|
174
|
+
|
|
175
|
+
DECISION RULES:
|
|
176
|
+
1. CONTINUE UNCHANGED: If you're on track and remaining tasks are still relevant
|
|
177
|
+
2. ADD NEW TASKS: If you discovered you need more specific information
|
|
178
|
+
3. REMOVE TASKS: If completed tasks already answered what remaining tasks were meant to find
|
|
179
|
+
4. MODIFY TASKS: If remaining tasks need to be more focused or different
|
|
180
|
+
|
|
181
|
+
Based on your latest findings, what should you do with your task plan?
|
|
182
|
+
|
|
183
|
+
OUTPUT FORMAT - Choose ONE:
|
|
184
|
+
|
|
185
|
+
Option 1 - Continue unchanged:
|
|
186
|
+
{
|
|
187
|
+
"action": "continue",
|
|
188
|
+
"reason": "Brief explanation why current plan is still good"
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
Option 2 - Add new tasks:
|
|
192
|
+
{
|
|
193
|
+
"action": "add_tasks",
|
|
194
|
+
"reason": "Why new tasks are needed",
|
|
195
|
+
"new_tasks": [
|
|
196
|
+
{
|
|
197
|
+
"name": "Task name",
|
|
198
|
+
"description": "What this new task should find",
|
|
199
|
+
"document": "document_id_to_search"
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
Option 3 - Remove tasks:
|
|
205
|
+
{
|
|
206
|
+
"action": "remove_tasks",
|
|
207
|
+
"reason": "Why these tasks are no longer needed",
|
|
208
|
+
"tasks_to_remove": ["task_id_1", "task_id_2"]
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
Option 4 - Modify tasks:
|
|
212
|
+
{
|
|
213
|
+
"action": "modify_tasks",
|
|
214
|
+
"reason": "Why tasks need to be changed",
|
|
215
|
+
"modified_tasks": [
|
|
216
|
+
{
|
|
217
|
+
"task_id": "existing_task_id",
|
|
218
|
+
"new_name": "Updated name",
|
|
219
|
+
"new_description": "Updated description",
|
|
220
|
+
"new_document": "new_document_id_to_search"
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
----------------
|
|
226
|
+
ORIGINAL QUERY: {original_query}
|
|
227
|
+
|
|
228
|
+
AVAILABLE DOCUMENTS:
|
|
229
|
+
{available_documents}
|
|
230
|
+
|
|
231
|
+
CURRENT TASK PLAN STATUS:
|
|
232
|
+
{current_plan_status}
|
|
233
|
+
|
|
234
|
+
LATEST TASK COMPLETED:
|
|
235
|
+
Task: {completed_task_name}
|
|
236
|
+
Findings: {task_findings}
|
|
237
|
+
|
|
238
|
+
PROGRESS SO FAR:
|
|
239
|
+
{progress_summary}
|
|
240
|
+
----------------
|
|
241
|
+
|
|
242
|
+
Analyze your situation and decide what to do. Output only valid JSON.`;
|
|
243
|
+
const VISION_PAGE_SELECTION_PROMPT = `Analyze these document page images and select the most relevant pages for this query:
|
|
244
|
+
|
|
245
|
+
Look at each page image carefully and determine which pages are most likely to contain information that would help answer the query. Consider:
|
|
246
|
+
1. Text content visible in the page
|
|
247
|
+
2. Charts, graphs, tables, or diagrams that might be relevant
|
|
248
|
+
3. Headers, titles, or section names that relate to the query
|
|
249
|
+
4. Overall page structure and content type
|
|
250
|
+
5. Try to focus on the query and look for the pages that contain the most relevant information only
|
|
251
|
+
6. Do not use more than 5 pages in your selection
|
|
252
|
+
|
|
253
|
+
Select all pages that are relevant - don't limit yourself to a specific number if multiple pages are needed.
|
|
254
|
+
|
|
255
|
+
Return a JSON object with the page numbers that are most relevant:
|
|
256
|
+
{"selected_pages": [1, 3, 7]}
|
|
257
|
+
----------------
|
|
258
|
+
Query: {query}
|
|
259
|
+
Query Description: {query_description}
|
|
260
|
+
----------------
|
|
261
|
+
Output only valid JSON. Here are the page images to analyze:`;
|
|
262
|
+
const TEXT_PAGE_SELECTION_PROMPT = `Given these page summaries, select the most relevant pages for this task:
|
|
263
|
+
|
|
264
|
+
Task: {task_description}
|
|
265
|
+
|
|
266
|
+
Pages:
|
|
267
|
+
{page_summaries}
|
|
268
|
+
|
|
269
|
+
Return ONLY a JSON object: {"selected_pages": [1, 3, 7]}
|
|
270
|
+
Select at most {max_pages} pages. Output only valid JSON.`;
|
|
271
|
+
const QUERY_REFORMULATION_PROMPT = `You are a query reformulation expert. Your task is to resolve references in the current query to make it suitable for document search.
|
|
272
|
+
|
|
273
|
+
Create a reformulated query that:
|
|
274
|
+
1. Resolves pronouns (e.g., "it", "this", "that") to their actual subjects from context
|
|
275
|
+
2. Keeps the query SHORT and focused ONLY on the current question's intent
|
|
276
|
+
3. Does NOT include previous questions or combine multiple intents
|
|
277
|
+
4. Expands unclear abbreviations if needed
|
|
278
|
+
5. If the query is already clear and specific, return it unchanged
|
|
279
|
+
|
|
280
|
+
IMPORTANT RULES:
|
|
281
|
+
- Focus on what the user is asking NOW, not what they asked before
|
|
282
|
+
- Only add context needed to understand references
|
|
283
|
+
- Keep the query concise for optimal document search
|
|
284
|
+
|
|
285
|
+
EXAMPLES:
|
|
286
|
+
|
|
287
|
+
Example 1:
|
|
288
|
+
Context: User asked about "machine learning model performance"
|
|
289
|
+
Current: "What about its accuracy?"
|
|
290
|
+
Output:
|
|
291
|
+
{
|
|
292
|
+
"reformulated_query": "What is the machine learning model accuracy?"
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
Example 2:
|
|
296
|
+
Context: User discussed "2023 quarterly report"
|
|
297
|
+
Current: "Compare it with last year"
|
|
298
|
+
Output:
|
|
299
|
+
{
|
|
300
|
+
"reformulated_query": "Compare 2023 quarterly report with 2022"
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
----------------
|
|
304
|
+
CONVERSATION CONTEXT:
|
|
305
|
+
{conversation_context}
|
|
306
|
+
|
|
307
|
+
RECENT TOPICS: {recent_topics}
|
|
308
|
+
|
|
309
|
+
CURRENT QUERY: {current_query}
|
|
310
|
+
----------------
|
|
311
|
+
|
|
312
|
+
Return a JSON object with the reformulated query. Output only valid JSON.`;
|
|
313
|
+
const QUERY_CLASSIFICATION_PROMPT = `Analyze the user's query and determine if it needs document retrieval to answer.
|
|
314
|
+
|
|
315
|
+
Think about whether this query requires searching through documents to provide a complete answer, or if it can be answered directly without documents.
|
|
316
|
+
|
|
317
|
+
OUTPUT FORMAT:
|
|
318
|
+
{
|
|
319
|
+
"reasoning": "Brief explanation of why this query does or doesn't need documents",
|
|
320
|
+
"needs_documents": true
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
Examples:
|
|
324
|
+
|
|
325
|
+
Query: "What were the Q3 revenues?"
|
|
326
|
+
{
|
|
327
|
+
"reasoning": "This asks for specific financial data that would be found in documents",
|
|
328
|
+
"needs_documents": true
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
Query: "Hello, how are you?"
|
|
332
|
+
{
|
|
333
|
+
"reasoning": "This is a greeting that doesn't require any document information",
|
|
334
|
+
"needs_documents": false
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
Query: "Summarize the main findings"
|
|
338
|
+
{
|
|
339
|
+
"reasoning": "This requires extracting and summarizing information from documents",
|
|
340
|
+
"needs_documents": true
|
|
341
|
+
}
|
|
342
|
+
----------------
|
|
343
|
+
QUERY: {query}
|
|
344
|
+
----------------
|
|
345
|
+
|
|
346
|
+
Analyze and output only valid JSON.`;
|
|
347
|
+
const CONVERSATION_SUMMARIZATION_PROMPT = `Summarize the following conversation, focusing on:
|
|
348
|
+
1. The main topics discussed
|
|
349
|
+
2. Key questions asked by the user
|
|
350
|
+
3. Important information or conclusions
|
|
351
|
+
4. Any unresolved questions or ongoing discussions
|
|
352
|
+
|
|
353
|
+
Keep the summary concise but comprehensive.
|
|
354
|
+
|
|
355
|
+
Conversation:
|
|
356
|
+
{conversation_text}
|
|
357
|
+
|
|
358
|
+
Summary:`;
|
|
359
|
+
function fillPrompt(template, params) {
|
|
360
|
+
let result = template;
|
|
361
|
+
for (const [key, value] of Object.entries(params)) {
|
|
362
|
+
result = result.replace(new RegExp(`\\{${key}\\}`, "g"), value);
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
367
|
+
0 && (module.exports = {
|
|
368
|
+
ADAPTIVE_INITIAL_PLANNING_PROMPT,
|
|
369
|
+
ADAPTIVE_PLAN_UPDATE_PROMPT,
|
|
370
|
+
CONVERSATION_SUMMARIZATION_PROMPT,
|
|
371
|
+
QUERY_CLASSIFICATION_PROMPT,
|
|
372
|
+
QUERY_REFORMULATION_PROMPT,
|
|
373
|
+
SYNTHESIS_PROMPT,
|
|
374
|
+
SYSTEM_ADAPTIVE_PLANNER,
|
|
375
|
+
SYSTEM_DIRECT_ANSWER,
|
|
376
|
+
SYSTEM_DOCPIXIE,
|
|
377
|
+
SYSTEM_PAGE_SELECTOR,
|
|
378
|
+
SYSTEM_QUERY_CLASSIFIER,
|
|
379
|
+
SYSTEM_QUERY_REFORMULATOR,
|
|
380
|
+
SYSTEM_SUMMARIZER,
|
|
381
|
+
SYSTEM_SYNTHESIS,
|
|
382
|
+
SYSTEM_TASK_PLANNER,
|
|
383
|
+
SYSTEM_VISION_EXPERT,
|
|
384
|
+
TASK_PROCESSING_PROMPT,
|
|
385
|
+
TEXT_PAGE_SELECTION_PROMPT,
|
|
386
|
+
VISION_PAGE_SELECTION_PROMPT,
|
|
387
|
+
fillPrompt
|
|
388
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var providers_exports = {};
|
|
28
|
+
__export(providers_exports, {
|
|
29
|
+
NocoBaseLLMAdapter: () => import_llm_adapter.NocoBaseLLMAdapter
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(providers_exports);
|
|
32
|
+
var import_llm_adapter = require("./llm-adapter");
|
|
33
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
34
|
+
0 && (module.exports = {
|
|
35
|
+
NocoBaseLLMAdapter
|
|
36
|
+
});
|