From ec574119922a34b908251362a9195a0161f90bc8 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Mon, 15 Dec 2025 13:53:14 +0100 Subject: [PATCH] Refactor document generation to output HTML format and update system instructions for clarity --- main.js | 2 +- services/modules/llm-chat_gpt/chatgpt.js | 6 +- services/modules/llm-gemini/gemini.js | 75 ++++++++++++++++++++---- services/modules/quen3/quen3.js | 43 ++++++++------ 4 files changed, 93 insertions(+), 33 deletions(-) diff --git a/main.js b/main.js index 39c408d..4f71d81 100644 --- a/main.js +++ b/main.js @@ -183,7 +183,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { // TODO implement documentation module // This code handles the Text to Document processing module call for (let i = 0; i < args.document.styles.length; i++) { - await mapFunctions.get("module-handler").function(args.document.module, {prompt: args.document.styles[i].prompt, transcript: transcriptpath}).then(resp => { + await mapFunctions.get("module-handler").function(args.document.module, {inputTranscriptPath: transcriptpath, documentTypePath: "./storage/documentType/standard_meeting_report.txt", language: "en"}).then(resp => { // TODO add language handling from frontend console.log(resp); transcriptpath = resp curstep++ diff --git a/services/modules/llm-chat_gpt/chatgpt.js b/services/modules/llm-chat_gpt/chatgpt.js index 76fa3a3..d07a422 100644 --- a/services/modules/llm-chat_gpt/chatgpt.js +++ b/services/modules/llm-chat_gpt/chatgpt.js @@ -50,7 +50,7 @@ const module_exports = { body: JSON.stringify({ model: "openai-gpt-oss-120b", messages: [ - { role: "system", content: "You are a helpful assistant that generates documents from transcripts." }, + { role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." }, { role: "user", content: promptText } ], temperature: 0 @@ -71,7 +71,7 @@ const module_exports = { let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file console.log(inputTranscriptName); - const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name + const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name fs.writeFileSync(outPath, output, "utf8"); // Write output to file console.log("Generated document written to:", outPath); @@ -91,7 +91,7 @@ if (require.main === module) { if (args.length < 2) { console.error("Usage: node llm-openai-gpt.js [language]"); - console.error("Example: node llm-openai-gpt.js ./transcript.json ./docType.json de"); + console.error("Example: node llm-openai-gpt.js ./transcript.json ./docType.txt de"); process.exit(1); } diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js index 6bd88a6..892560e 100644 --- a/services/modules/llm-gemini/gemini.js +++ b/services/modules/llm-gemini/gemini.js @@ -1,15 +1,17 @@ -const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory +const fs = require('fs'); +const path = require('path'); + +const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist } // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here" - const GEMINI_API_KEY = process.env.GOOGLE_API_KEY; // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here" -const GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"; //URL for the REST call, used model and action +const GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"; // URL for the REST call, used model and action -module.exports = { +const module_exports = { name: "llm-gemini", type: "llm", displayname: "Gemini LLM", @@ -19,7 +21,7 @@ module.exports = { try { console.log("Gemini LLM module invoked with parameters:", parameter); - await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language + await this.createDocumentFromTranscript( // Call the function to create document with transcript, document type and language parameter.inputTranscriptPath, // Path to input transcript file parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user parameter.language // Language for the document which is chosen in the front end by the user @@ -32,12 +34,15 @@ module.exports = { createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English try { - const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path - const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path - const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed + const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); // read transcript file from Path + const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); // read document type from Path + + // Add system instruction for HTML output + const systemInstruction = "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting."; + const promptText = `${systemInstruction}\n\n${documentType}, in language ${language}, transcript:\n\n${transcript}`; // combine doc type, language and transcript - Change prompt here if needed // --- REST CALL --- - const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { //safe model response in variable + const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { // safe model response in variable method: "POST", headers: { "Content-Type": "application/json" @@ -64,7 +69,7 @@ module.exports = { const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || ""; let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file console.log(inputTranscriptName); - const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name + const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name fs.writeFileSync(outPath, output, "utf8"); // Write output to file console.log("Generated document written to:", outPath); @@ -73,4 +78,52 @@ module.exports = { console.error("Error generating Gemini content:", error); } } -}; \ No newline at end of file +}; + +module.exports = module_exports; + +// CLI Mode: Allow direct execution +if (require.main === module) { + (async () => { + const args = process.argv.slice(2); + + if (args.length < 2) { + console.error("Usage: node llm-gemini.js [language]"); + console.error("Example: node llm-gemini.js ./transcript.json ./docType.txt de"); + process.exit(1); + } + + const [transcriptPath, documentTypePath, language] = args; + + // Check if API key is set + if (!GEMINI_API_KEY) { + console.error("ERROR: GOOGLE_API_KEY environment variable is not set!"); + console.error("Please set it with: export GOOGLE_API_KEY='your_api_key_here'"); + process.exit(1); + } + + // Check if files exist + if (!fs.existsSync(transcriptPath)) { + console.error(`ERROR: Transcript file not found: ${transcriptPath}`); + process.exit(1); + } + + if (!fs.existsSync(documentTypePath)) { + console.error(`ERROR: Document type file not found: ${documentTypePath}`); + process.exit(1); + } + + console.log("Starting document generation..."); + console.log(`Transcript: ${transcriptPath}`); + console.log(`Document Type: ${documentTypePath}`); + console.log(`Language: ${language || 'en (default)'}`); + + await module_exports.createDocumentFromTranscript( + transcriptPath, + documentTypePath, + language || 'en' + ); + + console.log("Done!"); + })(); +} \ No newline at end of file diff --git a/services/modules/quen3/quen3.js b/services/modules/quen3/quen3.js index 8272c52..fd93737 100644 --- a/services/modules/quen3/quen3.js +++ b/services/modules/quen3/quen3.js @@ -1,14 +1,15 @@ const fs = require('fs'); const path = require('path'); -const outputDir = path.join(__dirname, "../../../storage/documents"); +const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory if (!fs.existsSync(outputDir)) { - fs.mkdirSync(outputDir, { recursive: true }); + fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist } +// Ensure SAIA API key is set in environment variables: export SAIA_API_KEY="your_api_key_here" const SAIA_API_KEY = process.env.SAIA_API_KEY; -const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; +const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; // URL for the REST call, used model and action const module_exports = { name: "qwen3-235b-a22b", @@ -20,10 +21,10 @@ const module_exports = { try { console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter); - await this.createDocumentFromTranscript( - parameter.inputTranscriptPath, - parameter.documentTypePath, - parameter.language + await this.createDocumentFromTranscript( // Call the function to create document with transcript, document type and language + parameter.inputTranscriptPath, // Path to input transcript file + parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user + parameter.language // Language for the document which is chosen in the front end by the user ); } catch (error) { @@ -31,11 +32,11 @@ const module_exports = { } }, - createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { + createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English try { - const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); - const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); - const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; + const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); // read transcript file from Path + const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); // read document type from Path + const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; // combine doc type, language and transcript - Change prompt here if needed // --- REST CALL --- const response = await fetch(SAIA_URL, { @@ -48,26 +49,29 @@ const module_exports = { body: JSON.stringify({ model: "qwen3-235b-a22b", messages: [ - { role: "system", content: "You are a helpful assistant that generates documents from transcripts. Do NOT include any , reasoning, chain-of-thought, or internal analysis. Only output the final document content." }, + { role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." }, { role: "user", content: promptText } ], temperature: 0 }) }); - if (!response.ok) { + if (!response.ok) { // ok is true when a response was successful const text = await response.text(); throw new Error(`SAIA API error (${response.status}): ${text}`); } const data = await response.json(); + + // Get generated text from response or default to empty string (if null) + // SAIA uses OpenAI-compatible structure: data.choices[x].message.content const output = data.choices?.[0]?.message?.content || ""; - let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); + let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file console.log(inputTranscriptName); - const outPath = path.join(outputDir, `${inputTranscriptName}.md`); - fs.writeFileSync(outPath, output, "utf8"); + const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name + fs.writeFileSync(outPath, output, "utf8"); // Write output to file console.log("Generated document written to:", outPath); @@ -79,24 +83,27 @@ const module_exports = { module.exports = module_exports; +// CLI Mode: Allow direct execution if (require.main === module) { (async () => { const args = process.argv.slice(2); if (args.length < 2) { - console.error("Usage: node quen3.js [language]"); - console.error("Example: node quen3.js ./transcript.json ./docType.json de"); + console.error("Usage: node qwen3.js [language]"); + console.error("Example: node qwen3.js ./transcript.json ./docType.txt de"); process.exit(1); } const [transcriptPath, documentTypePath, language] = args; + // Check if API key is set if (!SAIA_API_KEY) { console.error("ERROR: SAIA_API_KEY environment variable is not set!"); console.error("Please set it with: export SAIA_API_KEY='your_api_key_here'"); process.exit(1); } + // Check if files exist if (!fs.existsSync(transcriptPath)) { console.error(`ERROR: Transcript file not found: ${transcriptPath}`); process.exit(1);