mulmocast-preprocessor 0.1.2 → 0.2.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/lib/cli/commands/process.js +1 -1
- package/lib/cli/commands/profiles.js +1 -1
- package/lib/cli/commands/query.d.ts +15 -0
- package/lib/cli/commands/query.js +31 -0
- package/lib/cli/commands/summarize.js +2 -36
- package/lib/cli/index.js +59 -0
- package/lib/cli/utils.d.ts +9 -0
- package/lib/cli/utils.js +35 -0
- package/lib/core/ai/command/query/index.d.ts +8 -0
- package/lib/core/ai/command/query/index.js +33 -0
- package/lib/core/ai/command/query/prompts.d.ts +14 -0
- package/lib/core/ai/command/query/prompts.js +59 -0
- package/lib/core/ai/command/summarize/index.d.ts +8 -0
- package/lib/core/ai/command/summarize/index.js +33 -0
- package/lib/core/ai/command/summarize/prompts.d.ts +18 -0
- package/lib/core/ai/command/summarize/prompts.js +70 -0
- package/lib/core/ai/llm.d.ts +45 -0
- package/lib/core/ai/llm.js +144 -0
- package/lib/core/llm/index.d.ts +45 -0
- package/lib/core/llm/index.js +144 -0
- package/lib/core/preprocessing/filter.d.ts +14 -0
- package/lib/core/preprocessing/filter.js +30 -0
- package/lib/core/preprocessing/process.d.ts +7 -0
- package/lib/core/preprocessing/process.js +12 -0
- package/lib/core/preprocessing/profiles.d.ts +5 -0
- package/lib/core/preprocessing/profiles.js +38 -0
- package/lib/core/preprocessing/variant.d.ts +6 -0
- package/lib/core/preprocessing/variant.js +26 -0
- package/lib/core/query/index.d.ts +8 -0
- package/lib/core/query/index.js +33 -0
- package/lib/core/query/prompts.d.ts +14 -0
- package/lib/core/query/prompts.js +59 -0
- package/lib/core/summarize/index.js +3 -84
- package/lib/core/summarize/prompts.js +1 -18
- package/lib/index.d.ts +8 -5
- package/lib/index.js +9 -7
- package/lib/types/query.d.ts +30 -0
- package/lib/types/query.js +21 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "fs";
|
|
2
2
|
import { GraphAILogger } from "graphai";
|
|
3
|
-
import { processScript } from "../../core/process.js";
|
|
3
|
+
import { processScript } from "../../core/preprocessing/process.js";
|
|
4
4
|
/**
|
|
5
5
|
* Process script with profile and output result
|
|
6
6
|
*/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LLMProvider } from "../../types/summarize.js";
|
|
2
|
+
interface QueryCommandOptions {
|
|
3
|
+
provider?: LLMProvider;
|
|
4
|
+
model?: string;
|
|
5
|
+
lang?: string;
|
|
6
|
+
systemPrompt?: string;
|
|
7
|
+
verbose?: boolean;
|
|
8
|
+
section?: string;
|
|
9
|
+
tags?: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Query command handler - outputs answer to stdout
|
|
13
|
+
*/
|
|
14
|
+
export declare const queryCommand: (scriptPath: string, question: string, options: QueryCommandOptions) => Promise<void>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { GraphAILogger } from "graphai";
|
|
2
|
+
import { queryScript } from "../../core/ai/command/query/index.js";
|
|
3
|
+
import { loadScript } from "../utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* Query command handler - outputs answer to stdout
|
|
6
|
+
*/
|
|
7
|
+
export const queryCommand = async (scriptPath, question, options) => {
|
|
8
|
+
try {
|
|
9
|
+
const script = await loadScript(scriptPath);
|
|
10
|
+
const result = await queryScript(script, question, {
|
|
11
|
+
provider: options.provider ?? "openai",
|
|
12
|
+
model: options.model,
|
|
13
|
+
lang: options.lang,
|
|
14
|
+
systemPrompt: options.systemPrompt,
|
|
15
|
+
verbose: options.verbose ?? false,
|
|
16
|
+
section: options.section,
|
|
17
|
+
tags: options.tags,
|
|
18
|
+
});
|
|
19
|
+
// Output answer to stdout
|
|
20
|
+
process.stdout.write(result.answer + "\n");
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error instanceof Error) {
|
|
24
|
+
GraphAILogger.error(`Error: ${error.message}`);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
GraphAILogger.error("Unknown error occurred");
|
|
28
|
+
}
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -1,40 +1,6 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
1
|
import { GraphAILogger } from "graphai";
|
|
3
|
-
import { summarizeScript } from "../../core/summarize/index.js";
|
|
4
|
-
|
|
5
|
-
* Check if input is a URL
|
|
6
|
-
*/
|
|
7
|
-
const isUrl = (input) => {
|
|
8
|
-
return input.startsWith("http://") || input.startsWith("https://");
|
|
9
|
-
};
|
|
10
|
-
/**
|
|
11
|
-
* Fetch JSON from URL with timeout
|
|
12
|
-
*/
|
|
13
|
-
const fetchJson = async (url) => {
|
|
14
|
-
const controller = new AbortController();
|
|
15
|
-
const timeout_ms = 30000;
|
|
16
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout_ms);
|
|
17
|
-
try {
|
|
18
|
-
const response = await fetch(url, { signal: controller.signal });
|
|
19
|
-
if (!response.ok) {
|
|
20
|
-
throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
21
|
-
}
|
|
22
|
-
return (await response.json());
|
|
23
|
-
}
|
|
24
|
-
finally {
|
|
25
|
-
clearTimeout(timeoutId);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Load script from file path or URL
|
|
30
|
-
*/
|
|
31
|
-
const loadScript = async (input) => {
|
|
32
|
-
if (isUrl(input)) {
|
|
33
|
-
return fetchJson(input);
|
|
34
|
-
}
|
|
35
|
-
const content = readFileSync(input, "utf-8");
|
|
36
|
-
return JSON.parse(content);
|
|
37
|
-
};
|
|
2
|
+
import { summarizeScript } from "../../core/ai/command/summarize/index.js";
|
|
3
|
+
import { loadScript } from "../utils.js";
|
|
38
4
|
/**
|
|
39
5
|
* Summarize command handler - outputs summary to stdout
|
|
40
6
|
*/
|
package/lib/cli/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
4
4
|
import { processCommand } from "./commands/process.js";
|
|
5
5
|
import { profilesCommand } from "./commands/profiles.js";
|
|
6
6
|
import { summarizeCommand } from "./commands/summarize.js";
|
|
7
|
+
import { queryCommand } from "./commands/query.js";
|
|
7
8
|
yargs(hideBin(process.argv))
|
|
8
9
|
.command("$0 <script>", "Process MulmoScript with profile", (builder) => builder
|
|
9
10
|
.positional("script", {
|
|
@@ -109,6 +110,62 @@ yargs(hideBin(process.argv))
|
|
|
109
110
|
section: argv.section,
|
|
110
111
|
tags,
|
|
111
112
|
});
|
|
113
|
+
})
|
|
114
|
+
.command("query <script> <question>", "Ask a question about the script content", (builder) => builder
|
|
115
|
+
.positional("script", {
|
|
116
|
+
describe: "Path or URL to MulmoScript JSON file",
|
|
117
|
+
type: "string",
|
|
118
|
+
demandOption: true,
|
|
119
|
+
})
|
|
120
|
+
.positional("question", {
|
|
121
|
+
describe: "Question to ask about the script",
|
|
122
|
+
type: "string",
|
|
123
|
+
demandOption: true,
|
|
124
|
+
})
|
|
125
|
+
.option("provider", {
|
|
126
|
+
describe: "LLM provider (openai, anthropic, groq, gemini)",
|
|
127
|
+
type: "string",
|
|
128
|
+
default: "openai",
|
|
129
|
+
})
|
|
130
|
+
.option("model", {
|
|
131
|
+
alias: "m",
|
|
132
|
+
describe: "Model name",
|
|
133
|
+
type: "string",
|
|
134
|
+
})
|
|
135
|
+
.option("lang", {
|
|
136
|
+
alias: "l",
|
|
137
|
+
describe: "Output language (e.g., ja, en, zh)",
|
|
138
|
+
type: "string",
|
|
139
|
+
})
|
|
140
|
+
.option("system-prompt", {
|
|
141
|
+
describe: "Custom system prompt",
|
|
142
|
+
type: "string",
|
|
143
|
+
})
|
|
144
|
+
.option("verbose", {
|
|
145
|
+
describe: "Show detailed progress",
|
|
146
|
+
type: "boolean",
|
|
147
|
+
default: false,
|
|
148
|
+
})
|
|
149
|
+
.option("section", {
|
|
150
|
+
alias: "s",
|
|
151
|
+
describe: "Filter by section name",
|
|
152
|
+
type: "string",
|
|
153
|
+
})
|
|
154
|
+
.option("tags", {
|
|
155
|
+
alias: "t",
|
|
156
|
+
describe: "Filter by tags (comma-separated)",
|
|
157
|
+
type: "string",
|
|
158
|
+
}), (argv) => {
|
|
159
|
+
const tags = argv.tags ? argv.tags.split(",").map((t) => t.trim()) : undefined;
|
|
160
|
+
queryCommand(argv.script, argv.question, {
|
|
161
|
+
provider: argv.provider,
|
|
162
|
+
model: argv.model,
|
|
163
|
+
lang: argv.lang,
|
|
164
|
+
systemPrompt: argv.systemPrompt,
|
|
165
|
+
verbose: argv.verbose,
|
|
166
|
+
section: argv.section,
|
|
167
|
+
tags,
|
|
168
|
+
});
|
|
112
169
|
})
|
|
113
170
|
.example("$0 script.json --profile summary -o summary.json", "Apply summary profile and save to file")
|
|
114
171
|
.example("$0 script.json -p teaser", "Apply teaser profile and output to stdout")
|
|
@@ -120,6 +177,8 @@ yargs(hideBin(process.argv))
|
|
|
120
177
|
.example("$0 summarize script.json --format markdown", "Generate markdown summary")
|
|
121
178
|
.example("$0 summarize script.json -l ja", "Output summary in Japanese")
|
|
122
179
|
.example("$0 summarize https://example.com/script.json", "Summarize from URL")
|
|
180
|
+
.example('$0 query script.json "What is the main topic?"', "Ask a question about the script")
|
|
181
|
+
.example('$0 query script.json "登場人物は?" -l ja', "Query in Japanese")
|
|
123
182
|
.help()
|
|
124
183
|
.alias("h", "help")
|
|
125
184
|
.version()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ExtendedScript } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check if input is a URL
|
|
4
|
+
*/
|
|
5
|
+
export declare const isUrl: (input: string) => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Load script from file path or URL
|
|
8
|
+
*/
|
|
9
|
+
export declare const loadScript: (input: string) => Promise<ExtendedScript>;
|
package/lib/cli/utils.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
/**
|
|
3
|
+
* Check if input is a URL
|
|
4
|
+
*/
|
|
5
|
+
export const isUrl = (input) => {
|
|
6
|
+
return input.startsWith("http://") || input.startsWith("https://");
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Fetch JSON from URL with timeout
|
|
10
|
+
*/
|
|
11
|
+
const fetchJson = async (url) => {
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
const timeout_ms = 30000;
|
|
14
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout_ms);
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
19
|
+
}
|
|
20
|
+
return (await response.json());
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
clearTimeout(timeoutId);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Load script from file path or URL
|
|
28
|
+
*/
|
|
29
|
+
export const loadScript = async (input) => {
|
|
30
|
+
if (isUrl(input)) {
|
|
31
|
+
return fetchJson(input);
|
|
32
|
+
}
|
|
33
|
+
const content = readFileSync(input, "utf-8");
|
|
34
|
+
return JSON.parse(content);
|
|
35
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ExtendedScript } from "../../../../types/index.js";
|
|
2
|
+
import type { QueryOptions, QueryResult } from "../../../../types/query.js";
|
|
3
|
+
/**
|
|
4
|
+
* Main query function - answers a question based on script content
|
|
5
|
+
*/
|
|
6
|
+
export declare const queryScript: (script: ExtendedScript, question: string, options?: Partial<QueryOptions>) => Promise<QueryResult>;
|
|
7
|
+
export type { QueryOptions, QueryResult } from "../../../../types/query.js";
|
|
8
|
+
export { queryOptionsSchema } from "../../../../types/query.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { queryOptionsSchema } from "../../../../types/query.js";
|
|
2
|
+
import { executeLLM, filterScript } from "../../llm.js";
|
|
3
|
+
import { buildUserPrompt, getSystemPrompt } from "./prompts.js";
|
|
4
|
+
/**
|
|
5
|
+
* Main query function - answers a question based on script content
|
|
6
|
+
*/
|
|
7
|
+
export const queryScript = async (script, question, options = {}) => {
|
|
8
|
+
// Validate and apply defaults
|
|
9
|
+
const validatedOptions = queryOptionsSchema.parse(options);
|
|
10
|
+
// Filter script if section/tags specified
|
|
11
|
+
const filteredScript = filterScript(script, validatedOptions);
|
|
12
|
+
const scriptTitle = script.title || "Untitled";
|
|
13
|
+
if (filteredScript.beats.length === 0) {
|
|
14
|
+
return {
|
|
15
|
+
answer: "No content available to answer the question.",
|
|
16
|
+
question,
|
|
17
|
+
scriptTitle,
|
|
18
|
+
beatCount: 0,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// Build prompts
|
|
22
|
+
const systemPrompt = getSystemPrompt(validatedOptions);
|
|
23
|
+
const userPrompt = buildUserPrompt(filteredScript, question);
|
|
24
|
+
// Execute LLM
|
|
25
|
+
const answer = await executeLLM(systemPrompt, userPrompt, validatedOptions, `Querying script "${script.title}" with ${validatedOptions.provider}... Beats: ${filteredScript.beats.length}, Question: ${question}`);
|
|
26
|
+
return {
|
|
27
|
+
answer,
|
|
28
|
+
question,
|
|
29
|
+
scriptTitle,
|
|
30
|
+
beatCount: filteredScript.beats.length,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export { queryOptionsSchema } from "../../../../types/query.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { QueryOptions } from "../../../../types/query.js";
|
|
2
|
+
import type { ExtendedScript } from "../../../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Default system prompt for query
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_SYSTEM_PROMPT = "You are answering questions based on the content provided.\n- Answer based ONLY on the information in the provided content\n- If the answer cannot be found in the content, say so clearly\n- Be concise and direct in your answers\n- Do not make up information that is not in the content";
|
|
7
|
+
/**
|
|
8
|
+
* Get system prompt based on options
|
|
9
|
+
*/
|
|
10
|
+
export declare const getSystemPrompt: (options: QueryOptions) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Build user prompt from script and question
|
|
13
|
+
*/
|
|
14
|
+
export declare const buildUserPrompt: (script: ExtendedScript, question: string) => string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getLanguageName } from "../../llm.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default system prompt for query
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_SYSTEM_PROMPT = `You are answering questions based on the content provided.
|
|
6
|
+
- Answer based ONLY on the information in the provided content
|
|
7
|
+
- If the answer cannot be found in the content, say so clearly
|
|
8
|
+
- Be concise and direct in your answers
|
|
9
|
+
- Do not make up information that is not in the content`;
|
|
10
|
+
/**
|
|
11
|
+
* Get system prompt based on options
|
|
12
|
+
*/
|
|
13
|
+
export const getSystemPrompt = (options) => {
|
|
14
|
+
if (options.systemPrompt) {
|
|
15
|
+
return options.systemPrompt;
|
|
16
|
+
}
|
|
17
|
+
const basePrompt = DEFAULT_SYSTEM_PROMPT;
|
|
18
|
+
// Add language instruction if specified
|
|
19
|
+
if (options.lang) {
|
|
20
|
+
const langName = getLanguageName(options.lang);
|
|
21
|
+
return `${basePrompt}\n- IMPORTANT: Write the answer in ${langName}`;
|
|
22
|
+
}
|
|
23
|
+
return basePrompt;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Build user prompt from script and question
|
|
27
|
+
*/
|
|
28
|
+
export const buildUserPrompt = (script, question) => {
|
|
29
|
+
const parts = [];
|
|
30
|
+
// Add script metadata
|
|
31
|
+
parts.push(`# Script: ${script.title}`);
|
|
32
|
+
parts.push(`Language: ${script.lang}`);
|
|
33
|
+
parts.push("");
|
|
34
|
+
// Collect all text from beats
|
|
35
|
+
const sections = new Map();
|
|
36
|
+
script.beats.forEach((beat, index) => {
|
|
37
|
+
const text = beat.text || "";
|
|
38
|
+
if (!text.trim())
|
|
39
|
+
return;
|
|
40
|
+
const section = beat.meta?.section || "main";
|
|
41
|
+
if (!sections.has(section)) {
|
|
42
|
+
sections.set(section, []);
|
|
43
|
+
}
|
|
44
|
+
sections.get(section).push(`[${index}] ${text}`);
|
|
45
|
+
});
|
|
46
|
+
// Output by section
|
|
47
|
+
sections.forEach((texts, section) => {
|
|
48
|
+
parts.push(`## Section: ${section}`);
|
|
49
|
+
texts.forEach((t) => parts.push(t));
|
|
50
|
+
parts.push("");
|
|
51
|
+
});
|
|
52
|
+
parts.push("");
|
|
53
|
+
parts.push("---");
|
|
54
|
+
parts.push("");
|
|
55
|
+
parts.push(`Question: ${question}`);
|
|
56
|
+
parts.push("");
|
|
57
|
+
parts.push("Answer:");
|
|
58
|
+
return parts.join("\n");
|
|
59
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ExtendedScript } from "../../../../types/index.js";
|
|
2
|
+
import type { SummarizeOptions, SummarizeResult } from "../../../../types/summarize.js";
|
|
3
|
+
/**
|
|
4
|
+
* Main summarize function - generates a summary of the entire script
|
|
5
|
+
*/
|
|
6
|
+
export declare const summarizeScript: (script: ExtendedScript, options?: Partial<SummarizeOptions>) => Promise<SummarizeResult>;
|
|
7
|
+
export type { SummarizeOptions, SummarizeResult, LLMProvider, SummarizeFormat } from "../../../../types/summarize.js";
|
|
8
|
+
export { summarizeOptionsSchema, llmProviderSchema, summarizeFormatSchema } from "../../../../types/summarize.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { summarizeOptionsSchema } from "../../../../types/summarize.js";
|
|
2
|
+
import { executeLLM, filterScript } from "../../llm.js";
|
|
3
|
+
import { buildUserPrompt, getSystemPrompt } from "./prompts.js";
|
|
4
|
+
/**
|
|
5
|
+
* Main summarize function - generates a summary of the entire script
|
|
6
|
+
*/
|
|
7
|
+
export const summarizeScript = async (script, options = {}) => {
|
|
8
|
+
// Validate and apply defaults
|
|
9
|
+
const validatedOptions = summarizeOptionsSchema.parse(options);
|
|
10
|
+
// Filter script if section/tags specified
|
|
11
|
+
const filteredScript = filterScript(script, validatedOptions);
|
|
12
|
+
const scriptTitle = script.title || "Untitled";
|
|
13
|
+
if (filteredScript.beats.length === 0) {
|
|
14
|
+
return {
|
|
15
|
+
summary: "No content to summarize.",
|
|
16
|
+
format: validatedOptions.format,
|
|
17
|
+
scriptTitle,
|
|
18
|
+
beatCount: 0,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// Build prompts
|
|
22
|
+
const systemPrompt = getSystemPrompt(validatedOptions);
|
|
23
|
+
const userPrompt = buildUserPrompt(filteredScript, validatedOptions);
|
|
24
|
+
// Execute LLM
|
|
25
|
+
const summary = await executeLLM(systemPrompt, userPrompt, validatedOptions, `Summarizing script "${script.title}" with ${validatedOptions.provider}... Beats: ${filteredScript.beats.length}, Format: ${validatedOptions.format}`);
|
|
26
|
+
return {
|
|
27
|
+
summary,
|
|
28
|
+
format: validatedOptions.format,
|
|
29
|
+
scriptTitle,
|
|
30
|
+
beatCount: filteredScript.beats.length,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export { summarizeOptionsSchema, llmProviderSchema, summarizeFormatSchema } from "../../../../types/summarize.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SummarizeOptions } from "../../../../types/summarize.js";
|
|
2
|
+
import type { ExtendedScript } from "../../../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Default system prompt for text summary
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_SYSTEM_PROMPT_TEXT = "You are creating a summary based on the content provided.\n- Extract and explain the actual information and knowledge from the content\n- Do NOT describe what the presentation/script is about (avoid phrases like \"this presentation explains...\" or \"the script describes...\")\n- Write as if you are directly explaining the topic to the reader\n- Be concise and informative\n- Output plain text only";
|
|
7
|
+
/**
|
|
8
|
+
* Default system prompt for markdown summary
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_SYSTEM_PROMPT_MARKDOWN = "You are creating a summary based on the content provided.\n- Extract and explain the actual information and knowledge from the content\n- Do NOT describe what the presentation/script is about (avoid phrases like \"this presentation explains...\" or \"the script describes...\")\n- Write as if you are directly explaining the topic to the reader\n- Use markdown formatting (headers, bullet points, etc.)\n- Include a title, key points, and conclusion\n- Output well-formatted markdown";
|
|
11
|
+
/**
|
|
12
|
+
* Build user prompt from entire script
|
|
13
|
+
*/
|
|
14
|
+
export declare const buildUserPrompt: (script: ExtendedScript, options: SummarizeOptions) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Get system prompt based on format and language
|
|
17
|
+
*/
|
|
18
|
+
export declare const getSystemPrompt: (options: SummarizeOptions) => string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { getLanguageName } from "../../llm.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default system prompt for text summary
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_SYSTEM_PROMPT_TEXT = `You are creating a summary based on the content provided.
|
|
6
|
+
- Extract and explain the actual information and knowledge from the content
|
|
7
|
+
- Do NOT describe what the presentation/script is about (avoid phrases like "this presentation explains..." or "the script describes...")
|
|
8
|
+
- Write as if you are directly explaining the topic to the reader
|
|
9
|
+
- Be concise and informative
|
|
10
|
+
- Output plain text only`;
|
|
11
|
+
/**
|
|
12
|
+
* Default system prompt for markdown summary
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_SYSTEM_PROMPT_MARKDOWN = `You are creating a summary based on the content provided.
|
|
15
|
+
- Extract and explain the actual information and knowledge from the content
|
|
16
|
+
- Do NOT describe what the presentation/script is about (avoid phrases like "this presentation explains..." or "the script describes...")
|
|
17
|
+
- Write as if you are directly explaining the topic to the reader
|
|
18
|
+
- Use markdown formatting (headers, bullet points, etc.)
|
|
19
|
+
- Include a title, key points, and conclusion
|
|
20
|
+
- Output well-formatted markdown`;
|
|
21
|
+
/**
|
|
22
|
+
* Build user prompt from entire script
|
|
23
|
+
*/
|
|
24
|
+
export const buildUserPrompt = (script, options) => {
|
|
25
|
+
const parts = [];
|
|
26
|
+
// Add script metadata
|
|
27
|
+
parts.push(`# Script: ${script.title}`);
|
|
28
|
+
parts.push(`Language: ${script.lang}`);
|
|
29
|
+
parts.push("");
|
|
30
|
+
// Collect all text from beats
|
|
31
|
+
const sections = new Map();
|
|
32
|
+
script.beats.forEach((beat, index) => {
|
|
33
|
+
const text = beat.text || "";
|
|
34
|
+
if (!text.trim())
|
|
35
|
+
return;
|
|
36
|
+
const section = beat.meta?.section || "main";
|
|
37
|
+
if (!sections.has(section)) {
|
|
38
|
+
sections.set(section, []);
|
|
39
|
+
}
|
|
40
|
+
sections.get(section).push(`[${index}] ${text}`);
|
|
41
|
+
});
|
|
42
|
+
// Output by section
|
|
43
|
+
sections.forEach((texts, section) => {
|
|
44
|
+
parts.push(`## Section: ${section}`);
|
|
45
|
+
texts.forEach((t) => parts.push(t));
|
|
46
|
+
parts.push("");
|
|
47
|
+
});
|
|
48
|
+
// Add target length if specified
|
|
49
|
+
if (options.targetLengthChars) {
|
|
50
|
+
parts.push(`Target summary length: approximately ${options.targetLengthChars} characters`);
|
|
51
|
+
}
|
|
52
|
+
parts.push("");
|
|
53
|
+
parts.push("Based on the above content, explain the topic directly to the reader:");
|
|
54
|
+
return parts.join("\n");
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Get system prompt based on format and language
|
|
58
|
+
*/
|
|
59
|
+
export const getSystemPrompt = (options) => {
|
|
60
|
+
if (options.systemPrompt) {
|
|
61
|
+
return options.systemPrompt;
|
|
62
|
+
}
|
|
63
|
+
const basePrompt = options.format === "markdown" ? DEFAULT_SYSTEM_PROMPT_MARKDOWN : DEFAULT_SYSTEM_PROMPT_TEXT;
|
|
64
|
+
// Add language instruction if specified
|
|
65
|
+
if (options.lang) {
|
|
66
|
+
const langName = getLanguageName(options.lang);
|
|
67
|
+
return `${basePrompt}\n- IMPORTANT: Write the output in ${langName}`;
|
|
68
|
+
}
|
|
69
|
+
return basePrompt;
|
|
70
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ExtendedScript } from "../../types/index.js";
|
|
2
|
+
import type { LLMProvider } from "../../types/summarize.js";
|
|
3
|
+
/**
|
|
4
|
+
* Base options for LLM operations
|
|
5
|
+
*/
|
|
6
|
+
export interface BaseLLMOptions {
|
|
7
|
+
provider: LLMProvider;
|
|
8
|
+
model?: string;
|
|
9
|
+
temperature?: number;
|
|
10
|
+
maxTokens?: number;
|
|
11
|
+
lang?: string;
|
|
12
|
+
systemPrompt?: string;
|
|
13
|
+
verbose?: boolean;
|
|
14
|
+
section?: string;
|
|
15
|
+
tags?: string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Provider configuration
|
|
19
|
+
*/
|
|
20
|
+
export interface ProviderConfig {
|
|
21
|
+
agentName: string;
|
|
22
|
+
defaultModel: string;
|
|
23
|
+
keyName: string;
|
|
24
|
+
maxTokens?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get provider configuration
|
|
28
|
+
*/
|
|
29
|
+
export declare const getProviderConfig: (provider: LLMProvider) => ProviderConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Get API key for provider
|
|
32
|
+
*/
|
|
33
|
+
export declare const getProviderApiKey: (provider: LLMProvider) => string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Filter script based on options (section, tags)
|
|
36
|
+
*/
|
|
37
|
+
export declare const filterScript: (script: ExtendedScript, options: BaseLLMOptions) => ExtendedScript;
|
|
38
|
+
/**
|
|
39
|
+
* Get language name from code
|
|
40
|
+
*/
|
|
41
|
+
export declare const getLanguageName: (langCode: string) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Execute LLM call with GraphAI
|
|
44
|
+
*/
|
|
45
|
+
export declare const executeLLM: (systemPrompt: string, userPrompt: string, options: BaseLLMOptions, verboseMessage?: string) => Promise<string>;
|