included sharepoint nodes
This commit is contained in:
parent
e1ed0ee63c
commit
9a2e2b4f5f
368 changed files with 14850 additions and 255 deletions
|
|
@ -5,10 +5,25 @@ Interface for Automation2 feature - Workflows, Runs, Human Tasks.
|
||||||
Uses PostgreSQL poweron_automation2 database.
|
Uses PostgreSQL poweron_automation2 database.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import base64
|
||||||
import logging
|
import logging
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
def _make_json_serializable(obj: Any) -> Any:
|
||||||
|
"""
|
||||||
|
Recursively convert bytes to base64 strings so structures can be JSON-serialized
|
||||||
|
for storage in JSONB columns.
|
||||||
|
"""
|
||||||
|
if isinstance(obj, bytes):
|
||||||
|
return base64.b64encode(obj).decode("ascii")
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
return {k: _make_json_serializable(v) for k, v in obj.items()}
|
||||||
|
if isinstance(obj, list):
|
||||||
|
return [_make_json_serializable(v) for v in obj]
|
||||||
|
return obj
|
||||||
|
|
||||||
from modules.datamodels.datamodelUam import User
|
from modules.datamodels.datamodelUam import User
|
||||||
from modules.features.automation2.datamodelFeatureAutomation2 import (
|
from modules.features.automation2.datamodelFeatureAutomation2 import (
|
||||||
Automation2Workflow,
|
Automation2Workflow,
|
||||||
|
|
@ -139,7 +154,7 @@ class Automation2Objects:
|
||||||
"id": str(uuid.uuid4()),
|
"id": str(uuid.uuid4()),
|
||||||
"workflowId": workflowId,
|
"workflowId": workflowId,
|
||||||
"status": "running",
|
"status": "running",
|
||||||
"nodeOutputs": nodeOutputs or {},
|
"nodeOutputs": _make_json_serializable(nodeOutputs or {}),
|
||||||
"currentNodeId": None,
|
"currentNodeId": None,
|
||||||
"context": context or {},
|
"context": context or {},
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +189,7 @@ class Automation2Objects:
|
||||||
if status is not None:
|
if status is not None:
|
||||||
updates["status"] = status
|
updates["status"] = status
|
||||||
if nodeOutputs is not None:
|
if nodeOutputs is not None:
|
||||||
updates["nodeOutputs"] = nodeOutputs
|
updates["nodeOutputs"] = _make_json_serializable(nodeOutputs)
|
||||||
if currentNodeId is not None:
|
if currentNodeId is not None:
|
||||||
updates["currentNodeId"] = currentNodeId
|
updates["currentNodeId"] = currentNodeId
|
||||||
if context is not None:
|
if context is not None:
|
||||||
|
|
|
||||||
|
|
@ -44,16 +44,14 @@ SHAREPOINT_NODES = [
|
||||||
"description": {"en": "Upload file to SharePoint", "de": "Datei zu SharePoint hochladen", "fr": "Téléverser fichier vers SharePoint"},
|
"description": {"en": "Upload file to SharePoint", "de": "Datei zu SharePoint hochladen", "fr": "Téléverser fichier vers SharePoint"},
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{"name": "connectionId", "type": "string", "required": True, "description": {"en": "SharePoint connection", "de": "SharePoint-Verbindung", "fr": "Connexion SharePoint"}},
|
{"name": "connectionId", "type": "string", "required": True, "description": {"en": "SharePoint connection", "de": "SharePoint-Verbindung", "fr": "Connexion SharePoint"}},
|
||||||
{"name": "folderPath", "type": "string", "required": True, "description": {"en": "Target folder path", "de": "Zielordner-Pfad", "fr": "Chemin du dossier cible"}},
|
{"name": "path", "type": "string", "required": True, "description": {"en": "Target folder path (e.g. /sites/.../Folder)", "de": "Zielordner-Pfad", "fr": "Chemin du dossier cible"}},
|
||||||
{"name": "siteId", "type": "string", "required": True, "description": {"en": "SharePoint site ID", "de": "SharePoint Site-ID", "fr": "ID du site SharePoint"}},
|
|
||||||
{"name": "fileName", "type": "string", "required": True, "description": {"en": "File name", "de": "Dateiname", "fr": "Nom du fichier"}},
|
|
||||||
],
|
],
|
||||||
"inputs": 1,
|
"inputs": 1,
|
||||||
"outputs": 1,
|
"outputs": 1,
|
||||||
"meta": {"icon": "mdi-upload", "color": "#0078D4"},
|
"meta": {"icon": "mdi-upload", "color": "#0078D4"},
|
||||||
"_method": "sharepoint",
|
"_method": "sharepoint",
|
||||||
"_action": "uploadFile",
|
"_action": "uploadFile",
|
||||||
"_paramMap": {"connectionId": "connectionReference", "folderPath": "folderPath", "siteId": "siteId", "fileName": "fileName"},
|
"_paramMap": {"connectionId": "connectionReference", "path": "pathQuery"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sharepoint.listFiles",
|
"id": "sharepoint.listFiles",
|
||||||
|
|
@ -75,18 +73,17 @@ SHAREPOINT_NODES = [
|
||||||
"id": "sharepoint.downloadFile",
|
"id": "sharepoint.downloadFile",
|
||||||
"category": "sharepoint",
|
"category": "sharepoint",
|
||||||
"label": {"en": "Download File", "de": "Datei herunterladen", "fr": "Télécharger fichier"},
|
"label": {"en": "Download File", "de": "Datei herunterladen", "fr": "Télécharger fichier"},
|
||||||
"description": {"en": "Download file from path", "de": "Datei vom Pfad herunterladen", "fr": "Télécharger le fichier"},
|
"description": {"en": "Download file from path (e.g. /sites/SiteName/Shared Documents/file.pdf)", "de": "Datei vom Pfad herunterladen", "fr": "Télécharger le fichier"},
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{"name": "connectionId", "type": "string", "required": True, "description": {"en": "SharePoint connection", "de": "SharePoint-Verbindung", "fr": "Connexion SharePoint"}},
|
{"name": "connectionId", "type": "string", "required": True, "description": {"en": "SharePoint connection", "de": "SharePoint-Verbindung", "fr": "Connexion SharePoint"}},
|
||||||
{"name": "siteId", "type": "string", "required": True, "description": {"en": "SharePoint site ID", "de": "SharePoint Site-ID", "fr": "ID du site"}},
|
{"name": "path", "type": "string", "required": True, "description": {"en": "Full file path (e.g. /sites/SiteName/Shared Documents/file.pdf)", "de": "Vollständiger Dateipfad", "fr": "Chemin complet du fichier"}},
|
||||||
{"name": "filePath", "type": "string", "required": True, "description": {"en": "File path", "de": "Dateipfad", "fr": "Chemin du fichier"}},
|
|
||||||
],
|
],
|
||||||
"inputs": 1,
|
"inputs": 1,
|
||||||
"outputs": 1,
|
"outputs": 1,
|
||||||
"meta": {"icon": "mdi-download", "color": "#0078D4"},
|
"meta": {"icon": "mdi-download", "color": "#0078D4"},
|
||||||
"_method": "sharepoint",
|
"_method": "sharepoint",
|
||||||
"_action": "downloadFileByPath",
|
"_action": "downloadFileByPath",
|
||||||
"_paramMap": {"connectionId": "connectionReference", "siteId": "siteId", "filePath": "filePath"},
|
"_paramMap": {"connectionId": "connectionReference", "path": "pathQuery", "siteId": "siteId", "filePath": "filePath"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sharepoint.copyFile",
|
"id": "sharepoint.copyFile",
|
||||||
|
|
@ -95,17 +92,14 @@ SHAREPOINT_NODES = [
|
||||||
"description": {"en": "Copy file to destination", "de": "Datei an Ziel kopieren", "fr": "Copier le fichier"},
|
"description": {"en": "Copy file to destination", "de": "Datei an Ziel kopieren", "fr": "Copier le fichier"},
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{"name": "connectionId", "type": "string", "required": True, "description": {"en": "SharePoint connection", "de": "SharePoint-Verbindung", "fr": "Connexion SharePoint"}},
|
{"name": "connectionId", "type": "string", "required": True, "description": {"en": "SharePoint connection", "de": "SharePoint-Verbindung", "fr": "Connexion SharePoint"}},
|
||||||
{"name": "siteId", "type": "string", "required": True, "description": {"en": "SharePoint site ID", "de": "SharePoint Site-ID", "fr": "ID du site"}},
|
{"name": "sourcePath", "type": "string", "required": True, "description": {"en": "Source file path (from browse)", "de": "Quelldatei-Pfad", "fr": "Chemin fichier source"}},
|
||||||
{"name": "sourceFolder", "type": "string", "required": True, "description": {"en": "Source folder path", "de": "Quellordner-Pfad", "fr": "Chemin dossier source"}},
|
{"name": "destPath", "type": "string", "required": True, "description": {"en": "Destination folder path (from browse)", "de": "Zielordner-Pfad", "fr": "Chemin dossier cible"}},
|
||||||
{"name": "sourceFile", "type": "string", "required": True, "description": {"en": "Source file name", "de": "Quelldatei-Name", "fr": "Nom fichier source"}},
|
|
||||||
{"name": "destFolder", "type": "string", "required": True, "description": {"en": "Destination folder path", "de": "Zielordner-Pfad", "fr": "Chemin dossier cible"}},
|
|
||||||
{"name": "destFile", "type": "string", "required": True, "description": {"en": "Destination file name", "de": "Zieldatei-Name", "fr": "Nom fichier cible"}},
|
|
||||||
],
|
],
|
||||||
"inputs": 1,
|
"inputs": 1,
|
||||||
"outputs": 1,
|
"outputs": 1,
|
||||||
"meta": {"icon": "mdi-content-copy", "color": "#0078D4"},
|
"meta": {"icon": "mdi-content-copy", "color": "#0078D4"},
|
||||||
"_method": "sharepoint",
|
"_method": "sharepoint",
|
||||||
"_action": "copyFile",
|
"_action": "copyFile",
|
||||||
"_paramMap": {"connectionId": "connectionReference", "siteId": "siteId", "sourceFolder": "sourceFolder", "sourceFile": "sourceFile", "destFolder": "destFolder", "destFile": "destFile"},
|
"_paramMap": {"connectionId": "connectionReference", "sourcePath": "sourcePath", "destPath": "destPath"},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,10 @@ async def post_execute(
|
||||||
|
|
||||||
graph = body.get("graph") or body
|
graph = body.get("graph") or body
|
||||||
workflowId = body.get("workflowId")
|
workflowId = body.get("workflowId")
|
||||||
if workflowId:
|
req_nodes = graph.get("nodes") or []
|
||||||
|
# When workflowId is set: prefer graph from request (current editor state) if it has nodes.
|
||||||
|
# Only fall back to stored workflow graph when request graph is empty (e.g. resume from email).
|
||||||
|
if workflowId and len(req_nodes) == 0:
|
||||||
a2 = getAutomation2Interface(context.user, mandateId, instanceId)
|
a2 = getAutomation2Interface(context.user, mandateId, instanceId)
|
||||||
wf = a2.getWorkflow(workflowId)
|
wf = a2.getWorkflow(workflowId)
|
||||||
if wf and wf.get("graph"):
|
if wf and wf.get("graph"):
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,8 @@ class ChatService:
|
||||||
logger.error(f"No messages found with documentsLabel: {docRef}")
|
logger.error(f"No messages found with documentsLabel: {docRef}")
|
||||||
raise ValueError(f"Document reference not found: {docRef}")
|
raise ValueError(f"Document reference not found: {docRef}")
|
||||||
|
|
||||||
logger.debug(f"Resolved {len(allDocuments)} documents from document list: {documentList}")
|
ref_count = len(getattr(documentList, 'references', [])) if documentList else 0
|
||||||
|
logger.debug(f"Resolved {len(allDocuments)} documents from document list ({ref_count} refs)")
|
||||||
return allDocuments
|
return allDocuments
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error getting documents from document list: {str(e)}")
|
logger.error(f"Error getting documents from document list: {str(e)}")
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,38 @@ class ExtractionService:
|
||||||
if model is None or model.calculatepriceCHF is None:
|
if model is None or model.calculatepriceCHF is None:
|
||||||
raise RuntimeError(f"FATAL: Required internal model '{modelDisplayName}' is not available. Check connector registration.")
|
raise RuntimeError(f"FATAL: Required internal model '{modelDisplayName}' is not available. Check connector registration.")
|
||||||
|
|
||||||
|
def extractContentFromBytes(
|
||||||
|
self,
|
||||||
|
documentBytes: bytes,
|
||||||
|
fileName: str,
|
||||||
|
mimeType: str,
|
||||||
|
documentId: Optional[str] = None,
|
||||||
|
options: Optional[ExtractionOptions] = None,
|
||||||
|
) -> ContentExtracted:
|
||||||
|
"""Extract content from raw bytes (no persistence).
|
||||||
|
Used for inline ActionDocuments from SharePoint/email in automation2."""
|
||||||
|
opts = options or ExtractionOptions(prompt="", mergeStrategy=MergeStrategy())
|
||||||
|
doc_id = documentId or str(uuid.uuid4())
|
||||||
|
ec = runExtraction(
|
||||||
|
self._extractorRegistry,
|
||||||
|
self._chunkerRegistry,
|
||||||
|
documentBytes,
|
||||||
|
fileName,
|
||||||
|
mimeType,
|
||||||
|
opts,
|
||||||
|
)
|
||||||
|
for p in ec.parts:
|
||||||
|
if not p.metadata:
|
||||||
|
p.metadata = {}
|
||||||
|
p.metadata.setdefault("documentId", doc_id)
|
||||||
|
p.metadata.setdefault("documentMimeType", mimeType)
|
||||||
|
p.metadata.setdefault("originalFileName", fileName)
|
||||||
|
p.metadata.setdefault("contentFormat", "extracted")
|
||||||
|
p.metadata.setdefault("intent", "extract")
|
||||||
|
p.metadata.setdefault("usageHint", f"Use extracted content from {fileName}")
|
||||||
|
p.metadata.setdefault("sourceAction", "extraction.extractContentFromBytes")
|
||||||
|
return ec
|
||||||
|
|
||||||
def extractContent(
|
def extractContent(
|
||||||
self,
|
self,
|
||||||
documents: List[ChatDocument],
|
documents: List[ChatDocument],
|
||||||
|
|
|
||||||
|
|
@ -56,15 +56,15 @@ class DocumentGenerationPath:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Schritt 5A: Kläre Dokument-Intents
|
# Schritt 5A: Kläre Dokument-Intents
|
||||||
documents = []
|
doc_list = []
|
||||||
if documentList:
|
if documentList:
|
||||||
documents = self.services.chat.getChatDocumentsFromDocumentList(documentList)
|
doc_list = self.services.chat.getChatDocumentsFromDocumentList(documentList)
|
||||||
|
|
||||||
# Filter: Entferne Original-Dokumente, wenn bereits Pre-Extracted JSONs existieren
|
# Filter: Entferne Original-Dokumente, wenn bereits Pre-Extracted JSONs existieren
|
||||||
# (um Duplikate zu vermeiden - Pre-Extracted JSONs enthalten bereits die ContentParts)
|
# (um Duplikate zu vermeiden - Pre-Extracted JSONs enthalten bereits die ContentParts)
|
||||||
# Schritt 1: Identifiziere alle Original-Dokument-IDs, die durch Pre-Extracted JSONs abgedeckt werden
|
# Schritt 1: Identifiziere alle Original-Dokument-IDs, die durch Pre-Extracted JSONs abgedeckt werden
|
||||||
originalDocIdsCoveredByPreExtracted = set()
|
originalDocIdsCoveredByPreExtracted = set()
|
||||||
for doc in documents:
|
for doc in doc_list:
|
||||||
preExtracted = self.services.ai.intentAnalyzer.resolvePreExtractedDocument(doc)
|
preExtracted = self.services.ai.intentAnalyzer.resolvePreExtractedDocument(doc)
|
||||||
if preExtracted:
|
if preExtracted:
|
||||||
originalDocId = preExtracted["originalDocument"]["id"]
|
originalDocId = preExtracted["originalDocument"]["id"]
|
||||||
|
|
@ -73,7 +73,7 @@ class DocumentGenerationPath:
|
||||||
|
|
||||||
# Schritt 2: Filtere Dokumente - entferne Original-Dokumente, die bereits durch Pre-Extracted JSONs abgedeckt werden
|
# Schritt 2: Filtere Dokumente - entferne Original-Dokumente, die bereits durch Pre-Extracted JSONs abgedeckt werden
|
||||||
filteredDocuments = []
|
filteredDocuments = []
|
||||||
for doc in documents:
|
for doc in doc_list:
|
||||||
preExtracted = self.services.ai.intentAnalyzer.resolvePreExtractedDocument(doc)
|
preExtracted = self.services.ai.intentAnalyzer.resolvePreExtractedDocument(doc)
|
||||||
if preExtracted:
|
if preExtracted:
|
||||||
# Pre-Extracted JSON behalten
|
# Pre-Extracted JSON behalten
|
||||||
|
|
@ -85,13 +85,13 @@ class DocumentGenerationPath:
|
||||||
# Normales Dokument ohne Pre-Extracted JSON - behalten
|
# Normales Dokument ohne Pre-Extracted JSON - behalten
|
||||||
filteredDocuments.append(doc)
|
filteredDocuments.append(doc)
|
||||||
|
|
||||||
documents = filteredDocuments
|
doc_list = filteredDocuments
|
||||||
|
|
||||||
checkWorkflowStopped(self.services)
|
checkWorkflowStopped(self.services)
|
||||||
|
|
||||||
if not documentIntents and documents:
|
if not documentIntents and doc_list:
|
||||||
documentIntents = await self.services.ai.clarifyDocumentIntents(
|
documentIntents = await self.services.ai.clarifyDocumentIntents(
|
||||||
documents,
|
doc_list,
|
||||||
userPrompt,
|
userPrompt,
|
||||||
{"outputFormat": outputFormat},
|
{"outputFormat": outputFormat},
|
||||||
docOperationId
|
docOperationId
|
||||||
|
|
@ -100,9 +100,9 @@ class DocumentGenerationPath:
|
||||||
checkWorkflowStopped(self.services)
|
checkWorkflowStopped(self.services)
|
||||||
|
|
||||||
# Schritt 5B: Extrahiere und bereite Content vor
|
# Schritt 5B: Extrahiere und bereite Content vor
|
||||||
if documents:
|
if doc_list:
|
||||||
preparedContentParts = await self.services.ai.extractAndPrepareContent(
|
preparedContentParts = await self.services.ai.extractAndPrepareContent(
|
||||||
documents,
|
doc_list,
|
||||||
documentIntents or [],
|
documentIntents or [],
|
||||||
docOperationId
|
docOperationId
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,18 @@ class RendererRegistry:
|
||||||
"""Register a renderer class keyed by (format, outputStyle)."""
|
"""Register a renderer class keyed by (format, outputStyle)."""
|
||||||
try:
|
try:
|
||||||
supportedFormats = rendererClass.getSupportedFormats()
|
supportedFormats = rendererClass.getSupportedFormats()
|
||||||
outputStyle = rendererClass.getOutputStyle() if hasattr(rendererClass, 'getOutputStyle') else 'document'
|
|
||||||
priority = rendererClass.getPriority() if hasattr(rendererClass, 'getPriority') else 0
|
priority = rendererClass.getPriority() if hasattr(rendererClass, 'getPriority') else 0
|
||||||
|
|
||||||
for formatName in supportedFormats:
|
for formatName in supportedFormats:
|
||||||
formatKey = formatName.lower()
|
formatKey = formatName.lower()
|
||||||
|
# Per-format output style when renderer supports it (e.g. RendererText: txt→document, js→code)
|
||||||
|
if hasattr(rendererClass, 'getOutputStyle'):
|
||||||
|
try:
|
||||||
|
outputStyle = rendererClass.getOutputStyle(formatKey)
|
||||||
|
except TypeError:
|
||||||
|
outputStyle = rendererClass.getOutputStyle() if callable(getattr(rendererClass, 'getOutputStyle')) else 'document'
|
||||||
|
else:
|
||||||
|
outputStyle = 'document'
|
||||||
registryKey = (formatKey, outputStyle)
|
registryKey = (formatKey, outputStyle)
|
||||||
|
|
||||||
if registryKey in self._renderers:
|
if registryKey in self._renderers:
|
||||||
|
|
|
||||||
|
|
@ -692,12 +692,35 @@ class SharepointService:
|
||||||
logger.error(f"Error extracting site from standard path '{pathQuery}': {str(e)}")
|
logger.error(f"Error extracting site from standard path '{pathQuery}': {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _isGraphSiteId(self, sitePath: str) -> bool:
|
||||||
|
"""Check if sitePath is a Graph API site ID (hostname,siteId,webId format with 2 commas)."""
|
||||||
|
if not sitePath or sitePath.count(',') != 2:
|
||||||
|
return False
|
||||||
|
parts = sitePath.split(',')
|
||||||
|
return len(parts) == 3 and all(p.strip() for p in parts)
|
||||||
|
|
||||||
async def getSiteByStandardPath(self, sitePath: str, allSites: Optional[List[Dict[str, Any]]] = None) -> Optional[Dict[str, Any]]:
|
async def getSiteByStandardPath(self, sitePath: str, allSites: Optional[List[Dict[str, Any]]] = None) -> Optional[Dict[str, Any]]:
|
||||||
"""Get SharePoint site directly by Microsoft-standard path (/sites/SiteName)."""
|
"""Get SharePoint site directly by Microsoft-standard path (/sites/SiteName) or by site ID."""
|
||||||
try:
|
try:
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
hostname = None
|
|
||||||
|
|
||||||
|
# When sitePath is a Graph API site ID (host,siteId,webId), use sites/{id} directly
|
||||||
|
if self._isGraphSiteId(sitePath):
|
||||||
|
endpoint = f"sites/{sitePath}"
|
||||||
|
result = await self._makeGraphApiCall(endpoint)
|
||||||
|
if result and "error" not in result:
|
||||||
|
return {
|
||||||
|
"id": result.get("id"),
|
||||||
|
"displayName": result.get("displayName"),
|
||||||
|
"name": result.get("name"),
|
||||||
|
"webUrl": result.get("webUrl"),
|
||||||
|
"description": result.get("description"),
|
||||||
|
"createdDateTime": result.get("createdDateTime"),
|
||||||
|
"lastModifiedDateTime": result.get("lastModifiedDateTime")
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
hostname = None
|
||||||
if allSites and len(allSites) > 0:
|
if allSites and len(allSites) > 0:
|
||||||
webUrl = allSites[0].get("webUrl", "")
|
webUrl = allSites[0].get("webUrl", "")
|
||||||
hostname = urlparse(webUrl).hostname if webUrl else None
|
hostname = urlparse(webUrl).hostname if webUrl else None
|
||||||
|
|
@ -777,6 +800,14 @@ class SharepointService:
|
||||||
parsedPath = self.extractSiteFromStandardPath(pathQuery)
|
parsedPath = self.extractSiteFromStandardPath(pathQuery)
|
||||||
if parsedPath:
|
if parsedPath:
|
||||||
siteName = parsedPath.get("siteName")
|
siteName = parsedPath.get("siteName")
|
||||||
|
# When siteName is Graph API composite ID (host,siteId,webId), match by exact id
|
||||||
|
if siteName and ',' in siteName:
|
||||||
|
exact = [s for s in allSites if s.get("id") == siteName]
|
||||||
|
if exact:
|
||||||
|
logger.info(f"Resolved site by exact ID: {siteName}")
|
||||||
|
return exact
|
||||||
|
logger.warning(f"No site found with exact ID '{siteName}'")
|
||||||
|
return []
|
||||||
sites = self.filterSitesByHint(allSites, siteName)
|
sites = self.filterSitesByHint(allSites, siteName)
|
||||||
if not sites:
|
if not sites:
|
||||||
logger.warning(f"No SharePoint site found matching '{siteName}'")
|
logger.warning(f"No SharePoint site found matching '{siteName}'")
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,8 @@ async def executeGraph(
|
||||||
mandateId,
|
mandateId,
|
||||||
startAfterNodeId is not None,
|
startAfterNodeId is not None,
|
||||||
)
|
)
|
||||||
|
from modules.workflows.processing.shared.methodDiscovery import discoverMethods
|
||||||
|
discoverMethods(services)
|
||||||
nodeTypeIds = _getNodeTypeIds(services)
|
nodeTypeIds = _getNodeTypeIds(services)
|
||||||
logger.debug("executeGraph nodeTypeIds (%d): %s", len(nodeTypeIds), sorted(nodeTypeIds))
|
logger.debug("executeGraph nodeTypeIds (%d): %s", len(nodeTypeIds), sorted(nodeTypeIds))
|
||||||
errors = validateGraph(graph, nodeTypeIds)
|
errors = validateGraph(graph, nodeTypeIds)
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,19 @@ def _getNodeDefinition(nodeType: str) -> Optional[Dict[str, Any]]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _resolveConnectionIdToReference(chatService, connectionId: str) -> Optional[str]:
|
def _resolveConnectionIdToReference(chatService, connectionId: str, services=None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Resolve connectionId (UserConnection.id) to connectionReference format.
|
Resolve connectionId (UserConnection.id) to connectionReference format.
|
||||||
connectionReference format: connection:{authority}:{externalUsername}
|
connectionReference format: connection:{authority}:{externalUsername}
|
||||||
|
Falls back to interfaceDbApp.getUserConnectionById when chatService resolution fails.
|
||||||
"""
|
"""
|
||||||
if not connectionId or not chatService:
|
if not connectionId:
|
||||||
return None
|
return None
|
||||||
|
# Already in reference format
|
||||||
|
if isinstance(connectionId, str) and connectionId.startswith("connection:"):
|
||||||
|
return connectionId
|
||||||
|
# Try chatService first
|
||||||
|
if chatService:
|
||||||
try:
|
try:
|
||||||
connections = chatService.getUserConnections()
|
connections = chatService.getUserConnections()
|
||||||
for c in connections or []:
|
for c in connections or []:
|
||||||
|
|
@ -33,9 +39,23 @@ def _resolveConnectionIdToReference(chatService, connectionId: str) -> Optional[
|
||||||
authority = authority.value
|
authority = authority.value
|
||||||
username = conn.get("externalUsername", "")
|
username = conn.get("externalUsername", "")
|
||||||
return f"connection:{authority}:{username}"
|
return f"connection:{authority}:{username}"
|
||||||
return None
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Could not resolve connectionId {connectionId} to reference: {e}")
|
logger.debug("_resolveConnectionIdToReference chatService: %s", e)
|
||||||
|
# Fallback: interfaceDbApp.getUserConnectionById (automation2 may not have chat.getUserConnections)
|
||||||
|
app = getattr(services, "interfaceDbApp", None) if services else None
|
||||||
|
if app and hasattr(app, "getUserConnectionById"):
|
||||||
|
try:
|
||||||
|
conn = app.getUserConnectionById(str(connectionId))
|
||||||
|
if conn:
|
||||||
|
authority = getattr(conn, "authority", None)
|
||||||
|
if hasattr(authority, "value"):
|
||||||
|
authority = authority.value
|
||||||
|
else:
|
||||||
|
authority = str(authority) if authority else "outlook"
|
||||||
|
username = getattr(conn, "externalUsername", "") or ""
|
||||||
|
return f"connection:{authority}:{username}"
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug("_resolveConnectionIdToReference getUserConnectionById: %s", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -67,6 +87,71 @@ def _extractEmailContentFromUpstream(inp: Any) -> Optional[Dict[str, Any]]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _extractContextFromUpstream(inp: Any) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Extract plain text context from upstream node output (e.g. AI node returning txt).
|
||||||
|
Use when _extractEmailContentFromUpstream returns None – the generated document content
|
||||||
|
(email body, summary, etc.) should be passed as context to email.draftEmail.
|
||||||
|
"""
|
||||||
|
if not inp:
|
||||||
|
return None
|
||||||
|
docs = None
|
||||||
|
if isinstance(inp, dict):
|
||||||
|
docs = inp.get("documents") or inp.get("documentList")
|
||||||
|
if not docs and isinstance(inp.get("data"), dict):
|
||||||
|
docs = inp.get("data", {}).get("documents")
|
||||||
|
if not docs or not isinstance(docs, (list, tuple)):
|
||||||
|
return None
|
||||||
|
doc = docs[0] if docs else None
|
||||||
|
if not doc:
|
||||||
|
return None
|
||||||
|
raw = getattr(doc, "documentData", None) if hasattr(doc, "documentData") else (doc.get("documentData") or doc.get("content") if isinstance(doc, dict) else None)
|
||||||
|
if not raw:
|
||||||
|
return None
|
||||||
|
if isinstance(raw, bytes):
|
||||||
|
return raw.decode("utf-8", errors="replace").strip()
|
||||||
|
s = str(raw).strip()
|
||||||
|
return s if s else None
|
||||||
|
|
||||||
|
|
||||||
|
def _gatherAttachmentDocumentsFromUpstream(
|
||||||
|
nodeId: str,
|
||||||
|
inputSources: Dict[str, Dict[int, tuple]],
|
||||||
|
nodeOutputs: Dict[str, Any],
|
||||||
|
orderedNodes: List[Dict],
|
||||||
|
visited: Optional[set] = None,
|
||||||
|
) -> List[Any]:
|
||||||
|
"""
|
||||||
|
Walk upstream from nodeId through AI nodes to collect file documents (e.g. from sharepoint.downloadFile).
|
||||||
|
Used when email.draftEmail has AI upstream – attachments come from file nodes, not AI output.
|
||||||
|
"""
|
||||||
|
visited = visited or set()
|
||||||
|
if nodeId in visited:
|
||||||
|
return []
|
||||||
|
visited.add(nodeId)
|
||||||
|
docs = []
|
||||||
|
src = inputSources.get(nodeId, {}).get(0)
|
||||||
|
if not src:
|
||||||
|
return []
|
||||||
|
srcId, _ = src
|
||||||
|
srcNode = next((n for n in (orderedNodes or []) if n.get("id") == srcId), None)
|
||||||
|
srcType = (srcNode or {}).get("type", "")
|
||||||
|
out = nodeOutputs.get(srcId)
|
||||||
|
|
||||||
|
if srcType in ("sharepoint.downloadFile", "sharepoint.readFile"):
|
||||||
|
if isinstance(out, dict):
|
||||||
|
for d in out.get("documents") or out.get("documentList") or []:
|
||||||
|
if isinstance(d, dict) and (d.get("documentData") or (d.get("validationMetadata") or {}).get("fileId")):
|
||||||
|
docs.append(d)
|
||||||
|
elif hasattr(d, "documentData") or (getattr(d, "validationMetadata", None) or {}).get("fileId"):
|
||||||
|
docs.append(d.model_dump() if hasattr(d, "model_dump") else d)
|
||||||
|
elif srcType.startswith("ai."):
|
||||||
|
docs.extend(
|
||||||
|
_gatherAttachmentDocumentsFromUpstream(srcId, inputSources, nodeOutputs, orderedNodes, visited)
|
||||||
|
)
|
||||||
|
return docs
|
||||||
|
|
||||||
|
|
||||||
def _getIncomingEmailFromUpstream(
|
def _getIncomingEmailFromUpstream(
|
||||||
nodeId: str,
|
nodeId: str,
|
||||||
inputSources: Dict[str, Dict[int, tuple]],
|
inputSources: Dict[str, Dict[int, tuple]],
|
||||||
|
|
@ -213,6 +298,7 @@ def _buildActionParams(
|
||||||
nodeDef: Dict[str, Any],
|
nodeDef: Dict[str, Any],
|
||||||
resolvedParams: Dict[str, Any],
|
resolvedParams: Dict[str, Any],
|
||||||
chatService,
|
chatService,
|
||||||
|
services=None,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Build params for ActionExecutor from node parameters using _paramMap.
|
Build params for ActionExecutor from node parameters using _paramMap.
|
||||||
|
|
@ -259,8 +345,8 @@ def _buildActionParams(
|
||||||
# Resolve connectionId to connectionReference
|
# Resolve connectionId to connectionReference
|
||||||
if "connectionId" in params:
|
if "connectionId" in params:
|
||||||
connId = params.get("connectionId")
|
connId = params.get("connectionId")
|
||||||
if connId and chatService:
|
if connId:
|
||||||
ref = _resolveConnectionIdToReference(chatService, connId)
|
ref = _resolveConnectionIdToReference(chatService, connId, services)
|
||||||
if ref:
|
if ref:
|
||||||
params["connectionReference"] = ref
|
params["connectionReference"] = ref
|
||||||
else:
|
else:
|
||||||
|
|
@ -366,7 +452,7 @@ class ActionNodeExecutor:
|
||||||
logger.debug("ai.prompt: injected email context from upstream %s", srcType)
|
logger.debug("ai.prompt: injected email context from upstream %s", srcType)
|
||||||
|
|
||||||
chatService = getattr(self.services, "chat", None)
|
chatService = getattr(self.services, "chat", None)
|
||||||
actionParams = _buildActionParams(node, nodeDef or {}, resolvedParams, chatService)
|
actionParams = _buildActionParams(node, nodeDef or {}, resolvedParams, chatService, self.services)
|
||||||
|
|
||||||
# email.checkEmail: pause and wait for new email (background poller will resume)
|
# email.checkEmail: pause and wait for new email (background poller will resume)
|
||||||
if nodeType == "email.checkEmail":
|
if nodeType == "email.checkEmail":
|
||||||
|
|
@ -408,9 +494,37 @@ class ActionNodeExecutor:
|
||||||
email_content = _extractEmailContentFromUpstream(inp)
|
email_content = _extractEmailContentFromUpstream(inp)
|
||||||
if email_content:
|
if email_content:
|
||||||
actionParams["emailContent"] = email_content
|
actionParams["emailContent"] = email_content
|
||||||
actionParams.setdefault("context", "(from connected AI node)")
|
actionParams["context"] = email_content.get("body", "") or "(from connected AI node)"
|
||||||
|
# Attachments: gather from file nodes upstream of AI (e.g. downloadFile -> AI -> email)
|
||||||
|
attachment_docs = _gatherAttachmentDocumentsFromUpstream(
|
||||||
|
nodeId, inputSources, nodeOutputs, orderedNodes
|
||||||
|
)
|
||||||
|
if attachment_docs:
|
||||||
|
existing = actionParams.get("documentList") or []
|
||||||
|
# Prefer file docs from upstream; append any existing that look like binary attachments
|
||||||
|
def _is_binary_attachment(d):
|
||||||
|
if isinstance(d, dict) and d.get("documentData"):
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
json.loads(d["documentData"])
|
||||||
|
return False # JSON = email content, not attachment
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return True
|
||||||
|
return bool(isinstance(d, dict) and (d.get("validationMetadata") or {}).get("fileId"))
|
||||||
|
extra = [x for x in (existing if isinstance(existing, list) else []) if _is_binary_attachment(x)]
|
||||||
|
actionParams["documentList"] = attachment_docs + extra
|
||||||
|
if not email_content:
|
||||||
|
# AI returns plain text (e.g. email.txt): use as email body directly (no extra AI call)
|
||||||
|
ctx = _extractContextFromUpstream(inp)
|
||||||
|
if ctx:
|
||||||
|
actionParams["emailContent"] = {
|
||||||
|
"subject": actionParams.get("subject", "Draft"),
|
||||||
|
"body": ctx,
|
||||||
|
"to": actionParams.get("to"),
|
||||||
|
}
|
||||||
|
actionParams["context"] = ctx
|
||||||
else:
|
else:
|
||||||
# AI failed or wrong format: pass incoming email from upstream as context
|
# Fallback: incoming email from upstream (if flow is email->AI->draft)
|
||||||
incoming = _getIncomingEmailFromUpstream(nodeId, inputSources, nodeOutputs, orderedNodes)
|
incoming = _getIncomingEmailFromUpstream(nodeId, inputSources, nodeOutputs, orderedNodes)
|
||||||
if incoming:
|
if incoming:
|
||||||
ctx, doc_list, reply_to = incoming
|
ctx, doc_list, reply_to = incoming
|
||||||
|
|
@ -419,6 +533,33 @@ class ActionNodeExecutor:
|
||||||
actionParams["documentList"] = doc_list
|
actionParams["documentList"] = doc_list
|
||||||
if reply_to and not actionParams.get("to"):
|
if reply_to and not actionParams.get("to"):
|
||||||
actionParams["to"] = [reply_to]
|
actionParams["to"] = [reply_to]
|
||||||
|
else:
|
||||||
|
doc_count = len(inp.get("documents", [])) if isinstance(inp, dict) else 0
|
||||||
|
logger.warning(
|
||||||
|
"email.draftEmail: AI upstream returned %d doc(s) but context extraction failed (no subject/body, no plain text). "
|
||||||
|
"Ensure AI node outputs document with documentData.",
|
||||||
|
doc_count,
|
||||||
|
)
|
||||||
|
actionParams["context"] = "(no context extracted from upstream – check AI node output)"
|
||||||
|
elif srcType in ("sharepoint.downloadFile", "sharepoint.readFile"):
|
||||||
|
# File itself is the context: pass as attachment, use filename as minimal context (no content extraction)
|
||||||
|
if not actionParams.get("context"):
|
||||||
|
inp = nodeOutputs.get(srcId)
|
||||||
|
docs = (inp.get("documents") or inp.get("documentList", [])) if isinstance(inp, dict) else []
|
||||||
|
doc = docs[0] if docs else None
|
||||||
|
name = None
|
||||||
|
if isinstance(doc, dict):
|
||||||
|
name = doc.get("documentName") or doc.get("fileName")
|
||||||
|
elif doc and hasattr(doc, "documentName"):
|
||||||
|
name = getattr(doc, "documentName", None) or getattr(doc, "fileName", None)
|
||||||
|
ctx = name if name else "Attachment"
|
||||||
|
actionParams["context"] = ctx
|
||||||
|
actionParams["emailContent"] = {
|
||||||
|
"subject": actionParams.get("subject", "Draft"),
|
||||||
|
"body": ctx,
|
||||||
|
"to": actionParams.get("to"),
|
||||||
|
}
|
||||||
|
# documentList already merged from upstream (file as attachment)
|
||||||
else:
|
else:
|
||||||
# Direct connection to email.checkEmail/searchEmail: use incoming email as context
|
# Direct connection to email.checkEmail/searchEmail: use incoming email as context
|
||||||
if not actionParams.get("context"):
|
if not actionParams.get("context"):
|
||||||
|
|
@ -431,11 +572,12 @@ class ActionNodeExecutor:
|
||||||
if reply_to and not actionParams.get("to"):
|
if reply_to and not actionParams.get("to"):
|
||||||
actionParams["to"] = [reply_to]
|
actionParams["to"] = [reply_to]
|
||||||
|
|
||||||
# sharepoint.uploadFile: content from documentList (upstream) if not in params
|
# Generic context handover: when upstream provides documents, pass first doc as content for actions that expect it
|
||||||
if nodeType == "sharepoint.uploadFile" and "content" not in actionParams:
|
|
||||||
docList = actionParams.get("documentList") or resolvedParams.get("documentList")
|
docList = actionParams.get("documentList") or resolvedParams.get("documentList")
|
||||||
if docList:
|
if docList and "content" not in actionParams:
|
||||||
actionParams["content"] = docList[0] if isinstance(docList, list) and docList else docList
|
first = docList[0] if isinstance(docList, list) and docList else docList
|
||||||
|
# Actions like sharepoint.uploadFile consume content from context
|
||||||
|
actionParams["content"] = first
|
||||||
|
|
||||||
executor = ActionExecutor(self.services)
|
executor = ActionExecutor(self.services)
|
||||||
logger.info("ActionNodeExecutor node %s calling executeAction(%s, %s)", nodeId, methodName, actionName)
|
logger.info("ActionNodeExecutor node %s calling executeAction(%s, %s)", nodeId, methodName, actionName)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
# Copyright (c) 2025 Patrick Motsch
|
# Copyright (c) 2025 Patrick Motsch
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
||||||
|
import base64
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
import uuid
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from modules.datamodels.datamodelChat import ActionResult, ActionDocument
|
from modules.datamodels.datamodelChat import ActionResult, ActionDocument
|
||||||
from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationTypeEnum, ProcessingModeEnum
|
from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationTypeEnum, ProcessingModeEnum
|
||||||
|
|
@ -11,6 +13,64 @@ from modules.datamodels.datamodelExtraction import ContentPart
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_action_document_like(obj: Any) -> bool:
|
||||||
|
"""Check if object is ActionDocument-like (has documentData for inline workflow documents)."""
|
||||||
|
if obj is None:
|
||||||
|
return False
|
||||||
|
data = None
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
data = obj.get("documentData") or obj.get("document_data")
|
||||||
|
else:
|
||||||
|
data = getattr(obj, "documentData", None) or getattr(obj, "document_data", None)
|
||||||
|
if data is None:
|
||||||
|
return False
|
||||||
|
if isinstance(data, bytes):
|
||||||
|
return len(data) > 0
|
||||||
|
if isinstance(data, str):
|
||||||
|
return len(data.strip()) > 0
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _action_docs_to_content_parts(services, docs: List[Any]) -> List[ContentPart]:
|
||||||
|
"""Extract content from ActionDocument-like objects in memory (no persistence).
|
||||||
|
Decodes base64, runs extraction pipeline, returns ContentParts for AI.
|
||||||
|
"""
|
||||||
|
from modules.datamodels.datamodelExtraction import ExtractionOptions, MergeStrategy
|
||||||
|
|
||||||
|
all_parts = []
|
||||||
|
extraction = getattr(services, "extraction", None)
|
||||||
|
if not extraction:
|
||||||
|
logger.warning("ai.process: No extraction service - cannot extract from inline documents")
|
||||||
|
return []
|
||||||
|
opts = ExtractionOptions(prompt="", mergeStrategy=MergeStrategy())
|
||||||
|
for i, doc in enumerate(docs):
|
||||||
|
raw = (doc.get("documentData") or doc.get("document_data")) if isinstance(doc, dict) else (getattr(doc, "documentData", None) or getattr(doc, "document_data", None))
|
||||||
|
if not raw:
|
||||||
|
continue
|
||||||
|
name = doc.get("documentName", doc.get("fileName", f"document_{i}"))
|
||||||
|
mime = doc.get("mimeType", "application/octet-stream")
|
||||||
|
if isinstance(raw, str):
|
||||||
|
try:
|
||||||
|
content = base64.b64decode(raw, validate=True)
|
||||||
|
except Exception:
|
||||||
|
content = raw.encode("utf-8")
|
||||||
|
else:
|
||||||
|
content = raw if isinstance(raw, bytes) else bytes(raw)
|
||||||
|
ec = extraction.extractContentFromBytes(
|
||||||
|
documentBytes=content,
|
||||||
|
fileName=name,
|
||||||
|
mimeType=mime,
|
||||||
|
documentId=str(uuid.uuid4()),
|
||||||
|
options=opts,
|
||||||
|
)
|
||||||
|
for p in ec.parts:
|
||||||
|
if p.data or getattr(p, "typeGroup", "") == "image":
|
||||||
|
p.metadata.setdefault("originalFileName", name)
|
||||||
|
all_parts.append(p)
|
||||||
|
logger.info(f"ai.process: Extracted {len(ec.parts)} parts from {name} (no persistence)")
|
||||||
|
return all_parts
|
||||||
|
|
||||||
async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
operationId = None
|
operationId = None
|
||||||
try:
|
try:
|
||||||
|
|
@ -41,8 +101,21 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
||||||
|
|
||||||
documentListParam = parameters.get("documentList")
|
documentListParam = parameters.get("documentList")
|
||||||
# Convert to DocumentReferenceList if needed
|
inline_content_parts: Optional[List[ContentPart]] = None
|
||||||
if documentListParam is None:
|
|
||||||
|
# Handle inline ActionDocuments (e.g. from SharePoint/email in automation2 – no persistence)
|
||||||
|
is_inline = (
|
||||||
|
isinstance(documentListParam, list)
|
||||||
|
and len(documentListParam) > 0
|
||||||
|
and _is_action_document_like(documentListParam[0])
|
||||||
|
)
|
||||||
|
if is_inline:
|
||||||
|
inline_content_parts = _action_docs_to_content_parts(self.services, documentListParam)
|
||||||
|
documentList = DocumentReferenceList(references=[])
|
||||||
|
logger.info(
|
||||||
|
f"ai.process: Extracted {len(inline_content_parts)} ContentParts from {len(documentListParam)} inline ActionDocuments (no persistence)"
|
||||||
|
)
|
||||||
|
elif documentListParam is None:
|
||||||
documentList = DocumentReferenceList(references=[])
|
documentList = DocumentReferenceList(references=[])
|
||||||
logger.debug(f"ai.process: documentList is None, using empty DocumentReferenceList")
|
logger.debug(f"ai.process: documentList is None, using empty DocumentReferenceList")
|
||||||
elif isinstance(documentListParam, DocumentReferenceList):
|
elif isinstance(documentListParam, DocumentReferenceList):
|
||||||
|
|
@ -54,6 +127,11 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
documentList = DocumentReferenceList.from_string_list([documentListParam])
|
documentList = DocumentReferenceList.from_string_list([documentListParam])
|
||||||
logger.info(f"ai.process: Converted string to DocumentReferenceList with {len(documentList.references)} references")
|
logger.info(f"ai.process: Converted string to DocumentReferenceList with {len(documentList.references)} references")
|
||||||
elif isinstance(documentListParam, list):
|
elif isinstance(documentListParam, list):
|
||||||
|
first = documentListParam[0] if documentListParam else None
|
||||||
|
logger.info(
|
||||||
|
f"ai.process: documentList is list of {len(documentListParam)} items, "
|
||||||
|
f"first type={type(first).__name__}, has_documentData={_is_action_document_like(first) if first else False}"
|
||||||
|
)
|
||||||
documentList = DocumentReferenceList.from_string_list(documentListParam)
|
documentList = DocumentReferenceList.from_string_list(documentListParam)
|
||||||
logger.info(f"ai.process: Converted list to DocumentReferenceList with {len(documentList.references)} references")
|
logger.info(f"ai.process: Converted list to DocumentReferenceList with {len(documentList.references)} references")
|
||||||
else:
|
else:
|
||||||
|
|
@ -65,7 +143,9 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
simpleMode = parameters.get("simpleMode", False)
|
simpleMode = parameters.get("simpleMode", False)
|
||||||
|
|
||||||
if not aiPrompt:
|
if not aiPrompt:
|
||||||
logger.error(f"aiPrompt is missing or empty. Parameters: {parameters}")
|
param_keys = list(parameters.keys()) if isinstance(parameters, dict) else []
|
||||||
|
doc_count = len(parameters.get("documentList") or []) if isinstance(parameters.get("documentList"), (list, tuple)) else 0
|
||||||
|
logger.error(f"aiPrompt is missing or empty. Parameter keys: {param_keys}, documentList: {doc_count} item(s)")
|
||||||
return ActionResult.isFailure(
|
return ActionResult.isFailure(
|
||||||
error="AI prompt is required"
|
error="AI prompt is required"
|
||||||
)
|
)
|
||||||
|
|
@ -86,10 +166,9 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
mimeMap = {"txt": "text/plain", "json": "application/json", "html": "text/html", "md": "text/markdown", "csv": "text/csv", "xml": "application/xml"}
|
mimeMap = {"txt": "text/plain", "json": "application/json", "html": "text/html", "md": "text/markdown", "csv": "text/csv", "xml": "application/xml"}
|
||||||
output_mime_type = mimeMap.get(normalized_result_type, "text/plain") if normalized_result_type else "text/plain"
|
output_mime_type = mimeMap.get(normalized_result_type, "text/plain") if normalized_result_type else "text/plain"
|
||||||
|
|
||||||
# Phase 7.3: Pass both documentList and contentParts to AI service
|
# Phase 7.3: Pass documentList and/or contentParts to AI service
|
||||||
# (Extraction logic removed - handled by AI service)
|
contentParts: Optional[List[ContentPart]] = inline_content_parts
|
||||||
contentParts: Optional[List[ContentPart]] = None
|
if "contentParts" in parameters and not inline_content_parts:
|
||||||
if "contentParts" in parameters:
|
|
||||||
contentPartsParam = parameters.get("contentParts")
|
contentPartsParam = parameters.get("contentParts")
|
||||||
if contentPartsParam:
|
if contentPartsParam:
|
||||||
if isinstance(contentPartsParam, list):
|
if isinstance(contentPartsParam, list):
|
||||||
|
|
@ -203,8 +282,8 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
aiResponse = await self.services.ai.callAiContent(
|
aiResponse = await self.services.ai.callAiContent(
|
||||||
prompt=aiPrompt,
|
prompt=aiPrompt,
|
||||||
options=options,
|
options=options,
|
||||||
documentList=documentList, # Pass documentList - AI service handles extraction
|
documentList=documentList if not inline_content_parts else None, # Skip if using inline extracted parts
|
||||||
contentParts=contentParts, # Pass contentParts if provided (or None)
|
contentParts=contentParts, # From inline ActionDocuments (extracted in memory) or parameters
|
||||||
outputFormat=output_format, # Can be None - AI determines from prompt
|
outputFormat=output_format, # Can be None - AI determines from prompt
|
||||||
parentOperationId=operationId,
|
parentOperationId=operationId,
|
||||||
generationIntent=generationIntent # REQUIRED for DATA_GENERATE
|
generationIntent=generationIntent # REQUIRED for DATA_GENERATE
|
||||||
|
|
|
||||||
|
|
@ -261,35 +261,78 @@ Return JSON:
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add documents as attachments if provided
|
# Add documents as attachments if provided
|
||||||
|
# Supports: 1) inline ActionDocuments (dict with documentData from e.g. sharepoint.downloadFile)
|
||||||
|
# 2) docItem:... references (chat workflow documents)
|
||||||
if documentList:
|
if documentList:
|
||||||
message["attachments"] = []
|
message["attachments"] = []
|
||||||
for attachment_ref in documentList:
|
for attachment_ref in documentList:
|
||||||
# Get attachment document from service center
|
base64_content = None
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
attach_name = "attachment"
|
||||||
attachment_docs = self.services.chat.getChatDocumentsFromDocumentList(DocumentReferenceList.from_string_list([attachment_ref]))
|
attach_mime = "application/octet-stream"
|
||||||
if attachment_docs:
|
|
||||||
for doc in attachment_docs:
|
# Inline document: dict/object with documentData (from automation2 upstream, e.g. sharepoint.downloadFile)
|
||||||
file_id = getattr(doc, 'fileId', None)
|
is_inline = isinstance(attachment_ref, dict) and attachment_ref.get("documentData")
|
||||||
|
if not is_inline and hasattr(attachment_ref, "documentData"):
|
||||||
|
is_inline = bool(getattr(attachment_ref, "documentData", None))
|
||||||
|
if is_inline:
|
||||||
|
doc = attachment_ref
|
||||||
|
base64_content = doc.get("documentData") if isinstance(doc, dict) else getattr(doc, "documentData", None)
|
||||||
|
attach_name = (doc.get("documentName") or doc.get("fileName")) if isinstance(doc, dict) else (getattr(doc, "documentName", None) or getattr(doc, "fileName", "attachment"))
|
||||||
|
attach_mime = (doc.get("mimeType") or attach_mime) if isinstance(doc, dict) else (getattr(doc, "mimeType", None) or attach_mime)
|
||||||
|
if base64_content and attach_name:
|
||||||
|
message["attachments"].append({
|
||||||
|
"@odata.type": "#microsoft.graph.fileAttachment",
|
||||||
|
"name": attach_name,
|
||||||
|
"contentType": attach_mime,
|
||||||
|
"contentBytes": base64_content
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
# fileId in validationMetadata: resolve via getFileData (avoids large base64 in pipeline)
|
||||||
|
file_id = None
|
||||||
|
if isinstance(attachment_ref, dict):
|
||||||
|
vm = attachment_ref.get("validationMetadata") or {}
|
||||||
|
file_id = vm.get("fileId")
|
||||||
|
elif hasattr(attachment_ref, "validationMetadata"):
|
||||||
|
vm = getattr(attachment_ref, "validationMetadata") or {}
|
||||||
|
file_id = vm.get("fileId") if isinstance(vm, dict) else None
|
||||||
if file_id:
|
if file_id:
|
||||||
try:
|
try:
|
||||||
file_content = self.services.chat.getFileData(file_id)
|
file_content = self.services.chat.getFileData(file_id)
|
||||||
if file_content:
|
if file_content:
|
||||||
if isinstance(file_content, bytes):
|
base64_content = base64.b64encode(file_content if isinstance(file_content, bytes) else str(file_content).encode("utf-8")).decode("utf-8")
|
||||||
content_bytes = file_content
|
name = (attachment_ref.get("documentName") or attachment_ref.get("fileName", "attachment")) if isinstance(attachment_ref, dict) else (getattr(attachment_ref, "documentName", None) or getattr(attachment_ref, "fileName", "attachment"))
|
||||||
else:
|
mime = (attachment_ref.get("mimeType") or attach_mime) if isinstance(attachment_ref, dict) else (getattr(attachment_ref, "mimeType", None) or attach_mime)
|
||||||
content_bytes = str(file_content).encode('utf-8')
|
message["attachments"].append({
|
||||||
|
"@odata.type": "#microsoft.graph.fileAttachment",
|
||||||
|
"name": name,
|
||||||
|
"contentType": mime,
|
||||||
|
"contentBytes": base64_content
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("Could not load file %s for attachment: %s", file_id, e)
|
||||||
|
|
||||||
base64_content = base64.b64encode(content_bytes).decode('utf-8')
|
# docItem:... reference (chat workflow) – only when it's a string ref
|
||||||
|
attachment_docs = []
|
||||||
attachment = {
|
if isinstance(attachment_ref, str) and attachment_ref.strip():
|
||||||
|
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
||||||
|
attachment_docs = self.services.chat.getChatDocumentsFromDocumentList(DocumentReferenceList.from_string_list([attachment_ref]))
|
||||||
|
if attachment_docs:
|
||||||
|
for doc in attachment_docs:
|
||||||
|
fid = getattr(doc, 'fileId', None)
|
||||||
|
if fid:
|
||||||
|
try:
|
||||||
|
file_content = self.services.chat.getFileData(fid)
|
||||||
|
if file_content:
|
||||||
|
cb = file_content if isinstance(file_content, bytes) else str(file_content).encode('utf-8')
|
||||||
|
message["attachments"].append({
|
||||||
"@odata.type": "#microsoft.graph.fileAttachment",
|
"@odata.type": "#microsoft.graph.fileAttachment",
|
||||||
"name": doc.fileName,
|
"name": doc.fileName,
|
||||||
"contentType": doc.mimeType or "application/octet-stream",
|
"contentType": doc.mimeType or "application/octet-stream",
|
||||||
"contentBytes": base64_content
|
"contentBytes": base64.b64encode(cb).decode('utf-8')
|
||||||
}
|
})
|
||||||
message["attachments"].append(attachment)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error reading attachment file {doc.fileName}: {str(e)}")
|
logger.error("Error reading attachment file %s: %s", doc.fileName, e)
|
||||||
|
|
||||||
# Create the draft message
|
# Create the draft message
|
||||||
drafts_folder_id = self.folderManagement.getFolderId("Drafts", connection)
|
drafts_folder_id = self.folderManagement.getFolderId("Drafts", connection)
|
||||||
|
|
@ -331,11 +374,18 @@ Return JSON:
|
||||||
attachmentFilenames = []
|
attachmentFilenames = []
|
||||||
attachmentReferences = []
|
attachmentReferences = []
|
||||||
if documentList:
|
if documentList:
|
||||||
|
# Inline docs (dict with documentName): use directly
|
||||||
|
string_refs = [r for r in documentList if isinstance(r, str)]
|
||||||
|
inline_docs = [r for r in documentList if isinstance(r, dict)]
|
||||||
|
for d in inline_docs:
|
||||||
|
name = d.get("documentName") or d.get("fileName")
|
||||||
|
if name:
|
||||||
|
attachmentFilenames.append(name)
|
||||||
|
if string_refs:
|
||||||
try:
|
try:
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
||||||
attached_docs = self.services.chat.getChatDocumentsFromDocumentList(DocumentReferenceList.from_string_list(documentList)) or []
|
attached_docs = self.services.chat.getChatDocumentsFromDocumentList(DocumentReferenceList.from_string_list(string_refs)) or []
|
||||||
attachmentFilenames = [getattr(doc, 'fileName', '') for doc in attached_docs if getattr(doc, 'fileName', None)]
|
attachmentFilenames.extend(getattr(doc, 'fileName', '') for doc in attached_docs if getattr(doc, 'fileName', None))
|
||||||
# Store normalized document references (with filenames) - use normalized_ai_attachments if available
|
|
||||||
attachmentReferences = normalized_ai_attachments if normalized_ai_attachments else [self.services.chat.getDocumentReferenceFromChatDocument(d) for d in attached_docs]
|
attachmentReferences = normalized_ai_attachments if normalized_ai_attachments else [self.services.chat.getDocumentReferenceFromChatDocument(d) for d in attached_docs]
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -157,15 +157,22 @@ class MethodOutlook(MethodBase):
|
||||||
name="context",
|
name="context",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXTAREA,
|
frontendType=FrontendType.TEXTAREA,
|
||||||
required=True,
|
required=False,
|
||||||
description="Detailed context for composing the email"
|
description="Detailed context for AI composition (omit when emailContent provided)"
|
||||||
|
),
|
||||||
|
"emailContent": WorkflowActionParameter(
|
||||||
|
name="emailContent",
|
||||||
|
type="dict",
|
||||||
|
frontendType=FrontendType.HIDDEN,
|
||||||
|
required=False,
|
||||||
|
description="Direct subject/body/to from upstream (skips AI composition)"
|
||||||
),
|
),
|
||||||
"documentList": WorkflowActionParameter(
|
"documentList": WorkflowActionParameter(
|
||||||
name="documentList",
|
name="documentList",
|
||||||
type="List[str]",
|
type="List[Any]",
|
||||||
frontendType=FrontendType.DOCUMENT_REFERENCE,
|
frontendType=FrontendType.DOCUMENT_REFERENCE,
|
||||||
required=False,
|
required=False,
|
||||||
description="Document references for context/attachments"
|
description="Document references or inline ActionDocuments for attachments"
|
||||||
),
|
),
|
||||||
"cc": WorkflowActionParameter(
|
"cc": WorkflowActionParameter(
|
||||||
name="cc",
|
name="cc",
|
||||||
|
|
|
||||||
|
|
@ -14,28 +14,51 @@ async def copyFile(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
if not connectionReference:
|
if not connectionReference:
|
||||||
return ActionResult.isFailure(error="connectionReference parameter is required")
|
return ActionResult.isFailure(error="connectionReference parameter is required")
|
||||||
|
|
||||||
siteIdParam = parameters.get("siteId")
|
# Set SharePoint access token first – required before siteDiscovery/sharepoint calls
|
||||||
if not siteIdParam:
|
connection = self.connection.getMicrosoftConnection(connectionReference)
|
||||||
return ActionResult.isFailure(error="siteId parameter is required")
|
if not connection:
|
||||||
|
return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference")
|
||||||
|
|
||||||
sourceFolder = parameters.get("sourceFolder")
|
sourcePath = (parameters.get("sourcePath") or parameters.get("sourcePathQuery") or "").strip()
|
||||||
if not sourceFolder:
|
destPath = (parameters.get("destPath") or parameters.get("destPathQuery") or "").strip()
|
||||||
return ActionResult.isFailure(error="sourceFolder parameter is required")
|
|
||||||
|
|
||||||
sourceFile = parameters.get("sourceFile")
|
|
||||||
if not sourceFile:
|
|
||||||
return ActionResult.isFailure(error="sourceFile parameter is required")
|
|
||||||
|
|
||||||
destFolder = parameters.get("destFolder")
|
|
||||||
if not destFolder:
|
|
||||||
return ActionResult.isFailure(error="destFolder parameter is required")
|
|
||||||
|
|
||||||
destFile = parameters.get("destFile")
|
|
||||||
if not destFile:
|
|
||||||
return ActionResult.isFailure(error="destFile parameter is required")
|
|
||||||
|
|
||||||
# Extract siteId from document if it's a reference
|
|
||||||
siteId = None
|
siteId = None
|
||||||
|
sourceFolder = None
|
||||||
|
sourceFile = None
|
||||||
|
destFolder = None
|
||||||
|
destFile = None
|
||||||
|
|
||||||
|
if sourcePath and destPath and sourcePath.startswith("/sites/") and destPath.startswith("/sites/"):
|
||||||
|
parsedSource = self.services.sharepoint.extractSiteFromStandardPath(sourcePath)
|
||||||
|
parsedDest = self.services.sharepoint.extractSiteFromStandardPath(destPath)
|
||||||
|
if parsedSource and parsedDest:
|
||||||
|
innerSrc = (parsedSource.get("innerPath") or "").strip().rstrip("/")
|
||||||
|
innerDest = (parsedDest.get("innerPath") or "").strip().rstrip("/")
|
||||||
|
if innerSrc:
|
||||||
|
if "/" in innerSrc:
|
||||||
|
sourceFolder = innerSrc.rsplit("/", 1)[0]
|
||||||
|
sourceFile = innerSrc.rsplit("/", 1)[-1]
|
||||||
|
else:
|
||||||
|
sourceFolder = ""
|
||||||
|
sourceFile = innerSrc
|
||||||
|
destFolder = innerDest
|
||||||
|
destFile = sourceFile
|
||||||
|
sites, _ = await self.siteDiscovery.resolveSitesFromPathQuery(sourcePath)
|
||||||
|
if sites:
|
||||||
|
siteId = sites[0].get("id")
|
||||||
|
|
||||||
|
if not siteId or not sourceFolder or not sourceFile or not destFolder:
|
||||||
|
siteIdParam = parameters.get("siteId")
|
||||||
|
sourceFolder = parameters.get("sourceFolder")
|
||||||
|
sourceFile = parameters.get("sourceFile")
|
||||||
|
destFolder = parameters.get("destFolder")
|
||||||
|
destFile = parameters.get("destFile")
|
||||||
|
if not siteIdParam:
|
||||||
|
return ActionResult.isFailure(error="Either sourcePath+destPath or siteId, sourceFolder, sourceFile, destFolder, destFile are required")
|
||||||
|
if not sourceFolder or not sourceFile or not destFolder or not destFile:
|
||||||
|
return ActionResult.isFailure(error="sourceFolder, sourceFile, destFolder, and destFile are required")
|
||||||
|
if not destFile:
|
||||||
|
destFile = sourceFile
|
||||||
if isinstance(siteIdParam, str):
|
if isinstance(siteIdParam, str):
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
||||||
try:
|
try:
|
||||||
|
|
@ -44,21 +67,15 @@ async def copyFile(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
if chatDocuments and len(chatDocuments) > 0:
|
if chatDocuments and len(chatDocuments) > 0:
|
||||||
siteInfoJson = json.loads(chatDocuments[0].documentData)
|
siteInfoJson = json.loads(chatDocuments[0].documentData)
|
||||||
siteId = siteInfoJson.get("id")
|
siteId = siteInfoJson.get("id")
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not siteId:
|
if not siteId:
|
||||||
siteId = siteIdParam
|
siteId = siteIdParam
|
||||||
else:
|
else:
|
||||||
siteId = siteIdParam
|
siteId = siteIdParam
|
||||||
|
|
||||||
if not siteId:
|
if not siteId:
|
||||||
return ActionResult.isFailure(error="Could not extract siteId from parameter")
|
return ActionResult.isFailure(error="Could not resolve siteId")
|
||||||
|
|
||||||
# Get Microsoft connection
|
|
||||||
connection = self.connection.getMicrosoftConnection(connectionReference)
|
|
||||||
if not connection:
|
|
||||||
return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference")
|
|
||||||
|
|
||||||
# Copy file
|
# Copy file
|
||||||
await self.services.sharepoint.copyFileAsync(
|
await self.services.sharepoint.copyFileAsync(
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,39 @@ async def downloadFileByPath(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
if not connectionReference:
|
if not connectionReference:
|
||||||
return ActionResult.isFailure(error="connectionReference parameter is required")
|
return ActionResult.isFailure(error="connectionReference parameter is required")
|
||||||
|
|
||||||
|
# Set SharePoint access token first – required before siteDiscovery/sharepoint calls
|
||||||
|
connection = self.connection.getMicrosoftConnection(connectionReference)
|
||||||
|
if not connection:
|
||||||
|
return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference")
|
||||||
|
|
||||||
|
pathQuery = (parameters.get("pathQuery") or parameters.get("path") or "").strip()
|
||||||
siteIdParam = parameters.get("siteId")
|
siteIdParam = parameters.get("siteId")
|
||||||
if not siteIdParam:
|
|
||||||
return ActionResult.isFailure(error="siteId parameter is required")
|
|
||||||
|
|
||||||
filePath = parameters.get("filePath")
|
filePath = parameters.get("filePath")
|
||||||
if not filePath:
|
# If filePath looks like full SharePoint path, use as pathQuery fallback
|
||||||
return ActionResult.isFailure(error="filePath parameter is required")
|
if not pathQuery and filePath and isinstance(filePath, str) and filePath.strip().startswith("/sites/"):
|
||||||
|
pathQuery = filePath.strip()
|
||||||
|
|
||||||
# Extract siteId from document if it's a reference
|
|
||||||
siteId = None
|
siteId = None
|
||||||
|
innerPath = None
|
||||||
|
|
||||||
|
# Option 1: pathQuery provided (e.g. /sites/SiteName/Shared Documents/file.pdf) – resolve site and inner path
|
||||||
|
if pathQuery and pathQuery != "*":
|
||||||
|
sites, errorMsg = await self.siteDiscovery.resolveSitesFromPathQuery(pathQuery)
|
||||||
|
if errorMsg:
|
||||||
|
return ActionResult.isFailure(error=errorMsg)
|
||||||
|
if not sites:
|
||||||
|
return ActionResult.isFailure(error="Could not resolve site from pathQuery")
|
||||||
|
parsedPath = self.services.sharepoint.extractSiteFromStandardPath(pathQuery)
|
||||||
|
if not parsedPath:
|
||||||
|
return ActionResult.isFailure(error="pathQuery must be a standard SharePoint path (e.g. /sites/SiteName/Shared Documents/file.pdf)")
|
||||||
|
innerPath = (parsedPath.get("innerPath") or "").strip()
|
||||||
|
if not innerPath:
|
||||||
|
return ActionResult.isFailure(error="pathQuery must include a file path (e.g. /sites/SiteName/Shared Documents/file.pdf)")
|
||||||
|
siteId = sites[0].get("id")
|
||||||
|
filePath = innerPath
|
||||||
|
elif siteIdParam and filePath:
|
||||||
|
# Option 2: siteId + filePath provided directly
|
||||||
if isinstance(siteIdParam, str):
|
if isinstance(siteIdParam, str):
|
||||||
# Try to parse from document reference
|
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
||||||
try:
|
try:
|
||||||
docList = DocumentReferenceList.from_string_list([siteIdParam])
|
docList = DocumentReferenceList.from_string_list([siteIdParam])
|
||||||
|
|
@ -35,24 +56,19 @@ async def downloadFileByPath(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
if chatDocuments and len(chatDocuments) > 0:
|
if chatDocuments and len(chatDocuments) > 0:
|
||||||
siteInfoJson = json.loads(chatDocuments[0].documentData)
|
siteInfoJson = json.loads(chatDocuments[0].documentData)
|
||||||
siteId = siteInfoJson.get("id")
|
siteId = siteInfoJson.get("id")
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not siteId:
|
if not siteId:
|
||||||
# Assume it's the site ID directly
|
|
||||||
siteId = siteIdParam
|
siteId = siteIdParam
|
||||||
else:
|
else:
|
||||||
siteId = siteIdParam
|
siteId = siteIdParam
|
||||||
|
else:
|
||||||
|
return ActionResult.isFailure(error="Either pathQuery (e.g. /sites/SiteName/Shared Documents/file.pdf) or both siteId and filePath are required")
|
||||||
|
|
||||||
if not siteId:
|
if not siteId or not filePath:
|
||||||
return ActionResult.isFailure(error="Could not extract siteId from parameter")
|
return ActionResult.isFailure(error="Could not resolve siteId and file path from parameters")
|
||||||
|
|
||||||
# Get Microsoft connection
|
# Download file (connection/token already set above)
|
||||||
connection = self.connection.getMicrosoftConnection(connectionReference)
|
|
||||||
if not connection:
|
|
||||||
return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference")
|
|
||||||
|
|
||||||
# Download file
|
|
||||||
fileContent = await self.services.sharepoint.downloadFileByPath(
|
fileContent = await self.services.sharepoint.downloadFileByPath(
|
||||||
siteId=siteId,
|
siteId=siteId,
|
||||||
filePath=filePath
|
filePath=filePath
|
||||||
|
|
@ -73,7 +89,19 @@ async def downloadFileByPath(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
"downloadFileByPath"
|
"downloadFileByPath"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Encode as base64
|
# Save to user's Files (FileItem + FileData) via interfaceDbComponent – appears in Files UI
|
||||||
|
fileItem = None
|
||||||
|
db = getattr(self.services, "interfaceDbComponent", None)
|
||||||
|
if db:
|
||||||
|
try:
|
||||||
|
mimeType = db.getMimeType(filename) if hasattr(db, "getMimeType") else "application/octet-stream"
|
||||||
|
fileItem = db.createFile(name=filename, mimeType=mimeType, content=fileContent)
|
||||||
|
db.createFileData(fileItem.id, fileContent)
|
||||||
|
logger.info(f"Saved SharePoint file to user Files: {filename} (id={fileItem.id})")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Could not save to user Files: {e}")
|
||||||
|
|
||||||
|
# Encode as base64 for workflow context (AI, data nodes)
|
||||||
fileBase64 = base64.b64encode(fileContent).decode('utf-8')
|
fileBase64 = base64.b64encode(fileContent).decode('utf-8')
|
||||||
|
|
||||||
validationMetadata = self._createValidationMetadata(
|
validationMetadata = self._createValidationMetadata(
|
||||||
|
|
@ -82,6 +110,8 @@ async def downloadFileByPath(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
filePath=filePath,
|
filePath=filePath,
|
||||||
fileSize=len(fileContent)
|
fileSize=len(fileContent)
|
||||||
)
|
)
|
||||||
|
if fileItem:
|
||||||
|
validationMetadata["fileId"] = fileItem.id
|
||||||
|
|
||||||
document = ActionDocument(
|
document = ActionDocument(
|
||||||
documentName=filename,
|
documentName=filename,
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,56 @@ async def readDocuments(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
self.services.chat.progressLogFinish(operationId, False)
|
self.services.chat.progressLogFinish(operationId, False)
|
||||||
return ActionResult.isFailure(error="Either documentList must contain findDocumentPath result with file information, or pathQuery must be provided. Use findDocumentPath first to get file paths, or provide pathQuery directly.")
|
return ActionResult.isFailure(error="Either documentList must contain findDocumentPath result with file information, or pathQuery must be provided. Use findDocumentPath first to get file paths, or provide pathQuery directly.")
|
||||||
|
|
||||||
# This should never be reached if logic above is correct
|
# When we have pathQuery + sites but no sharePointFileIds (e.g. user selected from browse tree),
|
||||||
|
# download the file by path
|
||||||
|
if pathQuery and pathQuery.strip() != "" and pathQuery.strip() != "*" and sites and not sharePointFileIds:
|
||||||
|
parsedPath = self.services.sharepoint.extractSiteFromStandardPath(pathQuery)
|
||||||
|
if parsedPath:
|
||||||
|
innerPath = (parsedPath.get("innerPath") or "").strip()
|
||||||
|
if not innerPath:
|
||||||
|
if operationId:
|
||||||
|
self.services.chat.progressLogFinish(operationId, False)
|
||||||
|
return ActionResult.isFailure(error="pathQuery must include a file path (e.g. /sites/SiteName/Shared Documents/file.pdf)")
|
||||||
|
siteId = sites[0].get("id")
|
||||||
|
if not siteId:
|
||||||
|
if operationId:
|
||||||
|
self.services.chat.progressLogFinish(operationId, False)
|
||||||
|
return ActionResult.isFailure(error="Could not resolve site ID from pathQuery")
|
||||||
|
self.services.chat.progressLogUpdate(operationId, 0.5, f"Reading file from path: {innerPath}")
|
||||||
|
fileContent = await self.services.sharepoint.downloadFileByPath(siteId=siteId, filePath=innerPath)
|
||||||
|
if fileContent is None:
|
||||||
|
if operationId:
|
||||||
|
self.services.chat.progressLogFinish(operationId, False)
|
||||||
|
return ActionResult.isFailure(error=f"File not found or could not be downloaded: {innerPath}")
|
||||||
|
fileName = innerPath.split("/")[-1] if "/" in innerPath else innerPath
|
||||||
|
mimeType = "application/octet-stream"
|
||||||
|
if fileName.endswith(".pdf"):
|
||||||
|
mimeType = "application/pdf"
|
||||||
|
elif fileName.endswith(".txt"):
|
||||||
|
mimeType = "text/plain"
|
||||||
|
elif fileName.endswith(".json"):
|
||||||
|
mimeType = "application/json"
|
||||||
|
base64Content = base64.b64encode(fileContent).decode("utf-8")
|
||||||
|
validationMetadata = {
|
||||||
|
"actionType": "sharepoint.readDocuments",
|
||||||
|
"fileName": fileName,
|
||||||
|
"sharepointFileId": None,
|
||||||
|
"siteName": sites[0].get("displayName"),
|
||||||
|
"mimeType": mimeType,
|
||||||
|
"contentType": "binary",
|
||||||
|
"size": len(fileContent),
|
||||||
|
"includeMetadata": includeMetadata
|
||||||
|
}
|
||||||
|
actionDoc = ActionDocument(
|
||||||
|
documentName=fileName,
|
||||||
|
documentData=base64Content,
|
||||||
|
mimeType=mimeType,
|
||||||
|
validationMetadata=validationMetadata
|
||||||
|
)
|
||||||
|
self.services.chat.progressLogUpdate(operationId, 0.9, f"Read 1 document(s)")
|
||||||
|
self.services.chat.progressLogFinish(operationId, True)
|
||||||
|
return ActionResult.isSuccess(documents=[actionDoc])
|
||||||
|
|
||||||
if operationId:
|
if operationId:
|
||||||
self.services.chat.progressLogFinish(operationId, False)
|
self.services.chat.progressLogFinish(operationId, False)
|
||||||
return ActionResult.isFailure(error="Unexpected error: could not process documentList or pathQuery")
|
return ActionResult.isFailure(error="Unexpected error: could not process documentList or pathQuery")
|
||||||
|
|
|
||||||
|
|
@ -15,24 +15,31 @@ async def uploadFile(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
if not connectionReference:
|
if not connectionReference:
|
||||||
return ActionResult.isFailure(error="connectionReference parameter is required")
|
return ActionResult.isFailure(error="connectionReference parameter is required")
|
||||||
|
|
||||||
siteIdParam = parameters.get("siteId")
|
|
||||||
if not siteIdParam:
|
|
||||||
return ActionResult.isFailure(error="siteId parameter is required")
|
|
||||||
|
|
||||||
folderPath = parameters.get("folderPath")
|
|
||||||
if not folderPath:
|
|
||||||
return ActionResult.isFailure(error="folderPath parameter is required")
|
|
||||||
|
|
||||||
fileName = parameters.get("fileName")
|
|
||||||
if not fileName:
|
|
||||||
return ActionResult.isFailure(error="fileName parameter is required")
|
|
||||||
|
|
||||||
contentParam = parameters.get("content")
|
contentParam = parameters.get("content")
|
||||||
if not contentParam:
|
if not contentParam:
|
||||||
return ActionResult.isFailure(error="content parameter is required")
|
return ActionResult.isFailure(error="content parameter is required")
|
||||||
|
|
||||||
# Extract siteId from document if it's a reference
|
# Resolve siteId and folderPath: pathQuery (path) or explicit siteId+folderPath
|
||||||
|
pathQuery = (parameters.get("pathQuery") or parameters.get("path") or "").strip()
|
||||||
|
siteIdParam = parameters.get("siteId")
|
||||||
|
folderPath = parameters.get("folderPath")
|
||||||
siteId = None
|
siteId = None
|
||||||
|
|
||||||
|
if pathQuery and pathQuery != "*":
|
||||||
|
# Option 1: pathQuery (e.g. /sites/host,siteId,webId/15. Persoenliche Ordner/Ida Dittrich/)
|
||||||
|
sites, errorMsg = await self.siteDiscovery.resolveSitesFromPathQuery(pathQuery)
|
||||||
|
if errorMsg:
|
||||||
|
return ActionResult.isFailure(error=errorMsg)
|
||||||
|
if not sites:
|
||||||
|
return ActionResult.isFailure(error="Could not resolve site from path")
|
||||||
|
parsedPath = self.services.sharepoint.extractSiteFromStandardPath(pathQuery)
|
||||||
|
if not parsedPath:
|
||||||
|
return ActionResult.isFailure(error="path must be a standard SharePoint path (e.g. /sites/SiteName/Shared Documents/Folder)")
|
||||||
|
innerPath = (parsedPath.get("innerPath") or "").strip().rstrip("/")
|
||||||
|
siteId = sites[0].get("id")
|
||||||
|
folderPath = innerPath
|
||||||
|
elif siteIdParam and folderPath:
|
||||||
|
# Option 2: explicit siteId + folderPath
|
||||||
if isinstance(siteIdParam, str):
|
if isinstance(siteIdParam, str):
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
||||||
try:
|
try:
|
||||||
|
|
@ -41,24 +48,50 @@ async def uploadFile(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
if chatDocuments and len(chatDocuments) > 0:
|
if chatDocuments and len(chatDocuments) > 0:
|
||||||
siteInfoJson = json.loads(chatDocuments[0].documentData)
|
siteInfoJson = json.loads(chatDocuments[0].documentData)
|
||||||
siteId = siteInfoJson.get("id")
|
siteId = siteInfoJson.get("id")
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not siteId:
|
if not siteId:
|
||||||
siteId = siteIdParam
|
siteId = siteIdParam
|
||||||
else:
|
else:
|
||||||
siteId = siteIdParam
|
siteId = siteIdParam
|
||||||
|
else:
|
||||||
|
return ActionResult.isFailure(error="Either path (e.g. /sites/.../Folder) or both siteId and folderPath are required")
|
||||||
|
|
||||||
if not siteId:
|
if not siteId:
|
||||||
return ActionResult.isFailure(error="Could not extract siteId from parameter")
|
return ActionResult.isFailure(error="Could not resolve siteId")
|
||||||
|
|
||||||
# Get file content from document
|
# fileName: from param or from content document
|
||||||
|
fileName = parameters.get("fileName")
|
||||||
|
if not fileName and contentParam:
|
||||||
|
content = contentParam[0] if isinstance(contentParam, (list, tuple)) and contentParam else contentParam
|
||||||
|
if isinstance(content, dict):
|
||||||
|
fileName = content.get("documentName") or content.get("fileName")
|
||||||
|
elif hasattr(content, "documentName"):
|
||||||
|
fileName = getattr(content, "documentName", None) or getattr(content, "fileName", None)
|
||||||
|
if not fileName:
|
||||||
|
fileName = "file"
|
||||||
|
|
||||||
|
# Get file content: support inline ActionDocument (from automation2 e.g. sharepoint.downloadFile)
|
||||||
|
# or docItem references (chat workflow)
|
||||||
|
content = contentParam[0] if isinstance(contentParam, (list, tuple)) and contentParam else contentParam
|
||||||
|
fileContentBase64 = None
|
||||||
|
if isinstance(content, dict) and content.get("documentData"):
|
||||||
|
fileContentBase64 = content.get("documentData")
|
||||||
|
elif hasattr(content, "documentData") and content.documentData:
|
||||||
|
fileContentBase64 = content.documentData
|
||||||
|
elif isinstance(content, dict) and (content.get("validationMetadata") or {}).get("fileId"):
|
||||||
|
file_id = content["validationMetadata"]["fileId"]
|
||||||
|
try:
|
||||||
|
raw = self.services.chat.getFileData(file_id)
|
||||||
|
fileContentBase64 = base64.b64encode(raw if isinstance(raw, bytes) else str(raw).encode("utf-8")).decode("utf-8")
|
||||||
|
except Exception as e:
|
||||||
|
return ActionResult.isFailure(error=f"Could not load file content from fileId {file_id}: {e}")
|
||||||
|
if not fileContentBase64:
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
from modules.datamodels.datamodelDocref import DocumentReferenceList
|
||||||
docList = DocumentReferenceList.from_string_list([contentParam] if isinstance(contentParam, str) else contentParam)
|
docList = DocumentReferenceList.from_string_list([content] if isinstance(content, str) else content)
|
||||||
chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList)
|
chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList)
|
||||||
if not chatDocuments or len(chatDocuments) == 0:
|
if not chatDocuments or len(chatDocuments) == 0:
|
||||||
return ActionResult.isFailure(error="Could not get file content from document reference")
|
return ActionResult.isFailure(error="Could not get file content from document reference")
|
||||||
|
|
||||||
fileContentBase64 = chatDocuments[0].documentData
|
fileContentBase64 = chatDocuments[0].documentData
|
||||||
|
|
||||||
# Decode base64
|
# Decode base64
|
||||||
|
|
|
||||||
|
|
@ -274,19 +274,26 @@ class MethodSharepoint(MethodBase):
|
||||||
required=True,
|
required=True,
|
||||||
description="Microsoft connection label"
|
description="Microsoft connection label"
|
||||||
),
|
),
|
||||||
|
"pathQuery": WorkflowActionParameter(
|
||||||
|
name="pathQuery",
|
||||||
|
type="str",
|
||||||
|
frontendType=FrontendType.TEXT,
|
||||||
|
required=False,
|
||||||
|
description="Full SharePoint path (e.g. /sites/SiteName/Shared Documents/file.pdf). When provided, siteId and filePath are derived automatically."
|
||||||
|
),
|
||||||
"siteId": WorkflowActionParameter(
|
"siteId": WorkflowActionParameter(
|
||||||
name="siteId",
|
name="siteId",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXT,
|
frontendType=FrontendType.TEXT,
|
||||||
required=True,
|
required=False,
|
||||||
description="SharePoint site ID (from findSiteByUrl result) or document reference containing site info"
|
description="SharePoint site ID (optional when pathQuery is provided)"
|
||||||
),
|
),
|
||||||
"filePath": WorkflowActionParameter(
|
"filePath": WorkflowActionParameter(
|
||||||
name="filePath",
|
name="filePath",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXT,
|
frontendType=FrontendType.TEXT,
|
||||||
required=True,
|
required=False,
|
||||||
description="Full file path relative to site root (e.g., /General/50 Docs hosted by SELISE/file.xlsx)"
|
description="File path relative to site root (optional when pathQuery is provided)"
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
execute=downloadFileByPath.__get__(self, self.__class__)
|
execute=downloadFileByPath.__get__(self, self.__class__)
|
||||||
|
|
@ -303,40 +310,19 @@ class MethodSharepoint(MethodBase):
|
||||||
required=True,
|
required=True,
|
||||||
description="Microsoft connection label"
|
description="Microsoft connection label"
|
||||||
),
|
),
|
||||||
"siteId": WorkflowActionParameter(
|
"sourcePath": WorkflowActionParameter(
|
||||||
name="siteId",
|
name="sourcePath",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXT,
|
frontendType=FrontendType.TEXT,
|
||||||
required=True,
|
required=True,
|
||||||
description="SharePoint site ID (from findSiteByUrl result) or document reference containing site info"
|
description="Full path to source file (e.g. /sites/.../folder/file.pdf)"
|
||||||
),
|
),
|
||||||
"sourceFolder": WorkflowActionParameter(
|
"destPath": WorkflowActionParameter(
|
||||||
name="sourceFolder",
|
name="destPath",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXT,
|
frontendType=FrontendType.TEXT,
|
||||||
required=True,
|
required=True,
|
||||||
description="Source folder path relative to site root"
|
description="Full path to destination folder (e.g. /sites/.../folder)"
|
||||||
),
|
|
||||||
"sourceFile": WorkflowActionParameter(
|
|
||||||
name="sourceFile",
|
|
||||||
type="str",
|
|
||||||
frontendType=FrontendType.TEXT,
|
|
||||||
required=True,
|
|
||||||
description="Source file name"
|
|
||||||
),
|
|
||||||
"destFolder": WorkflowActionParameter(
|
|
||||||
name="destFolder",
|
|
||||||
type="str",
|
|
||||||
frontendType=FrontendType.TEXT,
|
|
||||||
required=True,
|
|
||||||
description="Destination folder path relative to site root"
|
|
||||||
),
|
|
||||||
"destFile": WorkflowActionParameter(
|
|
||||||
name="destFile",
|
|
||||||
type="str",
|
|
||||||
frontendType=FrontendType.TEXT,
|
|
||||||
required=True,
|
|
||||||
description="Destination file name"
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
execute=copyFile.__get__(self, self.__class__)
|
execute=copyFile.__get__(self, self.__class__)
|
||||||
|
|
@ -353,33 +339,40 @@ class MethodSharepoint(MethodBase):
|
||||||
required=True,
|
required=True,
|
||||||
description="Microsoft connection label"
|
description="Microsoft connection label"
|
||||||
),
|
),
|
||||||
|
"pathQuery": WorkflowActionParameter(
|
||||||
|
name="pathQuery",
|
||||||
|
type="str",
|
||||||
|
frontendType=FrontendType.TEXT,
|
||||||
|
required=False,
|
||||||
|
description="Target folder path (e.g. /sites/.../Folder). When provided, siteId and folderPath are derived. Alternative to explicit siteId+folderPath."
|
||||||
|
),
|
||||||
"siteId": WorkflowActionParameter(
|
"siteId": WorkflowActionParameter(
|
||||||
name="siteId",
|
name="siteId",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXT,
|
frontendType=FrontendType.TEXT,
|
||||||
required=True,
|
required=False,
|
||||||
description="SharePoint site ID (from findSiteByUrl result) or document reference containing site info"
|
description="SharePoint site ID (when not using pathQuery)"
|
||||||
),
|
),
|
||||||
"folderPath": WorkflowActionParameter(
|
"folderPath": WorkflowActionParameter(
|
||||||
name="folderPath",
|
name="folderPath",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXT,
|
frontendType=FrontendType.TEXT,
|
||||||
required=True,
|
required=False,
|
||||||
description="Folder path relative to site root"
|
description="Folder path relative to site root (when not using pathQuery)"
|
||||||
),
|
),
|
||||||
"fileName": WorkflowActionParameter(
|
"fileName": WorkflowActionParameter(
|
||||||
name="fileName",
|
name="fileName",
|
||||||
type="str",
|
type="str",
|
||||||
frontendType=FrontendType.TEXT,
|
frontendType=FrontendType.TEXT,
|
||||||
required=True,
|
required=False,
|
||||||
description="File name"
|
description="File name (defaults to document name when content from context)"
|
||||||
),
|
),
|
||||||
"content": WorkflowActionParameter(
|
"content": WorkflowActionParameter(
|
||||||
name="content",
|
name="content",
|
||||||
type="str",
|
type="Any",
|
||||||
frontendType=FrontendType.DOCUMENT_REFERENCE,
|
frontendType=FrontendType.DOCUMENT_REFERENCE,
|
||||||
required=True,
|
required=True,
|
||||||
description="Document reference containing file content as base64-encoded bytes"
|
description="File content from context (upstream document) or document reference"
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
execute=uploadFile.__get__(self, self.__class__)
|
execute=uploadFile.__get__(self, self.__class__)
|
||||||
|
|
|
||||||
|
|
@ -69,15 +69,14 @@ class ActionExecutor:
|
||||||
|
|
||||||
logger.info(f"=== TASK {taskNum} ACTION {actionNum}: {action.execMethod}.{action.execAction} ===")
|
logger.info(f"=== TASK {taskNum} ACTION {actionNum}: {action.execMethod}.{action.execAction} ===")
|
||||||
|
|
||||||
# Log input parameters
|
# Log input parameters (redact documentData to avoid dumping base64 in logs)
|
||||||
inputDocs = action.execParameters.get('documentList', [])
|
inputDocs = action.execParameters.get('documentList', [])
|
||||||
inputConnections = action.execParameters.get('connections', [])
|
inputConnections = action.execParameters.get('connections', [])
|
||||||
logger.info(f"Input documents: {inputDocs} (type: {type(inputDocs)})")
|
doc_preview = f"{len(inputDocs)} item(s)" if isinstance(inputDocs, (list, tuple)) else str(type(inputDocs))
|
||||||
|
logger.info(f"Input documents: {doc_preview} (type: {type(inputDocs).__name__})")
|
||||||
if inputConnections:
|
if inputConnections:
|
||||||
logger.info(f"Input connections: {inputConnections}")
|
logger.info(f"Input connections: {inputConnections}")
|
||||||
|
logger.debug(f"Action parameters keys: {list(action.execParameters.keys())}")
|
||||||
# Log all action parameters for debugging
|
|
||||||
logger.info(f"All action parameters: {action.execParameters}")
|
|
||||||
|
|
||||||
enhancedParameters = action.execParameters.copy()
|
enhancedParameters = action.execParameters.copy()
|
||||||
if action.expectedDocumentFormats:
|
if action.expectedDocumentFormats:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
# TASK: Plan Document Structure (Documents + Chapters)
|
||||||
|
|
||||||
|
This is a STRUCTURE PLANNING task. You define which documents to create and which chapters each document will have.
|
||||||
|
Chapter CONTENT will be generated in a later step - here you only plan the STRUCTURE and assign content references.
|
||||||
|
Return EXACTLY ONE complete JSON object. Do not generate multiple JSON objects, alternatives, or variations. Do not use separators like "---" between JSON objects.
|
||||||
|
|
||||||
|
## USER REQUEST (for context)
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## AVAILABLE CONTENT PARTS
|
||||||
|
|
||||||
|
(No content parts available)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE
|
||||||
|
|
||||||
|
CRITICAL: Every chapter MUST have contentParts assigned if it relates to documents/images/data from the user request.
|
||||||
|
If the user request mentions documents/images/data, then EVERY chapter that generates content related to those references MUST assign the relevant ContentParts explicitly.
|
||||||
|
|
||||||
|
Assignment logic:
|
||||||
|
- If chapter DISPLAYS a document/image → assign "object" format ContentPart with "caption"
|
||||||
|
- If chapter generates text content ABOUT a document/image/data → assign ContentPart with "instruction":
|
||||||
|
- Prefer "extracted" format if available (contains analyzed/extracted content)
|
||||||
|
- If only "object" format is available, use "object" format with "instruction" (to write ABOUT the image/document)
|
||||||
|
- If chapter's generationHint or purpose relates to a document/image/data mentioned in user request → it MUST have ContentParts assigned
|
||||||
|
- Multiple chapters might assign the same ContentPart (e.g., one chapter displays image, another writes about it)
|
||||||
|
- Use ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
- Empty contentParts are only allowed if chapter generates content WITHOUT referencing any documents/images/data from the user request
|
||||||
|
|
||||||
|
CRITICAL RULE: If the user request mentions BOTH:
|
||||||
|
a) Documents/images/data (listed in AVAILABLE CONTENT PARTS above), AND
|
||||||
|
b) Generic content types (article text, main content, body text, etc.)
|
||||||
|
Then chapters that generate those generic content types MUST assign the relevant ContentParts, because the content should relate to or be based on the provided documents/images/data.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential information only
|
||||||
|
- AVOID verbose, lengthy, or repetitive text - be concise and direct
|
||||||
|
- Prioritize FACTS over filler text - no introductions like "In this chapter..."
|
||||||
|
- Minimize system resources: shorter content = faster processing
|
||||||
|
- Quality over quantity: precise, meaningful content rather than padding
|
||||||
|
|
||||||
|
## CHAPTER STRUCTURE REQUIREMENTS
|
||||||
|
- Generate chapters based on USER REQUEST - analyze what structure the user wants
|
||||||
|
- Create ONLY the minimum chapters needed to cover the user's request - avoid over-structuring
|
||||||
|
- HARD LIMIT: Maximum 7 chapters per document. If the topic can be covered in fewer, prefer fewer. Combine related topics into single chapters rather than creating many small ones.
|
||||||
|
- IMPORTANT: Each chapter MUST have ALL these fields:
|
||||||
|
- id: Unique identifier (e.g., "chapter_1")
|
||||||
|
- level: Heading level (1, 2, 3, etc.)
|
||||||
|
- title: Chapter title
|
||||||
|
- contentParts: Object mapping ContentPart IDs to usage instructions (MUST assign if chapter relates to documents/data from user request)
|
||||||
|
- generationHint: Description of what content to generate (including formatting/styling requirements)
|
||||||
|
- sections: Empty array [] (REQUIRED - sections are generated in next phase)
|
||||||
|
- contentParts: {"partId": {"instruction": "..."} or {"caption": "..."} or both} - Assign ContentParts as required by CONTENT ASSIGNMENT RULE above
|
||||||
|
- The "instruction" field for each ContentPart MUST contain ALL relevant details from the USER REQUEST that apply to content extraction for this specific chapter. Include all formatting rules, data requirements, constraints, and specifications mentioned in the user request that are relevant for processing this ContentPart in this chapter.
|
||||||
|
- generationHint: Keep CONCISE but include relevant details from the USER REQUEST. Focus on WHAT to generate, not HOW to phrase it verbosely.
|
||||||
|
- The number of chapters depends on the user request - create only what is requested. Do NOT create chapters for topics without available data.
|
||||||
|
|
||||||
|
CRITICAL: Only create chapters for CONTENT sections, not for formatting/styling requirements. Formatting/styling requirements to be included in each generationHint if needed.
|
||||||
|
|
||||||
|
## DOCUMENT STRUCTURE
|
||||||
|
|
||||||
|
For each document, determine:
|
||||||
|
- outputFormat: From USER REQUEST (explicit mention or infer from purpose/content type). Default: "txt". Multiple documents can have different formats.
|
||||||
|
- language: From USER REQUEST (map to ISO 639-1: de, en, fr, it...). Default: "de". Multiple documents can have different languages.
|
||||||
|
- chapters: Structure appropriately for the format (e.g., pptx=slides, docx=sections, xlsx=worksheets). Match format capabilities and constraints.
|
||||||
|
|
||||||
|
Required JSON fields:
|
||||||
|
- metadata: {"title": "...", "language": "..."}
|
||||||
|
- documents: Array with id, title, filename, outputFormat, language, chapters[]
|
||||||
|
- chapters: Array with id, level, title, contentParts, generationHint, sections[]
|
||||||
|
|
||||||
|
EXAMPLE STRUCTURE (for reference only - adapt to user request):
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Document Title",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Document Title",
|
||||||
|
"filename": "document.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Chapter Title",
|
||||||
|
"contentParts": {
|
||||||
|
"extracted_part_id": {
|
||||||
|
"instruction": "Use extracted content with ALL relevant details from user request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generationHint": "Detailed description including ALL relevant details from user request for this chapter",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
CRITICAL INSTRUCTIONS:
|
||||||
|
- Generate chapters based on USER REQUEST, NOT based on the example above
|
||||||
|
- The example shows the JSON structure format, NOT the required chapters
|
||||||
|
- Create only the chapters that match the user's request
|
||||||
|
- Adapt chapter titles and structure to match the user's specific request
|
||||||
|
- Determine outputFormat and language for each document by analyzing the USER REQUEST above
|
||||||
|
- The example shows placeholders "txt" and "de" - YOU MUST REPLACE THESE with actual values determined from the USER REQUEST
|
||||||
|
|
||||||
|
MANDATORY CONTENT ASSIGNMENT CHECK:
|
||||||
|
For each chapter, verify:
|
||||||
|
1. Does the user request mention documents/images/data? (e.g., "photo", "image", "document", "data", "based on", "about")
|
||||||
|
2. Does this chapter's generationHint, title, or purpose relate to those documents/images/data mentioned in step 1?
|
||||||
|
- Examples: "article about the photo", "text describing the image", "analysis of the document", "content based on the data"
|
||||||
|
- Even if chapter doesn't explicitly say "about the image", if user request mentions both the image AND this chapter's content type → relate them
|
||||||
|
3. If YES to both → chapter MUST have contentParts assigned (cannot be empty {})
|
||||||
|
4. If ContentPart is "object" format and chapter needs to write ABOUT it → assign with "instruction" field, not just "caption"
|
||||||
|
|
||||||
|
OUTPUT FORMAT: Start with { and end with }. Do NOT use markdown code fences (```json). Do NOT add explanatory text before or after the JSON. Return ONLY the JSON object itself.
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Erstellen Sie eine kurze Einleitung für die E-Mail, die den Zweck der Nachricht erklärt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptteil",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Formulieren Sie den Hauptinhalt der E-Mail basierend auf den Informationen, die im vorherigen Dokument enthalten waren.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Schluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Schreiben Sie einen abschließenden Absatz, der die E-Mail höflich beendet und eventuell weitere Schritte oder Erwartungen erwähnt.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Erstellen Sie eine kurze Einleitung für die E-Mail, die den Zweck der Nachricht erklärt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptteil",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Formulieren Sie den Hauptinhalt der E-Mail basierend auf den Informationen, die im vorherigen Dokument enthalten waren.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Schluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Schreiben Sie einen abschließenden Absatz, der die E-Mail höflich beendet und eventuell weitere Schritte oder Erwartungen erwähnt.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
# TASK: Plan Document Structure (Documents + Chapters)
|
||||||
|
|
||||||
|
This is a STRUCTURE PLANNING task. You define which documents to create and which chapters each document will have.
|
||||||
|
Chapter CONTENT will be generated in a later step - here you only plan the STRUCTURE and assign content references.
|
||||||
|
Return EXACTLY ONE complete JSON object. Do not generate multiple JSON objects, alternatives, or variations. Do not use separators like "---" between JSON objects.
|
||||||
|
|
||||||
|
## USER REQUEST (for context)
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## AVAILABLE CONTENT PARTS
|
||||||
|
|
||||||
|
(No content parts available)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE
|
||||||
|
|
||||||
|
CRITICAL: Every chapter MUST have contentParts assigned if it relates to documents/images/data from the user request.
|
||||||
|
If the user request mentions documents/images/data, then EVERY chapter that generates content related to those references MUST assign the relevant ContentParts explicitly.
|
||||||
|
|
||||||
|
Assignment logic:
|
||||||
|
- If chapter DISPLAYS a document/image → assign "object" format ContentPart with "caption"
|
||||||
|
- If chapter generates text content ABOUT a document/image/data → assign ContentPart with "instruction":
|
||||||
|
- Prefer "extracted" format if available (contains analyzed/extracted content)
|
||||||
|
- If only "object" format is available, use "object" format with "instruction" (to write ABOUT the image/document)
|
||||||
|
- If chapter's generationHint or purpose relates to a document/image/data mentioned in user request → it MUST have ContentParts assigned
|
||||||
|
- Multiple chapters might assign the same ContentPart (e.g., one chapter displays image, another writes about it)
|
||||||
|
- Use ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
- Empty contentParts are only allowed if chapter generates content WITHOUT referencing any documents/images/data from the user request
|
||||||
|
|
||||||
|
CRITICAL RULE: If the user request mentions BOTH:
|
||||||
|
a) Documents/images/data (listed in AVAILABLE CONTENT PARTS above), AND
|
||||||
|
b) Generic content types (article text, main content, body text, etc.)
|
||||||
|
Then chapters that generate those generic content types MUST assign the relevant ContentParts, because the content should relate to or be based on the provided documents/images/data.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential information only
|
||||||
|
- AVOID verbose, lengthy, or repetitive text - be concise and direct
|
||||||
|
- Prioritize FACTS over filler text - no introductions like "In this chapter..."
|
||||||
|
- Minimize system resources: shorter content = faster processing
|
||||||
|
- Quality over quantity: precise, meaningful content rather than padding
|
||||||
|
|
||||||
|
## CHAPTER STRUCTURE REQUIREMENTS
|
||||||
|
- Generate chapters based on USER REQUEST - analyze what structure the user wants
|
||||||
|
- Create ONLY the minimum chapters needed to cover the user's request - avoid over-structuring
|
||||||
|
- HARD LIMIT: Maximum 7 chapters per document. If the topic can be covered in fewer, prefer fewer. Combine related topics into single chapters rather than creating many small ones.
|
||||||
|
- IMPORTANT: Each chapter MUST have ALL these fields:
|
||||||
|
- id: Unique identifier (e.g., "chapter_1")
|
||||||
|
- level: Heading level (1, 2, 3, etc.)
|
||||||
|
- title: Chapter title
|
||||||
|
- contentParts: Object mapping ContentPart IDs to usage instructions (MUST assign if chapter relates to documents/data from user request)
|
||||||
|
- generationHint: Description of what content to generate (including formatting/styling requirements)
|
||||||
|
- sections: Empty array [] (REQUIRED - sections are generated in next phase)
|
||||||
|
- contentParts: {"partId": {"instruction": "..."} or {"caption": "..."} or both} - Assign ContentParts as required by CONTENT ASSIGNMENT RULE above
|
||||||
|
- The "instruction" field for each ContentPart MUST contain ALL relevant details from the USER REQUEST that apply to content extraction for this specific chapter. Include all formatting rules, data requirements, constraints, and specifications mentioned in the user request that are relevant for processing this ContentPart in this chapter.
|
||||||
|
- generationHint: Keep CONCISE but include relevant details from the USER REQUEST. Focus on WHAT to generate, not HOW to phrase it verbosely.
|
||||||
|
- The number of chapters depends on the user request - create only what is requested. Do NOT create chapters for topics without available data.
|
||||||
|
|
||||||
|
CRITICAL: Only create chapters for CONTENT sections, not for formatting/styling requirements. Formatting/styling requirements to be included in each generationHint if needed.
|
||||||
|
|
||||||
|
## DOCUMENT STRUCTURE
|
||||||
|
|
||||||
|
For each document, determine:
|
||||||
|
- outputFormat: From USER REQUEST (explicit mention or infer from purpose/content type). Default: "txt". Multiple documents can have different formats.
|
||||||
|
- language: From USER REQUEST (map to ISO 639-1: de, en, fr, it...). Default: "de". Multiple documents can have different languages.
|
||||||
|
- chapters: Structure appropriately for the format (e.g., pptx=slides, docx=sections, xlsx=worksheets). Match format capabilities and constraints.
|
||||||
|
|
||||||
|
Required JSON fields:
|
||||||
|
- metadata: {"title": "...", "language": "..."}
|
||||||
|
- documents: Array with id, title, filename, outputFormat, language, chapters[]
|
||||||
|
- chapters: Array with id, level, title, contentParts, generationHint, sections[]
|
||||||
|
|
||||||
|
EXAMPLE STRUCTURE (for reference only - adapt to user request):
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Document Title",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Document Title",
|
||||||
|
"filename": "document.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Chapter Title",
|
||||||
|
"contentParts": {
|
||||||
|
"extracted_part_id": {
|
||||||
|
"instruction": "Use extracted content with ALL relevant details from user request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generationHint": "Detailed description including ALL relevant details from user request for this chapter",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
CRITICAL INSTRUCTIONS:
|
||||||
|
- Generate chapters based on USER REQUEST, NOT based on the example above
|
||||||
|
- The example shows the JSON structure format, NOT the required chapters
|
||||||
|
- Create only the chapters that match the user's request
|
||||||
|
- Adapt chapter titles and structure to match the user's specific request
|
||||||
|
- Determine outputFormat and language for each document by analyzing the USER REQUEST above
|
||||||
|
- The example shows placeholders "txt" and "de" - YOU MUST REPLACE THESE with actual values determined from the USER REQUEST
|
||||||
|
|
||||||
|
MANDATORY CONTENT ASSIGNMENT CHECK:
|
||||||
|
For each chapter, verify:
|
||||||
|
1. Does the user request mention documents/images/data? (e.g., "photo", "image", "document", "data", "based on", "about")
|
||||||
|
2. Does this chapter's generationHint, title, or purpose relate to those documents/images/data mentioned in step 1?
|
||||||
|
- Examples: "article about the photo", "text describing the image", "analysis of the document", "content based on the data"
|
||||||
|
- Even if chapter doesn't explicitly say "about the image", if user request mentions both the image AND this chapter's content type → relate them
|
||||||
|
3. If YES to both → chapter MUST have contentParts assigned (cannot be empty {})
|
||||||
|
4. If ContentPart is "object" format and chapter needs to write ABOUT it → assign with "instruction" field, not just "caption"
|
||||||
|
|
||||||
|
OUTPUT FORMAT: Start with { and end with }. Do NOT use markdown code fences (```json). Do NOT add explanatory text before or after the JSON. Return ONLY the JSON object itself.
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Erstellen Sie eine Einleitung für die E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptinhalt",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Formulieren Sie den Hauptinhalt der E-Mail, der die wesentlichen Informationen oder Anfragen enthält.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Abschluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Fügen Sie einen Abschluss hinzu, der die E-Mail höflich beendet und eventuell weitere Schritte oder Erwartungen erwähnt.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Erstellen Sie eine Einleitung für die E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptinhalt",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Formulieren Sie den Hauptinhalt der E-Mail, der die wesentlichen Informationen oder Anfragen enthält.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Abschluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Fügen Sie einen Abschluss hinzu, der die E-Mail höflich beendet und eventuell weitere Schritte oder Erwartungen erwähnt.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
# TASK: Plan Document Structure (Documents + Chapters)
|
||||||
|
|
||||||
|
This is a STRUCTURE PLANNING task. You define which documents to create and which chapters each document will have.
|
||||||
|
Chapter CONTENT will be generated in a later step - here you only plan the STRUCTURE and assign content references.
|
||||||
|
Return EXACTLY ONE complete JSON object. Do not generate multiple JSON objects, alternatives, or variations. Do not use separators like "---" between JSON objects.
|
||||||
|
|
||||||
|
## USER REQUEST (for context)
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## AVAILABLE CONTENT PARTS
|
||||||
|
|
||||||
|
(No content parts available)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE
|
||||||
|
|
||||||
|
CRITICAL: Every chapter MUST have contentParts assigned if it relates to documents/images/data from the user request.
|
||||||
|
If the user request mentions documents/images/data, then EVERY chapter that generates content related to those references MUST assign the relevant ContentParts explicitly.
|
||||||
|
|
||||||
|
Assignment logic:
|
||||||
|
- If chapter DISPLAYS a document/image → assign "object" format ContentPart with "caption"
|
||||||
|
- If chapter generates text content ABOUT a document/image/data → assign ContentPart with "instruction":
|
||||||
|
- Prefer "extracted" format if available (contains analyzed/extracted content)
|
||||||
|
- If only "object" format is available, use "object" format with "instruction" (to write ABOUT the image/document)
|
||||||
|
- If chapter's generationHint or purpose relates to a document/image/data mentioned in user request → it MUST have ContentParts assigned
|
||||||
|
- Multiple chapters might assign the same ContentPart (e.g., one chapter displays image, another writes about it)
|
||||||
|
- Use ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
- Empty contentParts are only allowed if chapter generates content WITHOUT referencing any documents/images/data from the user request
|
||||||
|
|
||||||
|
CRITICAL RULE: If the user request mentions BOTH:
|
||||||
|
a) Documents/images/data (listed in AVAILABLE CONTENT PARTS above), AND
|
||||||
|
b) Generic content types (article text, main content, body text, etc.)
|
||||||
|
Then chapters that generate those generic content types MUST assign the relevant ContentParts, because the content should relate to or be based on the provided documents/images/data.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential information only
|
||||||
|
- AVOID verbose, lengthy, or repetitive text - be concise and direct
|
||||||
|
- Prioritize FACTS over filler text - no introductions like "In this chapter..."
|
||||||
|
- Minimize system resources: shorter content = faster processing
|
||||||
|
- Quality over quantity: precise, meaningful content rather than padding
|
||||||
|
|
||||||
|
## CHAPTER STRUCTURE REQUIREMENTS
|
||||||
|
- Generate chapters based on USER REQUEST - analyze what structure the user wants
|
||||||
|
- Create ONLY the minimum chapters needed to cover the user's request - avoid over-structuring
|
||||||
|
- HARD LIMIT: Maximum 7 chapters per document. If the topic can be covered in fewer, prefer fewer. Combine related topics into single chapters rather than creating many small ones.
|
||||||
|
- IMPORTANT: Each chapter MUST have ALL these fields:
|
||||||
|
- id: Unique identifier (e.g., "chapter_1")
|
||||||
|
- level: Heading level (1, 2, 3, etc.)
|
||||||
|
- title: Chapter title
|
||||||
|
- contentParts: Object mapping ContentPart IDs to usage instructions (MUST assign if chapter relates to documents/data from user request)
|
||||||
|
- generationHint: Description of what content to generate (including formatting/styling requirements)
|
||||||
|
- sections: Empty array [] (REQUIRED - sections are generated in next phase)
|
||||||
|
- contentParts: {"partId": {"instruction": "..."} or {"caption": "..."} or both} - Assign ContentParts as required by CONTENT ASSIGNMENT RULE above
|
||||||
|
- The "instruction" field for each ContentPart MUST contain ALL relevant details from the USER REQUEST that apply to content extraction for this specific chapter. Include all formatting rules, data requirements, constraints, and specifications mentioned in the user request that are relevant for processing this ContentPart in this chapter.
|
||||||
|
- generationHint: Keep CONCISE but include relevant details from the USER REQUEST. Focus on WHAT to generate, not HOW to phrase it verbosely.
|
||||||
|
- The number of chapters depends on the user request - create only what is requested. Do NOT create chapters for topics without available data.
|
||||||
|
|
||||||
|
CRITICAL: Only create chapters for CONTENT sections, not for formatting/styling requirements. Formatting/styling requirements to be included in each generationHint if needed.
|
||||||
|
|
||||||
|
## DOCUMENT STRUCTURE
|
||||||
|
|
||||||
|
For each document, determine:
|
||||||
|
- outputFormat: From USER REQUEST (explicit mention or infer from purpose/content type). Default: "txt". Multiple documents can have different formats.
|
||||||
|
- language: From USER REQUEST (map to ISO 639-1: de, en, fr, it...). Default: "de". Multiple documents can have different languages.
|
||||||
|
- chapters: Structure appropriately for the format (e.g., pptx=slides, docx=sections, xlsx=worksheets). Match format capabilities and constraints.
|
||||||
|
|
||||||
|
Required JSON fields:
|
||||||
|
- metadata: {"title": "...", "language": "..."}
|
||||||
|
- documents: Array with id, title, filename, outputFormat, language, chapters[]
|
||||||
|
- chapters: Array with id, level, title, contentParts, generationHint, sections[]
|
||||||
|
|
||||||
|
EXAMPLE STRUCTURE (for reference only - adapt to user request):
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Document Title",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Document Title",
|
||||||
|
"filename": "document.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Chapter Title",
|
||||||
|
"contentParts": {
|
||||||
|
"extracted_part_id": {
|
||||||
|
"instruction": "Use extracted content with ALL relevant details from user request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generationHint": "Detailed description including ALL relevant details from user request for this chapter",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
CRITICAL INSTRUCTIONS:
|
||||||
|
- Generate chapters based on USER REQUEST, NOT based on the example above
|
||||||
|
- The example shows the JSON structure format, NOT the required chapters
|
||||||
|
- Create only the chapters that match the user's request
|
||||||
|
- Adapt chapter titles and structure to match the user's specific request
|
||||||
|
- Determine outputFormat and language for each document by analyzing the USER REQUEST above
|
||||||
|
- The example shows placeholders "txt" and "de" - YOU MUST REPLACE THESE with actual values determined from the USER REQUEST
|
||||||
|
|
||||||
|
MANDATORY CONTENT ASSIGNMENT CHECK:
|
||||||
|
For each chapter, verify:
|
||||||
|
1. Does the user request mention documents/images/data? (e.g., "photo", "image", "document", "data", "based on", "about")
|
||||||
|
2. Does this chapter's generationHint, title, or purpose relate to those documents/images/data mentioned in step 1?
|
||||||
|
- Examples: "article about the photo", "text describing the image", "analysis of the document", "content based on the data"
|
||||||
|
- Even if chapter doesn't explicitly say "about the image", if user request mentions both the image AND this chapter's content type → relate them
|
||||||
|
3. If YES to both → chapter MUST have contentParts assigned (cannot be empty {})
|
||||||
|
4. If ContentPart is "object" format and chapter needs to write ABOUT it → assign with "instruction" field, not just "caption"
|
||||||
|
|
||||||
|
OUTPUT FORMAT: Start with { and end with }. Do NOT use markdown code fences (```json). Do NOT add explanatory text before or after the JSON. Return ONLY the JSON object itself.
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Einleitung der E-Mail, Begrüßung und Einführung in das Thema.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptteil",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Hauptinhalt der E-Mail, Details und relevante Informationen.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Schluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Abschluss der E-Mail, Zusammenfassung und Grußformel.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Einleitung der E-Mail, Begrüßung und Einführung in das Thema.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptteil",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Hauptinhalt der E-Mail, Details und relevante Informationen.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Schluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Abschluss der E-Mail, Zusammenfassung und Grußformel.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
# TASK: Plan Document Structure (Documents + Chapters)
|
||||||
|
|
||||||
|
This is a STRUCTURE PLANNING task. You define which documents to create and which chapters each document will have.
|
||||||
|
Chapter CONTENT will be generated in a later step - here you only plan the STRUCTURE and assign content references.
|
||||||
|
Return EXACTLY ONE complete JSON object. Do not generate multiple JSON objects, alternatives, or variations. Do not use separators like "---" between JSON objects.
|
||||||
|
|
||||||
|
## USER REQUEST (for context)
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## AVAILABLE CONTENT PARTS
|
||||||
|
|
||||||
|
(No content parts available)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE
|
||||||
|
|
||||||
|
CRITICAL: Every chapter MUST have contentParts assigned if it relates to documents/images/data from the user request.
|
||||||
|
If the user request mentions documents/images/data, then EVERY chapter that generates content related to those references MUST assign the relevant ContentParts explicitly.
|
||||||
|
|
||||||
|
Assignment logic:
|
||||||
|
- If chapter DISPLAYS a document/image → assign "object" format ContentPart with "caption"
|
||||||
|
- If chapter generates text content ABOUT a document/image/data → assign ContentPart with "instruction":
|
||||||
|
- Prefer "extracted" format if available (contains analyzed/extracted content)
|
||||||
|
- If only "object" format is available, use "object" format with "instruction" (to write ABOUT the image/document)
|
||||||
|
- If chapter's generationHint or purpose relates to a document/image/data mentioned in user request → it MUST have ContentParts assigned
|
||||||
|
- Multiple chapters might assign the same ContentPart (e.g., one chapter displays image, another writes about it)
|
||||||
|
- Use ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
- Empty contentParts are only allowed if chapter generates content WITHOUT referencing any documents/images/data from the user request
|
||||||
|
|
||||||
|
CRITICAL RULE: If the user request mentions BOTH:
|
||||||
|
a) Documents/images/data (listed in AVAILABLE CONTENT PARTS above), AND
|
||||||
|
b) Generic content types (article text, main content, body text, etc.)
|
||||||
|
Then chapters that generate those generic content types MUST assign the relevant ContentParts, because the content should relate to or be based on the provided documents/images/data.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential information only
|
||||||
|
- AVOID verbose, lengthy, or repetitive text - be concise and direct
|
||||||
|
- Prioritize FACTS over filler text - no introductions like "In this chapter..."
|
||||||
|
- Minimize system resources: shorter content = faster processing
|
||||||
|
- Quality over quantity: precise, meaningful content rather than padding
|
||||||
|
|
||||||
|
## CHAPTER STRUCTURE REQUIREMENTS
|
||||||
|
- Generate chapters based on USER REQUEST - analyze what structure the user wants
|
||||||
|
- Create ONLY the minimum chapters needed to cover the user's request - avoid over-structuring
|
||||||
|
- HARD LIMIT: Maximum 7 chapters per document. If the topic can be covered in fewer, prefer fewer. Combine related topics into single chapters rather than creating many small ones.
|
||||||
|
- IMPORTANT: Each chapter MUST have ALL these fields:
|
||||||
|
- id: Unique identifier (e.g., "chapter_1")
|
||||||
|
- level: Heading level (1, 2, 3, etc.)
|
||||||
|
- title: Chapter title
|
||||||
|
- contentParts: Object mapping ContentPart IDs to usage instructions (MUST assign if chapter relates to documents/data from user request)
|
||||||
|
- generationHint: Description of what content to generate (including formatting/styling requirements)
|
||||||
|
- sections: Empty array [] (REQUIRED - sections are generated in next phase)
|
||||||
|
- contentParts: {"partId": {"instruction": "..."} or {"caption": "..."} or both} - Assign ContentParts as required by CONTENT ASSIGNMENT RULE above
|
||||||
|
- The "instruction" field for each ContentPart MUST contain ALL relevant details from the USER REQUEST that apply to content extraction for this specific chapter. Include all formatting rules, data requirements, constraints, and specifications mentioned in the user request that are relevant for processing this ContentPart in this chapter.
|
||||||
|
- generationHint: Keep CONCISE but include relevant details from the USER REQUEST. Focus on WHAT to generate, not HOW to phrase it verbosely.
|
||||||
|
- The number of chapters depends on the user request - create only what is requested. Do NOT create chapters for topics without available data.
|
||||||
|
|
||||||
|
CRITICAL: Only create chapters for CONTENT sections, not for formatting/styling requirements. Formatting/styling requirements to be included in each generationHint if needed.
|
||||||
|
|
||||||
|
## DOCUMENT STRUCTURE
|
||||||
|
|
||||||
|
For each document, determine:
|
||||||
|
- outputFormat: From USER REQUEST (explicit mention or infer from purpose/content type). Default: "txt". Multiple documents can have different formats.
|
||||||
|
- language: From USER REQUEST (map to ISO 639-1: de, en, fr, it...). Default: "de". Multiple documents can have different languages.
|
||||||
|
- chapters: Structure appropriately for the format (e.g., pptx=slides, docx=sections, xlsx=worksheets). Match format capabilities and constraints.
|
||||||
|
|
||||||
|
Required JSON fields:
|
||||||
|
- metadata: {"title": "...", "language": "..."}
|
||||||
|
- documents: Array with id, title, filename, outputFormat, language, chapters[]
|
||||||
|
- chapters: Array with id, level, title, contentParts, generationHint, sections[]
|
||||||
|
|
||||||
|
EXAMPLE STRUCTURE (for reference only - adapt to user request):
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Document Title",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Document Title",
|
||||||
|
"filename": "document.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Chapter Title",
|
||||||
|
"contentParts": {
|
||||||
|
"extracted_part_id": {
|
||||||
|
"instruction": "Use extracted content with ALL relevant details from user request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generationHint": "Detailed description including ALL relevant details from user request for this chapter",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
CRITICAL INSTRUCTIONS:
|
||||||
|
- Generate chapters based on USER REQUEST, NOT based on the example above
|
||||||
|
- The example shows the JSON structure format, NOT the required chapters
|
||||||
|
- Create only the chapters that match the user's request
|
||||||
|
- Adapt chapter titles and structure to match the user's specific request
|
||||||
|
- Determine outputFormat and language for each document by analyzing the USER REQUEST above
|
||||||
|
- The example shows placeholders "txt" and "de" - YOU MUST REPLACE THESE with actual values determined from the USER REQUEST
|
||||||
|
|
||||||
|
MANDATORY CONTENT ASSIGNMENT CHECK:
|
||||||
|
For each chapter, verify:
|
||||||
|
1. Does the user request mention documents/images/data? (e.g., "photo", "image", "document", "data", "based on", "about")
|
||||||
|
2. Does this chapter's generationHint, title, or purpose relate to those documents/images/data mentioned in step 1?
|
||||||
|
- Examples: "article about the photo", "text describing the image", "analysis of the document", "content based on the data"
|
||||||
|
- Even if chapter doesn't explicitly say "about the image", if user request mentions both the image AND this chapter's content type → relate them
|
||||||
|
3. If YES to both → chapter MUST have contentParts assigned (cannot be empty {})
|
||||||
|
4. If ContentPart is "object" format and chapter needs to write ABOUT it → assign with "instruction" field, not just "caption"
|
||||||
|
|
||||||
|
OUTPUT FORMAT: Start with { and end with }. Do NOT use markdown code fences (```json). Do NOT add explanatory text before or after the JSON. Return ONLY the JSON object itself.
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Einleitung der E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptinhalt",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Hauptteil der E-Mail, der die wichtigsten Informationen und Details enthält.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Abschluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Einleitung der E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptinhalt",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Hauptteil der E-Mail, der die wichtigsten Informationen und Details enthält.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Abschluss",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
TASK: Generate Chapter Sections Structure
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
CHAPTER: Einleitung (Level 1, ID: chapter_1)
|
||||||
|
GENERATION HINT: Einleitung der E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT sections: Focus on essential information only
|
||||||
|
- AVOID creating too many sections - combine related content where possible
|
||||||
|
- Each section should serve a clear purpose with meaningful data
|
||||||
|
- If no relevant data exists for a topic, do NOT create a section for it
|
||||||
|
- Prefer ONE comprehensive section over multiple sparse sections
|
||||||
|
- HARD LIMIT: Maximum 5 sections per chapter. Combine related subtopics into single sections to stay within this limit.
|
||||||
|
|
||||||
|
**CRITICAL**: The chapter's generationHint above describes what content this chapter should generate. If the generationHint references documents/images/data, then EACH section that generates content for this chapter MUST assign the relevant ContentParts from AVAILABLE CONTENT PARTS below.
|
||||||
|
|
||||||
|
NOTE: Chapter already has a heading section. Do NOT generate a heading for the chapter title.
|
||||||
|
|
||||||
|
## SECTION INDEPENDENCE
|
||||||
|
- Each section is independent and self-contained
|
||||||
|
- One section does NOT have information about another section
|
||||||
|
- Each section must provide its own context and be understandable alone
|
||||||
|
|
||||||
|
AVAILABLE CONTENT PARTS:
|
||||||
|
|
||||||
|
(No content parts specified for this chapter)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE - CRITICAL
|
||||||
|
If AVAILABLE CONTENT PARTS are listed above, then EVERY section that generates content related to those ContentParts MUST assign them explicitly.
|
||||||
|
|
||||||
|
**Assignment logic:**
|
||||||
|
- If section generates text content ABOUT a ContentPart → assign "extracted" format ContentPart with appropriate instruction
|
||||||
|
- If section DISPLAYS a ContentPart → assign "object" format ContentPart
|
||||||
|
- If section's generationHint or purpose relates to a ContentPart listed above → it MUST have contentPartIds assigned
|
||||||
|
- If chapter's generationHint references documents/images/data AND section generates content for that chapter → section MUST assign relevant ContentParts
|
||||||
|
- Empty contentPartIds [] are only allowed if section generates content WITHOUT referencing any available ContentParts AND WITHOUT relating to chapter's generationHint
|
||||||
|
|
||||||
|
## ACCEPTED CONTENT TYPES FOR THIS FORMAT
|
||||||
|
The document output format (txt) accepts only the following content types:
|
||||||
|
table, bullet_list, heading, paragraph, code_block
|
||||||
|
|
||||||
|
**CRITICAL**: Only create sections with content types from this list. Other types will fail.
|
||||||
|
|
||||||
|
useAiCall RULE (simple):
|
||||||
|
- useAiCall: true → Content needs AI processing (extract, transform, generate, filter, summarize)
|
||||||
|
- useAiCall: false → Content can be inserted directly without changes (Format is "object" or "reference")
|
||||||
|
|
||||||
|
RETURN JSON:
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": ["extracted_part_id"],
|
||||||
|
"generationHint": "Description of what to extract or generate",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
**MANDATORY CONTENT ASSIGNMENT CHECK:**
|
||||||
|
For each section, verify:
|
||||||
|
1. Are ContentParts listed in AVAILABLE CONTENT PARTS above?
|
||||||
|
2. Does this section's generationHint or purpose relate to those ContentParts?
|
||||||
|
3. If YES to both → section MUST have contentPartIds assigned (cannot be empty [])
|
||||||
|
4. Assign ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
|
||||||
|
IMAGE SECTIONS:
|
||||||
|
- For image sections, always provide a "caption" field with a descriptive caption for the image.
|
||||||
|
|
||||||
|
Return only valid JSON. Do not include any explanatory text outside the JSON.
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
TASK: Generate Chapter Sections Structure
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
CHAPTER: Hauptinhalt (Level 1, ID: chapter_2)
|
||||||
|
GENERATION HINT: Hauptteil der E-Mail, der die wichtigsten Informationen und Details enthält.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT sections: Focus on essential information only
|
||||||
|
- AVOID creating too many sections - combine related content where possible
|
||||||
|
- Each section should serve a clear purpose with meaningful data
|
||||||
|
- If no relevant data exists for a topic, do NOT create a section for it
|
||||||
|
- Prefer ONE comprehensive section over multiple sparse sections
|
||||||
|
- HARD LIMIT: Maximum 5 sections per chapter. Combine related subtopics into single sections to stay within this limit.
|
||||||
|
|
||||||
|
**CRITICAL**: The chapter's generationHint above describes what content this chapter should generate. If the generationHint references documents/images/data, then EACH section that generates content for this chapter MUST assign the relevant ContentParts from AVAILABLE CONTENT PARTS below.
|
||||||
|
|
||||||
|
NOTE: Chapter already has a heading section. Do NOT generate a heading for the chapter title.
|
||||||
|
|
||||||
|
## SECTION INDEPENDENCE
|
||||||
|
- Each section is independent and self-contained
|
||||||
|
- One section does NOT have information about another section
|
||||||
|
- Each section must provide its own context and be understandable alone
|
||||||
|
|
||||||
|
AVAILABLE CONTENT PARTS:
|
||||||
|
|
||||||
|
(No content parts specified for this chapter)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE - CRITICAL
|
||||||
|
If AVAILABLE CONTENT PARTS are listed above, then EVERY section that generates content related to those ContentParts MUST assign them explicitly.
|
||||||
|
|
||||||
|
**Assignment logic:**
|
||||||
|
- If section generates text content ABOUT a ContentPart → assign "extracted" format ContentPart with appropriate instruction
|
||||||
|
- If section DISPLAYS a ContentPart → assign "object" format ContentPart
|
||||||
|
- If section's generationHint or purpose relates to a ContentPart listed above → it MUST have contentPartIds assigned
|
||||||
|
- If chapter's generationHint references documents/images/data AND section generates content for that chapter → section MUST assign relevant ContentParts
|
||||||
|
- Empty contentPartIds [] are only allowed if section generates content WITHOUT referencing any available ContentParts AND WITHOUT relating to chapter's generationHint
|
||||||
|
|
||||||
|
## ACCEPTED CONTENT TYPES FOR THIS FORMAT
|
||||||
|
The document output format (txt) accepts only the following content types:
|
||||||
|
table, bullet_list, heading, paragraph, code_block
|
||||||
|
|
||||||
|
**CRITICAL**: Only create sections with content types from this list. Other types will fail.
|
||||||
|
|
||||||
|
useAiCall RULE (simple):
|
||||||
|
- useAiCall: true → Content needs AI processing (extract, transform, generate, filter, summarize)
|
||||||
|
- useAiCall: false → Content can be inserted directly without changes (Format is "object" or "reference")
|
||||||
|
|
||||||
|
RETURN JSON:
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": ["extracted_part_id"],
|
||||||
|
"generationHint": "Description of what to extract or generate",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
**MANDATORY CONTENT ASSIGNMENT CHECK:**
|
||||||
|
For each section, verify:
|
||||||
|
1. Are ContentParts listed in AVAILABLE CONTENT PARTS above?
|
||||||
|
2. Does this section's generationHint or purpose relate to those ContentParts?
|
||||||
|
3. If YES to both → section MUST have contentPartIds assigned (cannot be empty [])
|
||||||
|
4. Assign ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
|
||||||
|
IMAGE SECTIONS:
|
||||||
|
- For image sections, always provide a "caption" field with a descriptive caption for the image.
|
||||||
|
|
||||||
|
Return only valid JSON. Do not include any explanatory text outside the JSON.
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
TASK: Generate Chapter Sections Structure
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
CHAPTER: Abschluss (Level 1, ID: chapter_3)
|
||||||
|
GENERATION HINT: Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT sections: Focus on essential information only
|
||||||
|
- AVOID creating too many sections - combine related content where possible
|
||||||
|
- Each section should serve a clear purpose with meaningful data
|
||||||
|
- If no relevant data exists for a topic, do NOT create a section for it
|
||||||
|
- Prefer ONE comprehensive section over multiple sparse sections
|
||||||
|
- HARD LIMIT: Maximum 5 sections per chapter. Combine related subtopics into single sections to stay within this limit.
|
||||||
|
|
||||||
|
**CRITICAL**: The chapter's generationHint above describes what content this chapter should generate. If the generationHint references documents/images/data, then EACH section that generates content for this chapter MUST assign the relevant ContentParts from AVAILABLE CONTENT PARTS below.
|
||||||
|
|
||||||
|
NOTE: Chapter already has a heading section. Do NOT generate a heading for the chapter title.
|
||||||
|
|
||||||
|
## SECTION INDEPENDENCE
|
||||||
|
- Each section is independent and self-contained
|
||||||
|
- One section does NOT have information about another section
|
||||||
|
- Each section must provide its own context and be understandable alone
|
||||||
|
|
||||||
|
AVAILABLE CONTENT PARTS:
|
||||||
|
|
||||||
|
(No content parts specified for this chapter)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE - CRITICAL
|
||||||
|
If AVAILABLE CONTENT PARTS are listed above, then EVERY section that generates content related to those ContentParts MUST assign them explicitly.
|
||||||
|
|
||||||
|
**Assignment logic:**
|
||||||
|
- If section generates text content ABOUT a ContentPart → assign "extracted" format ContentPart with appropriate instruction
|
||||||
|
- If section DISPLAYS a ContentPart → assign "object" format ContentPart
|
||||||
|
- If section's generationHint or purpose relates to a ContentPart listed above → it MUST have contentPartIds assigned
|
||||||
|
- If chapter's generationHint references documents/images/data AND section generates content for that chapter → section MUST assign relevant ContentParts
|
||||||
|
- Empty contentPartIds [] are only allowed if section generates content WITHOUT referencing any available ContentParts AND WITHOUT relating to chapter's generationHint
|
||||||
|
|
||||||
|
## ACCEPTED CONTENT TYPES FOR THIS FORMAT
|
||||||
|
The document output format (txt) accepts only the following content types:
|
||||||
|
table, bullet_list, heading, paragraph, code_block
|
||||||
|
|
||||||
|
**CRITICAL**: Only create sections with content types from this list. Other types will fail.
|
||||||
|
|
||||||
|
useAiCall RULE (simple):
|
||||||
|
- useAiCall: true → Content needs AI processing (extract, transform, generate, filter, summarize)
|
||||||
|
- useAiCall: false → Content can be inserted directly without changes (Format is "object" or "reference")
|
||||||
|
|
||||||
|
RETURN JSON:
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": ["extracted_part_id"],
|
||||||
|
"generationHint": "Description of what to extract or generate",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
**MANDATORY CONTENT ASSIGNMENT CHECK:**
|
||||||
|
For each section, verify:
|
||||||
|
1. Are ContentParts listed in AVAILABLE CONTENT PARTS above?
|
||||||
|
2. Does this section's generationHint or purpose relate to those ContentParts?
|
||||||
|
3. If YES to both → section MUST have contentPartIds assigned (cannot be empty [])
|
||||||
|
4. Assign ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
|
||||||
|
IMAGE SECTIONS:
|
||||||
|
- For image sections, always provide a "caption" field with a descriptive caption for the image.
|
||||||
|
|
||||||
|
Return only valid JSON. Do not include any explanatory text outside the JSON.
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Zusammenfassung der E-Mail-Inhalte und abschließende Gedanken",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"In der abschließenden Zusammenfassung der E-Mail möchten wir die wichtigsten Punkte noch einmal hervorheben. Es ist entscheidend, dass alle besprochenen Themen klar und prägnant zusammengefasst werden, um Missverständnisse zu vermeiden. Abschließend möchten wir betonen, wie wichtig die Zusammenarbeit und der kontinuierliche Dialog sind, um die gesteckten Ziele erfolgreich zu erreichen. Wir danken Ihnen für Ihre Aufmerksamkeit und freuen uns auf die weitere Zusammenarbeit."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Kurze Einführung in den Zweck der E-Mail",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Diese E-Mail dient dazu, den Empfänger über den Zweck und den Kontext der Nachricht zu informieren. Sie bietet eine kurze Übersicht über die Hauptthemen, die in den folgenden Abschnitten behandelt werden."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_2",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Kontext der Nachricht und warum sie wichtig ist",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Der Kontext dieser Nachricht ist entscheidend, um die Relevanz und Dringlichkeit der behandelten Themen zu verstehen. Es wird erläutert, warum diese Informationen für den Empfänger von Bedeutung sind und welche Schritte möglicherweise erforderlich sind."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_3",
|
||||||
|
"content_type": "bullet_list",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Hauptpunkte der Nachricht",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Zweck der E-Mail",
|
||||||
|
"Wichtige Informationen und Updates",
|
||||||
|
"Erforderliche Aktionen oder Antworten",
|
||||||
|
"Relevante Fristen oder Termine"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Einleitung des Hauptinhalts mit einer kurzen Zusammenfassung der wichtigsten Punkte.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Der Hauptinhalt dieser E-Mail bietet eine umfassende Übersicht über die wesentlichen Informationen, die für den Empfänger von Bedeutung sind. In den folgenden Abschnitten werden die wichtigsten Details und Anweisungen klar und prägnant dargestellt."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_2",
|
||||||
|
"content_type": "bullet_list",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Liste der wichtigsten Informationen oder Anweisungen.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Wichtiger Termin: 15. November 2023",
|
||||||
|
"Erforderliche Dokumente: Reisepass, Visum",
|
||||||
|
"Kontaktperson: Herr Müller, erreichbar unter mueller@example.com",
|
||||||
|
"Nächste Schritte: Anmeldung bis zum 10. November 2023"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_3",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Detaillierte Beschreibung eines spezifischen Themas oder einer Anweisung.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Bitte beachten Sie, dass alle Teilnehmer vor dem 10. November 2023 registriert sein müssen, um an der Veranstaltung teilnehmen zu können. Die Registrierung erfolgt über das Online-Portal, das Ihnen per E-Mail zugesandt wurde. Stellen Sie sicher, dass alle erforderlichen Dokumente hochgeladen werden, um Verzögerungen zu vermeiden."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_4",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Tabelle mit den wichtigsten Terminen und Fristen.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"headers": ["Ereignis", "Datum", "Details"],
|
||||||
|
"rows": [
|
||||||
|
["Anmeldeschluss", "10. November 2023", "Online-Registrierung erforderlich"],
|
||||||
|
["Veranstaltungstermin", "15. November 2023", "Beginn um 9:00 Uhr"],
|
||||||
|
["Dokumenteneinreichung", "Bis 12. November 2023", "Alle Dokumente müssen vollständig sein"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_5",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Abschluss des Hauptinhalts mit einem Aufruf zum Handeln oder einer abschließenden Bemerkung.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Wir freuen uns auf Ihre Teilnahme und stehen für Rückfragen jederzeit zur Verfügung. Bitte zögern Sie nicht, uns zu kontaktieren, falls Sie weitere Informationen benötigen. Ihre rechtzeitige Anmeldung wird sehr geschätzt."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_1
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Kurze Einführung in den Zweck der E-Mail
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (paragraph):
|
||||||
|
- section_3 (bullet_list):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_2
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Kontext der Nachricht und warum sie wichtig ist
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_3 (bullet_list):
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_3
|
||||||
|
- Content Type: bullet_list
|
||||||
|
- Generation Hint: Hauptpunkte der Nachricht
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (bullet_list).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {{"items": ["Item 1", "Item 2", "Item 3"]}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_1
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Einleitung des Hauptinhalts mit einer kurzen Zusammenfassung der wichtigsten Punkte.
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (paragraph):
|
||||||
|
- section_3 (bullet_list):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_2
|
||||||
|
- Content Type: bullet_list
|
||||||
|
- Generation Hint: Liste der wichtigsten Informationen oder Anweisungen.
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (bullet_list).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {{"items": ["Item 1", "Item 2", "Item 3"]}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_3 (bullet_list):
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Diese E-Mail dient dazu, den Zweck und die wichtigsten Informationen des vorherigen Dokuments zusammenzufassen. Sie bietet eine kurze Übersicht über die Hauptpunkte und soll als Einführung in die detaillierteren Abschnitte des Dokuments dienen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Diese E-Mail dient dazu, den Zweck und die wichtigsten Informationen des vorherigen Dokuments zusammenzufassen. Sie bietet eine kurze Übersicht über die Hauptpunkte und soll als Einführung in die detaillierteren Abschnitte des Dokuments dienen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_3
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Detaillierte Beschreibung eines spezifischen Themas oder einer Anweisung.
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "In dieser Einleitung werden die Hauptpunkte des Dokuments zusammengefasst. Der Fokus liegt auf der klaren Darstellung der wichtigsten Informationen, um dem Leser einen schnellen Überblick zu verschaffen. Die folgenden Abschnitte bieten detaillierte Einblicke und ergänzende Details zu den hier genannten Themen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "In dieser Einleitung werden die Hauptpunkte des Dokuments zusammengefasst. Der Fokus liegt auf der klaren Darstellung der wichtigsten Informationen, um dem Leser einen schnellen Überblick zu verschaffen. Die folgenden Abschnitte bieten detaillierte Einblicke und ergänzende Details zu den hier genannten Themen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_4
|
||||||
|
- Content Type: table
|
||||||
|
- Generation Hint: Tabelle mit den wichtigsten Terminen und Fristen.
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (table).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"content": {{"headers": ["Column1", "Column2"], "rows": [["Value1", "Value2"], ["Value3", "Value4"]]}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_2 (paragraph):
|
||||||
|
- section_3 (bullet_list):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
- section_3 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Betreff der E-Mail klar und prägnant formulieren.",
|
||||||
|
"Anrede personalisieren, um den Empfänger direkt anzusprechen.",
|
||||||
|
"Hauptinhalt der E-Mail in kurzen, prägnanten Sätzen darstellen.",
|
||||||
|
"Wichtige Informationen oder Anweisungen in Stichpunkten auflisten.",
|
||||||
|
"Abschließende Grußformel und Kontaktdaten angeben."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Betreff der E-Mail klar und prägnant formulieren.",
|
||||||
|
"Anrede personalisieren, um den Empfänger direkt anzusprechen.",
|
||||||
|
"Hauptinhalt der E-Mail in kurzen, prägnanten Sätzen darstellen.",
|
||||||
|
"Wichtige Informationen oder Anweisungen in Stichpunkten auflisten.",
|
||||||
|
"Abschließende Grußformel und Kontaktdaten angeben."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Die Nachricht ist von entscheidender Bedeutung, da sie wichtige Informationen übermittelt, die für die Empfänger relevant sind. Sie dient dazu, Klarheit zu schaffen, Missverständnisse zu vermeiden und die Empfänger über wesentliche Entwicklungen oder Entscheidungen zu informieren. Eine präzise und gut formulierte Nachricht trägt dazu bei, dass alle Beteiligten auf dem gleichen Stand sind und entsprechend handeln können. Dies fördert die Effizienz und Effektivität in der Kommunikation und im weiteren Handeln."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Die Nachricht ist von entscheidender Bedeutung, da sie wichtige Informationen übermittelt, die für die Empfänger relevant sind. Sie dient dazu, Klarheit zu schaffen, Missverständnisse zu vermeiden und die Empfänger über wesentliche Entwicklungen oder Entscheidungen zu informieren. Eine präzise und gut formulierte Nachricht trägt dazu bei, dass alle Beteiligten auf dem gleichen Stand sind und entsprechend handeln können. Dies fördert die Effizienz und Effektivität in der Kommunikation und im weiteren Handeln."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_5
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Abschluss des Hauptinhalts mit einem Aufruf zum Handeln oder einer abschließenden Bemerkung.
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_3 (bullet_list):
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_3 (paragraph):
|
||||||
|
- section_4 (table):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_1
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Zusammenfassung der E-Mail-Inhalte und abschließende Gedanken
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (paragraph):
|
||||||
|
- section_3 (bullet_list):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Betreff der E-Mail klar und prägnant formulieren.",
|
||||||
|
"Einleitung mit einer kurzen Begrüßung und Vorstellung.",
|
||||||
|
"Hauptinhalt der Nachricht in klaren Punkten darstellen.",
|
||||||
|
"Wichtige Informationen oder Anfragen deutlich hervorheben.",
|
||||||
|
"Abschluss mit einem Dank und einer höflichen Verabschiedung."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Betreff der E-Mail klar und prägnant formulieren.",
|
||||||
|
"Einleitung mit einer kurzen Begrüßung und Vorstellung.",
|
||||||
|
"Hauptinhalt der Nachricht in klaren Punkten darstellen.",
|
||||||
|
"Wichtige Informationen oder Anfragen deutlich hervorheben.",
|
||||||
|
"Abschluss mit einem Dank und einer höflichen Verabschiedung."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Vielen Dank, dass Sie sich die Zeit genommen haben, unseren Hauptinhalt zu lesen. Wir hoffen, dass die Informationen für Sie nützlich waren. Zögern Sie nicht, uns bei Fragen oder Anmerkungen zu kontaktieren. Wir freuen uns darauf, von Ihnen zu hören und stehen Ihnen jederzeit zur Verfügung, um Ihnen weiterzuhelfen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Vielen Dank, dass Sie sich die Zeit genommen haben, unseren Hauptinhalt zu lesen. Wir hoffen, dass die Informationen für Sie nützlich waren. Zögern Sie nicht, uns bei Fragen oder Anmerkungen zu kontaktieren. Wir freuen uns darauf, von Ihnen zu hören und stehen Ihnen jederzeit zur Verfügung, um Ihnen weiterzuhelfen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Beim Entwerfen einer E-Mail ist es wichtig, den Zweck klar zu definieren und die Nachricht prägnant zu halten. Beginnen Sie mit einer höflichen Anrede, gefolgt von einer kurzen Einführung, die den Kontext der E-Mail erklärt. Der Hauptteil sollte die wesentlichen Informationen oder Anfragen enthalten, klar strukturiert und leicht verständlich. Abschließend sollte die E-Mail mit einem freundlichen Gruß und, falls erforderlich, einem Hinweis auf mögliche nächste Schritte oder eine Antwortmöglichkeit enden. Achten Sie darauf, die E-Mail auf Rechtschreibung und Grammatik zu überprüfen, um Professionalität zu gewährleisten."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Beim Entwerfen einer E-Mail ist es wichtig, den Zweck klar zu definieren und die Nachricht prägnant zu halten. Beginnen Sie mit einer höflichen Anrede, gefolgt von einer kurzen Einführung, die den Kontext der E-Mail erklärt. Der Hauptteil sollte die wesentlichen Informationen oder Anfragen enthalten, klar strukturiert und leicht verständlich. Abschließend sollte die E-Mail mit einem freundlichen Gruß und, falls erforderlich, einem Hinweis auf mögliche nächste Schritte oder eine Antwortmöglichkeit enden. Achten Sie darauf, die E-Mail auf Rechtschreibung und Grammatik zu überprüfen, um Professionalität zu gewährleisten."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"content": {
|
||||||
|
"headers": ["Termin", "Frist"],
|
||||||
|
"rows": [
|
||||||
|
["Anmeldeschluss", "15. März 2024"],
|
||||||
|
["Zahlungsfrist", "30. März 2024"],
|
||||||
|
["Einreichung der Unterlagen", "10. April 2024"],
|
||||||
|
["Veranstaltungsbeginn", "20. April 2024"],
|
||||||
|
["Stornierungsfrist", "5. April 2024"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"content": {
|
||||||
|
"headers": [
|
||||||
|
"Termin",
|
||||||
|
"Frist"
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
"Anmeldeschluss",
|
||||||
|
"15. März 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Zahlungsfrist",
|
||||||
|
"30. März 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Einreichung der Unterlagen",
|
||||||
|
"10. April 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Veranstaltungsbeginn",
|
||||||
|
"20. April 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Stornierungsfrist",
|
||||||
|
"5. April 2024"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Die E-Mail fasst die wichtigsten Punkte zusammen und bietet abschließende Gedanken. Sie enthält eine klare Übersicht über die besprochenen Themen und hebt die entscheidenden Informationen hervor. Abschließend wird ein Ausblick auf die nächsten Schritte gegeben, um die besprochenen Themen weiter zu verfolgen und die Kommunikation zu verbessern."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Die E-Mail fasst die wichtigsten Punkte zusammen und bietet abschließende Gedanken. Sie enthält eine klare Übersicht über die besprochenen Themen und hebt die entscheidenden Informationen hervor. Abschließend wird ein Ausblick auf die nächsten Schritte gegeben, um die besprochenen Themen weiter zu verfolgen und die Kommunikation zu verbessern."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
231
prompts/20260322-174206-046-document_generation_response.txt
Normal file
231
prompts/20260322-174206-046-document_generation_response.txt
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1_heading",
|
||||||
|
"content_type": "heading",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "heading",
|
||||||
|
"content": {
|
||||||
|
"text": "Einleitung",
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Kurze Einführung in den Zweck der E-Mail",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Diese E-Mail dient dazu, den Zweck und die wichtigsten Informationen des vorherigen Dokuments zusammenzufassen. Sie bietet eine kurze Übersicht über die Hauptpunkte und soll als Einführung in die detaillierteren Abschnitte des Dokuments dienen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_2",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Kontext der Nachricht und warum sie wichtig ist",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Die Nachricht ist von entscheidender Bedeutung, da sie wichtige Informationen übermittelt, die für die Empfänger relevant sind. Sie dient dazu, Klarheit zu schaffen, Missverständnisse zu vermeiden und die Empfänger über wesentliche Entwicklungen oder Entscheidungen zu informieren. Eine präzise und gut formulierte Nachricht trägt dazu bei, dass alle Beteiligten auf dem gleichen Stand sind und entsprechend handeln können. Dies fördert die Effizienz und Effektivität in der Kommunikation und im weiteren Handeln."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_3",
|
||||||
|
"content_type": "bullet_list",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Hauptpunkte der Nachricht",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Betreff der E-Mail klar und prägnant formulieren.",
|
||||||
|
"Einleitung mit einer kurzen Begrüßung und Vorstellung.",
|
||||||
|
"Hauptinhalt der Nachricht in klaren Punkten darstellen.",
|
||||||
|
"Wichtige Informationen oder Anfragen deutlich hervorheben.",
|
||||||
|
"Abschluss mit einem Dank und einer höflichen Verabschiedung."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2_heading",
|
||||||
|
"content_type": "heading",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "heading",
|
||||||
|
"content": {
|
||||||
|
"text": "Hauptinhalt",
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Einleitung des Hauptinhalts mit einer kurzen Zusammenfassung der wichtigsten Punkte.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "In dieser Einleitung werden die Hauptpunkte des Dokuments zusammengefasst. Der Fokus liegt auf der klaren Darstellung der wichtigsten Informationen, um dem Leser einen schnellen Überblick zu verschaffen. Die folgenden Abschnitte bieten detaillierte Einblicke und ergänzende Details zu den hier genannten Themen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_2",
|
||||||
|
"content_type": "bullet_list",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Liste der wichtigsten Informationen oder Anweisungen.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Betreff der E-Mail klar und prägnant formulieren.",
|
||||||
|
"Anrede personalisieren, um den Empfänger direkt anzusprechen.",
|
||||||
|
"Hauptinhalt der E-Mail in kurzen, prägnanten Sätzen darstellen.",
|
||||||
|
"Wichtige Informationen oder Anweisungen in Stichpunkten auflisten.",
|
||||||
|
"Abschließende Grußformel und Kontaktdaten angeben."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_3",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Detaillierte Beschreibung eines spezifischen Themas oder einer Anweisung.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Beim Entwerfen einer E-Mail ist es wichtig, den Zweck klar zu definieren und die Nachricht prägnant zu halten. Beginnen Sie mit einer höflichen Anrede, gefolgt von einer kurzen Einführung, die den Kontext der E-Mail erklärt. Der Hauptteil sollte die wesentlichen Informationen oder Anfragen enthalten, klar strukturiert und leicht verständlich. Abschließend sollte die E-Mail mit einem freundlichen Gruß und, falls erforderlich, einem Hinweis auf mögliche nächste Schritte oder eine Antwortmöglichkeit enden. Achten Sie darauf, die E-Mail auf Rechtschreibung und Grammatik zu überprüfen, um Professionalität zu gewährleisten."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_4",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Tabelle mit den wichtigsten Terminen und Fristen.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"content": {
|
||||||
|
"headers": [
|
||||||
|
"Termin",
|
||||||
|
"Frist"
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
"Anmeldeschluss",
|
||||||
|
"15. März 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Zahlungsfrist",
|
||||||
|
"30. März 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Einreichung der Unterlagen",
|
||||||
|
"10. April 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Veranstaltungsbeginn",
|
||||||
|
"20. April 2024"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Stornierungsfrist",
|
||||||
|
"5. April 2024"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_5",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Abschluss des Hauptinhalts mit einem Aufruf zum Handeln oder einer abschließenden Bemerkung.",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Vielen Dank, dass Sie sich die Zeit genommen haben, unseren Hauptinhalt zu lesen. Wir hoffen, dass die Informationen für Sie nützlich waren. Zögern Sie nicht, uns bei Fragen oder Anmerkungen zu kontaktieren. Wir freuen uns darauf, von Ihnen zu hören und stehen Ihnen jederzeit zur Verfügung, um Ihnen weiterzuhelfen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3_heading",
|
||||||
|
"content_type": "heading",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "heading",
|
||||||
|
"content": {
|
||||||
|
"text": "Abschluss",
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Zusammenfassung der E-Mail-Inhalte und abschließende Gedanken",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Die E-Mail fasst die wichtigsten Punkte zusammen und bietet abschließende Gedanken. Sie enthält eine klare Übersicht über die besprochenen Themen und hebt die entscheidenden Informationen hervor. Abschließend wird ein Ausblick auf die nächsten Schritte gegeben, um die besprochenen Themen weiter zu verfolgen und die Kommunikation zu verbessern."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"outputStyle": "document"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
22
prompts/20260322-174207-047-email_composition_prompt.txt
Normal file
22
prompts/20260322-174207-047-email_composition_prompt.txt
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
Compose an email based on this context:
|
||||||
|
-------
|
||||||
|
Compose an email. The upstream AI step did not produce output.
|
||||||
|
-------
|
||||||
|
|
||||||
|
Recipients: (not specified - this is a draft)
|
||||||
|
Style: business
|
||||||
|
Max length: 1000 characters
|
||||||
|
|
||||||
|
Available_Document_References:
|
||||||
|
- (no documents)
|
||||||
|
|
||||||
|
Based on the context, decide which documents to attach.
|
||||||
|
|
||||||
|
CRITICAL: Use EXACT document references from Available_Document_References above. For individual documents: ALWAYS use docItem:<documentId>:<filename> format (include filename)
|
||||||
|
|
||||||
|
Return JSON:
|
||||||
|
{
|
||||||
|
"subject": "subject line",
|
||||||
|
"body": "email body (HTML allowed)",
|
||||||
|
"attachments": ["docItem:<documentId>:<filename>"]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"subject": "Follow-up on Upstream AI Process",
|
||||||
|
"body": "<p>Dear Team,</p><p>I hope this message finds you well. I am writing to inform you that the upstream AI step did not produce any output as expected. We need to address this issue promptly to ensure the continuity of our workflow.</p><p>Please let me know if there are any specific actions you would like me to take or if there are any updates on resolving this matter.</p><p>Thank you for your attention to this issue.</p><p>Best regards,<br>Your Name</p>",
|
||||||
|
"attachments": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
# TASK: Plan Document Structure (Documents + Chapters)
|
||||||
|
|
||||||
|
This is a STRUCTURE PLANNING task. You define which documents to create and which chapters each document will have.
|
||||||
|
Chapter CONTENT will be generated in a later step - here you only plan the STRUCTURE and assign content references.
|
||||||
|
Return EXACTLY ONE complete JSON object. Do not generate multiple JSON objects, alternatives, or variations. Do not use separators like "---" between JSON objects.
|
||||||
|
|
||||||
|
## USER REQUEST (for context)
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## AVAILABLE CONTENT PARTS
|
||||||
|
|
||||||
|
(No content parts available)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE
|
||||||
|
|
||||||
|
CRITICAL: Every chapter MUST have contentParts assigned if it relates to documents/images/data from the user request.
|
||||||
|
If the user request mentions documents/images/data, then EVERY chapter that generates content related to those references MUST assign the relevant ContentParts explicitly.
|
||||||
|
|
||||||
|
Assignment logic:
|
||||||
|
- If chapter DISPLAYS a document/image → assign "object" format ContentPart with "caption"
|
||||||
|
- If chapter generates text content ABOUT a document/image/data → assign ContentPart with "instruction":
|
||||||
|
- Prefer "extracted" format if available (contains analyzed/extracted content)
|
||||||
|
- If only "object" format is available, use "object" format with "instruction" (to write ABOUT the image/document)
|
||||||
|
- If chapter's generationHint or purpose relates to a document/image/data mentioned in user request → it MUST have ContentParts assigned
|
||||||
|
- Multiple chapters might assign the same ContentPart (e.g., one chapter displays image, another writes about it)
|
||||||
|
- Use ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
- Empty contentParts are only allowed if chapter generates content WITHOUT referencing any documents/images/data from the user request
|
||||||
|
|
||||||
|
CRITICAL RULE: If the user request mentions BOTH:
|
||||||
|
a) Documents/images/data (listed in AVAILABLE CONTENT PARTS above), AND
|
||||||
|
b) Generic content types (article text, main content, body text, etc.)
|
||||||
|
Then chapters that generate those generic content types MUST assign the relevant ContentParts, because the content should relate to or be based on the provided documents/images/data.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential information only
|
||||||
|
- AVOID verbose, lengthy, or repetitive text - be concise and direct
|
||||||
|
- Prioritize FACTS over filler text - no introductions like "In this chapter..."
|
||||||
|
- Minimize system resources: shorter content = faster processing
|
||||||
|
- Quality over quantity: precise, meaningful content rather than padding
|
||||||
|
|
||||||
|
## CHAPTER STRUCTURE REQUIREMENTS
|
||||||
|
- Generate chapters based on USER REQUEST - analyze what structure the user wants
|
||||||
|
- Create ONLY the minimum chapters needed to cover the user's request - avoid over-structuring
|
||||||
|
- HARD LIMIT: Maximum 7 chapters per document. If the topic can be covered in fewer, prefer fewer. Combine related topics into single chapters rather than creating many small ones.
|
||||||
|
- IMPORTANT: Each chapter MUST have ALL these fields:
|
||||||
|
- id: Unique identifier (e.g., "chapter_1")
|
||||||
|
- level: Heading level (1, 2, 3, etc.)
|
||||||
|
- title: Chapter title
|
||||||
|
- contentParts: Object mapping ContentPart IDs to usage instructions (MUST assign if chapter relates to documents/data from user request)
|
||||||
|
- generationHint: Description of what content to generate (including formatting/styling requirements)
|
||||||
|
- sections: Empty array [] (REQUIRED - sections are generated in next phase)
|
||||||
|
- contentParts: {"partId": {"instruction": "..."} or {"caption": "..."} or both} - Assign ContentParts as required by CONTENT ASSIGNMENT RULE above
|
||||||
|
- The "instruction" field for each ContentPart MUST contain ALL relevant details from the USER REQUEST that apply to content extraction for this specific chapter. Include all formatting rules, data requirements, constraints, and specifications mentioned in the user request that are relevant for processing this ContentPart in this chapter.
|
||||||
|
- generationHint: Keep CONCISE but include relevant details from the USER REQUEST. Focus on WHAT to generate, not HOW to phrase it verbosely.
|
||||||
|
- The number of chapters depends on the user request - create only what is requested. Do NOT create chapters for topics without available data.
|
||||||
|
|
||||||
|
CRITICAL: Only create chapters for CONTENT sections, not for formatting/styling requirements. Formatting/styling requirements to be included in each generationHint if needed.
|
||||||
|
|
||||||
|
## DOCUMENT STRUCTURE
|
||||||
|
|
||||||
|
For each document, determine:
|
||||||
|
- outputFormat: From USER REQUEST (explicit mention or infer from purpose/content type). Default: "txt". Multiple documents can have different formats.
|
||||||
|
- language: From USER REQUEST (map to ISO 639-1: de, en, fr, it...). Default: "de". Multiple documents can have different languages.
|
||||||
|
- chapters: Structure appropriately for the format (e.g., pptx=slides, docx=sections, xlsx=worksheets). Match format capabilities and constraints.
|
||||||
|
|
||||||
|
Required JSON fields:
|
||||||
|
- metadata: {"title": "...", "language": "..."}
|
||||||
|
- documents: Array with id, title, filename, outputFormat, language, chapters[]
|
||||||
|
- chapters: Array with id, level, title, contentParts, generationHint, sections[]
|
||||||
|
|
||||||
|
EXAMPLE STRUCTURE (for reference only - adapt to user request):
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Document Title",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Document Title",
|
||||||
|
"filename": "document.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Chapter Title",
|
||||||
|
"contentParts": {
|
||||||
|
"extracted_part_id": {
|
||||||
|
"instruction": "Use extracted content with ALL relevant details from user request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generationHint": "Detailed description including ALL relevant details from user request for this chapter",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
CRITICAL INSTRUCTIONS:
|
||||||
|
- Generate chapters based on USER REQUEST, NOT based on the example above
|
||||||
|
- The example shows the JSON structure format, NOT the required chapters
|
||||||
|
- Create only the chapters that match the user's request
|
||||||
|
- Adapt chapter titles and structure to match the user's specific request
|
||||||
|
- Determine outputFormat and language for each document by analyzing the USER REQUEST above
|
||||||
|
- The example shows placeholders "txt" and "de" - YOU MUST REPLACE THESE with actual values determined from the USER REQUEST
|
||||||
|
|
||||||
|
MANDATORY CONTENT ASSIGNMENT CHECK:
|
||||||
|
For each chapter, verify:
|
||||||
|
1. Does the user request mention documents/images/data? (e.g., "photo", "image", "document", "data", "based on", "about")
|
||||||
|
2. Does this chapter's generationHint, title, or purpose relate to those documents/images/data mentioned in step 1?
|
||||||
|
- Examples: "article about the photo", "text describing the image", "analysis of the document", "content based on the data"
|
||||||
|
- Even if chapter doesn't explicitly say "about the image", if user request mentions both the image AND this chapter's content type → relate them
|
||||||
|
3. If YES to both → chapter MUST have contentParts assigned (cannot be empty {})
|
||||||
|
4. If ContentPart is "object" format and chapter needs to write ABOUT it → assign with "instruction" field, not just "caption"
|
||||||
|
|
||||||
|
OUTPUT FORMAT: Start with { and end with }. Do NOT use markdown code fences (```json). Do NOT add explanatory text before or after the JSON. Return ONLY the JSON object itself.
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Einleitung der E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptinhalt",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Hauptteil der E-Mail, der die wesentlichen Informationen und Details enthält, die kommuniziert werden sollen.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Schlussfolgerung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"language": "de"
|
||||||
|
},
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"id": "doc_1",
|
||||||
|
"title": "Email Entwurf",
|
||||||
|
"filename": "email_entwurf.txt",
|
||||||
|
"outputFormat": "txt",
|
||||||
|
"language": "de",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"id": "chapter_1",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Einleitung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Einleitung der E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_2",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Hauptinhalt",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Hauptteil der E-Mail, der die wesentlichen Informationen und Details enthält, die kommuniziert werden sollen.",
|
||||||
|
"sections": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chapter_3",
|
||||||
|
"level": 1,
|
||||||
|
"title": "Schlussfolgerung",
|
||||||
|
"contentParts": {},
|
||||||
|
"generationHint": "Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken.",
|
||||||
|
"sections": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
TASK: Generate Chapter Sections Structure
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
CHAPTER: Einleitung (Level 1, ID: chapter_1)
|
||||||
|
GENERATION HINT: Einleitung der E-Mail, die den Zweck und den Kontext der Nachricht kurz beschreibt.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT sections: Focus on essential information only
|
||||||
|
- AVOID creating too many sections - combine related content where possible
|
||||||
|
- Each section should serve a clear purpose with meaningful data
|
||||||
|
- If no relevant data exists for a topic, do NOT create a section for it
|
||||||
|
- Prefer ONE comprehensive section over multiple sparse sections
|
||||||
|
- HARD LIMIT: Maximum 5 sections per chapter. Combine related subtopics into single sections to stay within this limit.
|
||||||
|
|
||||||
|
**CRITICAL**: The chapter's generationHint above describes what content this chapter should generate. If the generationHint references documents/images/data, then EACH section that generates content for this chapter MUST assign the relevant ContentParts from AVAILABLE CONTENT PARTS below.
|
||||||
|
|
||||||
|
NOTE: Chapter already has a heading section. Do NOT generate a heading for the chapter title.
|
||||||
|
|
||||||
|
## SECTION INDEPENDENCE
|
||||||
|
- Each section is independent and self-contained
|
||||||
|
- One section does NOT have information about another section
|
||||||
|
- Each section must provide its own context and be understandable alone
|
||||||
|
|
||||||
|
AVAILABLE CONTENT PARTS:
|
||||||
|
|
||||||
|
(No content parts specified for this chapter)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE - CRITICAL
|
||||||
|
If AVAILABLE CONTENT PARTS are listed above, then EVERY section that generates content related to those ContentParts MUST assign them explicitly.
|
||||||
|
|
||||||
|
**Assignment logic:**
|
||||||
|
- If section generates text content ABOUT a ContentPart → assign "extracted" format ContentPart with appropriate instruction
|
||||||
|
- If section DISPLAYS a ContentPart → assign "object" format ContentPart
|
||||||
|
- If section's generationHint or purpose relates to a ContentPart listed above → it MUST have contentPartIds assigned
|
||||||
|
- If chapter's generationHint references documents/images/data AND section generates content for that chapter → section MUST assign relevant ContentParts
|
||||||
|
- Empty contentPartIds [] are only allowed if section generates content WITHOUT referencing any available ContentParts AND WITHOUT relating to chapter's generationHint
|
||||||
|
|
||||||
|
## ACCEPTED CONTENT TYPES FOR THIS FORMAT
|
||||||
|
The document output format (txt) accepts only the following content types:
|
||||||
|
table, bullet_list, heading, paragraph, code_block
|
||||||
|
|
||||||
|
**CRITICAL**: Only create sections with content types from this list. Other types will fail.
|
||||||
|
|
||||||
|
useAiCall RULE (simple):
|
||||||
|
- useAiCall: true → Content needs AI processing (extract, transform, generate, filter, summarize)
|
||||||
|
- useAiCall: false → Content can be inserted directly without changes (Format is "object" or "reference")
|
||||||
|
|
||||||
|
RETURN JSON:
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": ["extracted_part_id"],
|
||||||
|
"generationHint": "Description of what to extract or generate",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
**MANDATORY CONTENT ASSIGNMENT CHECK:**
|
||||||
|
For each section, verify:
|
||||||
|
1. Are ContentParts listed in AVAILABLE CONTENT PARTS above?
|
||||||
|
2. Does this section's generationHint or purpose relate to those ContentParts?
|
||||||
|
3. If YES to both → section MUST have contentPartIds assigned (cannot be empty [])
|
||||||
|
4. Assign ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
|
||||||
|
IMAGE SECTIONS:
|
||||||
|
- For image sections, always provide a "caption" field with a descriptive caption for the image.
|
||||||
|
|
||||||
|
Return only valid JSON. Do not include any explanatory text outside the JSON.
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
TASK: Generate Chapter Sections Structure
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
CHAPTER: Hauptinhalt (Level 1, ID: chapter_2)
|
||||||
|
GENERATION HINT: Hauptteil der E-Mail, der die wesentlichen Informationen und Details enthält, die kommuniziert werden sollen.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT sections: Focus on essential information only
|
||||||
|
- AVOID creating too many sections - combine related content where possible
|
||||||
|
- Each section should serve a clear purpose with meaningful data
|
||||||
|
- If no relevant data exists for a topic, do NOT create a section for it
|
||||||
|
- Prefer ONE comprehensive section over multiple sparse sections
|
||||||
|
- HARD LIMIT: Maximum 5 sections per chapter. Combine related subtopics into single sections to stay within this limit.
|
||||||
|
|
||||||
|
**CRITICAL**: The chapter's generationHint above describes what content this chapter should generate. If the generationHint references documents/images/data, then EACH section that generates content for this chapter MUST assign the relevant ContentParts from AVAILABLE CONTENT PARTS below.
|
||||||
|
|
||||||
|
NOTE: Chapter already has a heading section. Do NOT generate a heading for the chapter title.
|
||||||
|
|
||||||
|
## SECTION INDEPENDENCE
|
||||||
|
- Each section is independent and self-contained
|
||||||
|
- One section does NOT have information about another section
|
||||||
|
- Each section must provide its own context and be understandable alone
|
||||||
|
|
||||||
|
AVAILABLE CONTENT PARTS:
|
||||||
|
|
||||||
|
(No content parts specified for this chapter)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE - CRITICAL
|
||||||
|
If AVAILABLE CONTENT PARTS are listed above, then EVERY section that generates content related to those ContentParts MUST assign them explicitly.
|
||||||
|
|
||||||
|
**Assignment logic:**
|
||||||
|
- If section generates text content ABOUT a ContentPart → assign "extracted" format ContentPart with appropriate instruction
|
||||||
|
- If section DISPLAYS a ContentPart → assign "object" format ContentPart
|
||||||
|
- If section's generationHint or purpose relates to a ContentPart listed above → it MUST have contentPartIds assigned
|
||||||
|
- If chapter's generationHint references documents/images/data AND section generates content for that chapter → section MUST assign relevant ContentParts
|
||||||
|
- Empty contentPartIds [] are only allowed if section generates content WITHOUT referencing any available ContentParts AND WITHOUT relating to chapter's generationHint
|
||||||
|
|
||||||
|
## ACCEPTED CONTENT TYPES FOR THIS FORMAT
|
||||||
|
The document output format (txt) accepts only the following content types:
|
||||||
|
table, bullet_list, heading, paragraph, code_block
|
||||||
|
|
||||||
|
**CRITICAL**: Only create sections with content types from this list. Other types will fail.
|
||||||
|
|
||||||
|
useAiCall RULE (simple):
|
||||||
|
- useAiCall: true → Content needs AI processing (extract, transform, generate, filter, summarize)
|
||||||
|
- useAiCall: false → Content can be inserted directly without changes (Format is "object" or "reference")
|
||||||
|
|
||||||
|
RETURN JSON:
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": ["extracted_part_id"],
|
||||||
|
"generationHint": "Description of what to extract or generate",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
**MANDATORY CONTENT ASSIGNMENT CHECK:**
|
||||||
|
For each section, verify:
|
||||||
|
1. Are ContentParts listed in AVAILABLE CONTENT PARTS above?
|
||||||
|
2. Does this section's generationHint or purpose relate to those ContentParts?
|
||||||
|
3. If YES to both → section MUST have contentPartIds assigned (cannot be empty [])
|
||||||
|
4. Assign ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
|
||||||
|
IMAGE SECTIONS:
|
||||||
|
- For image sections, always provide a "caption" field with a descriptive caption for the image.
|
||||||
|
|
||||||
|
Return only valid JSON. Do not include any explanatory text outside the JSON.
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
TASK: Generate Chapter Sections Structure
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
CHAPTER: Schlussfolgerung (Level 1, ID: chapter_3)
|
||||||
|
GENERATION HINT: Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken.
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT sections: Focus on essential information only
|
||||||
|
- AVOID creating too many sections - combine related content where possible
|
||||||
|
- Each section should serve a clear purpose with meaningful data
|
||||||
|
- If no relevant data exists for a topic, do NOT create a section for it
|
||||||
|
- Prefer ONE comprehensive section over multiple sparse sections
|
||||||
|
- HARD LIMIT: Maximum 5 sections per chapter. Combine related subtopics into single sections to stay within this limit.
|
||||||
|
|
||||||
|
**CRITICAL**: The chapter's generationHint above describes what content this chapter should generate. If the generationHint references documents/images/data, then EACH section that generates content for this chapter MUST assign the relevant ContentParts from AVAILABLE CONTENT PARTS below.
|
||||||
|
|
||||||
|
NOTE: Chapter already has a heading section. Do NOT generate a heading for the chapter title.
|
||||||
|
|
||||||
|
## SECTION INDEPENDENCE
|
||||||
|
- Each section is independent and self-contained
|
||||||
|
- One section does NOT have information about another section
|
||||||
|
- Each section must provide its own context and be understandable alone
|
||||||
|
|
||||||
|
AVAILABLE CONTENT PARTS:
|
||||||
|
|
||||||
|
(No content parts specified for this chapter)
|
||||||
|
|
||||||
|
## CONTENT ASSIGNMENT RULE - CRITICAL
|
||||||
|
If AVAILABLE CONTENT PARTS are listed above, then EVERY section that generates content related to those ContentParts MUST assign them explicitly.
|
||||||
|
|
||||||
|
**Assignment logic:**
|
||||||
|
- If section generates text content ABOUT a ContentPart → assign "extracted" format ContentPart with appropriate instruction
|
||||||
|
- If section DISPLAYS a ContentPart → assign "object" format ContentPart
|
||||||
|
- If section's generationHint or purpose relates to a ContentPart listed above → it MUST have contentPartIds assigned
|
||||||
|
- If chapter's generationHint references documents/images/data AND section generates content for that chapter → section MUST assign relevant ContentParts
|
||||||
|
- Empty contentPartIds [] are only allowed if section generates content WITHOUT referencing any available ContentParts AND WITHOUT relating to chapter's generationHint
|
||||||
|
|
||||||
|
## ACCEPTED CONTENT TYPES FOR THIS FORMAT
|
||||||
|
The document output format (txt) accepts only the following content types:
|
||||||
|
table, bullet_list, heading, paragraph, code_block
|
||||||
|
|
||||||
|
**CRITICAL**: Only create sections with content types from this list. Other types will fail.
|
||||||
|
|
||||||
|
useAiCall RULE (simple):
|
||||||
|
- useAiCall: true → Content needs AI processing (extract, transform, generate, filter, summarize)
|
||||||
|
- useAiCall: false → Content can be inserted directly without changes (Format is "object" or "reference")
|
||||||
|
|
||||||
|
RETURN JSON:
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": ["extracted_part_id"],
|
||||||
|
"generationHint": "Description of what to extract or generate",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
**MANDATORY CONTENT ASSIGNMENT CHECK:**
|
||||||
|
For each section, verify:
|
||||||
|
1. Are ContentParts listed in AVAILABLE CONTENT PARTS above?
|
||||||
|
2. Does this section's generationHint or purpose relate to those ContentParts?
|
||||||
|
3. If YES to both → section MUST have contentPartIds assigned (cannot be empty [])
|
||||||
|
4. Assign ContentPart IDs exactly as listed in AVAILABLE CONTENT PARTS above
|
||||||
|
|
||||||
|
IMAGE SECTIONS:
|
||||||
|
- For image sections, always provide a "caption" field with a descriptive caption for the image.
|
||||||
|
|
||||||
|
Return only valid JSON. Do not include any explanatory text outside the JSON.
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"content": "In der Schlussfolgerung fassen wir die wichtigsten Punkte zusammen, die in der E-Mail behandelt wurden. Es ist entscheidend, den Empfänger mit einem klaren und prägnanten Abschluss zu hinterlassen, der die Hauptbotschaft verstärkt und eventuell nächste Schritte oder Erwartungen klärt. Ein abschließender Gedanke könnte auch eine Einladung zur weiteren Diskussion oder Zusammenarbeit sein, um die Beziehung zu stärken und zukünftige Kommunikation zu fördern."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Einleitung zur E-Mail, die den Zweck und den Kontext der Nachricht beschreibt",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Diese E-Mail dient dazu, den Empfänger über die neuesten Entwicklungen in unserem Projekt zu informieren. Wir möchten Ihnen einen Überblick über die aktuellen Fortschritte geben und die nächsten Schritte erläutern. Ihr Feedback ist uns wichtig, um sicherzustellen, dass wir auf dem richtigen Weg sind."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_2",
|
||||||
|
"content_type": "bullet_list",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Hauptziele der E-Mail zusammenfassen",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Information über den aktuellen Projektstatus",
|
||||||
|
"Darstellung der nächsten Schritte",
|
||||||
|
"Einladung zur Rückmeldung und Diskussion"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_3",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Kontext der Nachricht im Rahmen des größeren Projekts",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
"Das Projekt, an dem wir arbeiten, ist ein wesentlicher Bestandteil unserer Unternehmensstrategie für das kommende Jahr. Es zielt darauf ab, unsere Marktposition zu stärken und neue Geschäftsmöglichkeiten zu erschließen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "section_1",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Einleitung und Überblick über die wesentlichen Informationen der E-Mail",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"content": "In diesem Abschnitt wird der Hauptinhalt der E-Mail vorgestellt. Hier werden die wichtigsten Informationen und Details zusammengefasst, die der Empfänger wissen muss. Der Fokus liegt darauf, die Kernaussagen klar und prägnant zu vermitteln."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_2",
|
||||||
|
"content_type": "bullet_list",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Auflistung der Hauptpunkte oder Themen, die in der E-Mail behandelt werden",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "item",
|
||||||
|
"content": "Ziel der E-Mail"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "item",
|
||||||
|
"content": "Wichtige Termine oder Fristen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "item",
|
||||||
|
"content": "Erforderliche Maßnahmen oder Aktionen"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_3",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Detaillierte Informationen zu einem spezifischen Thema oder Punkt",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"content": "Dieser Abschnitt bietet eine detaillierte Erklärung zu einem bestimmten Thema, das in der E-Mail behandelt wird. Hier werden alle relevanten Details und Hintergrundinformationen bereitgestellt, um ein umfassendes Verständnis zu gewährleisten."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_4",
|
||||||
|
"content_type": "table",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Tabellarische Darstellung von Daten oder Informationen, die in der E-Mail enthalten sind",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "row",
|
||||||
|
"content": ["Thema", "Beschreibung"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "row",
|
||||||
|
"content": ["Projektstatus", "Aktueller Stand des Projekts und nächste Schritte"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "row",
|
||||||
|
"content": ["Budget", "Übersicht über die aktuellen Ausgaben und geplante Budgets"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "section_5",
|
||||||
|
"content_type": "paragraph",
|
||||||
|
"contentPartIds": [],
|
||||||
|
"generationHint": "Zusammenfassung und abschließende Bemerkungen",
|
||||||
|
"useAiCall": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"content": "Zum Abschluss der E-Mail werden die wichtigsten Punkte noch einmal zusammengefasst. Es wird darauf hingewiesen, welche nächsten Schritte erforderlich sind und welche Fristen eingehalten werden müssen."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_1
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Einleitung zur E-Mail, die den Zweck und den Kontext der Nachricht beschreibt
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
- section_3 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_2
|
||||||
|
- Content Type: bullet_list
|
||||||
|
- Generation Hint: Hauptziele der E-Mail zusammenfassen
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (bullet_list).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {{"items": ["Item 1", "Item 2", "Item 3"]}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_3 (paragraph):
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_3
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Kontext der Nachricht im Rahmen des größeren Projekts
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_1
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Einleitung und Überblick über die wesentlichen Informationen der E-Mail
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
- section_3 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_2
|
||||||
|
- Content Type: bullet_list
|
||||||
|
- Generation Hint: Auflistung der Hauptpunkte oder Themen, die in der E-Mail behandelt werden
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (bullet_list).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {{"items": ["Item 1", "Item 2", "Item 3"]}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_3 (paragraph):
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Wichtige Informationen klar und prägnant kommunizieren",
|
||||||
|
"Empfänger über spezifische Aktionen oder Entscheidungen informieren",
|
||||||
|
"Erwartungen oder nächste Schritte deutlich machen"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Wichtige Informationen klar und prägnant kommunizieren",
|
||||||
|
"Empfänger über spezifische Aktionen oder Entscheidungen informieren",
|
||||||
|
"Erwartungen oder nächste Schritte deutlich machen"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_3
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Detaillierte Informationen zu einem spezifischen Thema oder Punkt
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_1 (paragraph):
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Begrüßung und Vorstellung des Absenders",
|
||||||
|
"Zweck der E-Mail und Hauptthemen",
|
||||||
|
"Wichtige Informationen oder Updates",
|
||||||
|
"Anfragen oder benötigte Aktionen vom Empfänger",
|
||||||
|
"Abschluss und Dankesworte"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "bullet_list",
|
||||||
|
"content": {
|
||||||
|
"items": [
|
||||||
|
"Begrüßung und Vorstellung des Absenders",
|
||||||
|
"Zweck der E-Mail und Hauptthemen",
|
||||||
|
"Wichtige Informationen oder Updates",
|
||||||
|
"Anfragen oder benötigte Aktionen vom Empfänger",
|
||||||
|
"Abschluss und Dankesworte"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Diese E-Mail dient dazu, den Zweck und den Kontext der Nachricht klar darzustellen. Sie enthält wichtige Informationen, die für das Verständnis des Themas notwendig sind. Bitte lesen Sie die folgenden Abschnitte sorgfältig, um alle relevanten Details zu erfassen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Diese E-Mail dient dazu, den Zweck und den Kontext der Nachricht klar darzustellen. Sie enthält wichtige Informationen, die für das Verständnis des Themas notwendig sind. Bitte lesen Sie die folgenden Abschnitte sorgfältig, um alle relevanten Details zu erfassen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_4
|
||||||
|
- Content Type: table
|
||||||
|
- Generation Hint: Tabellarische Darstellung von Daten oder Informationen, die in der E-Mail enthalten sind
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (table).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"content": {{"headers": ["Column1", "Column2"], "rows": [["Value1", "Value2"], ["Value3", "Value4"]]}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
- section_3 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
- section_3 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_5
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Zusammenfassung und abschließende Bemerkungen
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Previous sections:
|
||||||
|
- section_3 (paragraph):
|
||||||
|
- section_1 (paragraph):
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_3 (paragraph):
|
||||||
|
- section_4 (table):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Diese E-Mail bietet einen Überblick über die wichtigsten Informationen und Themen, die im vorherigen Dokument behandelt wurden. Sie fasst die wesentlichen Punkte zusammen, um den Empfängern einen schnellen und effektiven Einblick zu ermöglichen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Diese E-Mail bietet einen Überblick über die wichtigsten Informationen und Themen, die im vorherigen Dokument behandelt wurden. Sie fasst die wesentlichen Punkte zusammen, um den Empfängern einen schnellen und effektiven Einblick zu ermöglichen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Im Rahmen des Projekts ist es entscheidend, die Kommunikation klar und präzise zu halten. Die Nachricht sollte den aktuellen Fortschritt, die nächsten Schritte und eventuelle Herausforderungen adressieren. Es ist wichtig, alle relevanten Stakeholder auf dem Laufenden zu halten und sicherzustellen, dass alle notwendigen Ressourcen und Informationen bereitgestellt werden, um die Projektziele effizient zu erreichen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Im Rahmen des Projekts ist es entscheidend, die Kommunikation klar und präzise zu halten. Die Nachricht sollte den aktuellen Fortschritt, die nächsten Schritte und eventuelle Herausforderungen adressieren. Es ist wichtig, alle relevanten Stakeholder auf dem Laufenden zu halten und sicherzustellen, dass alle notwendigen Ressourcen und Informationen bereitgestellt werden, um die Projektziele effizient zu erreichen."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# TASK: Generate Section Content
|
||||||
|
|
||||||
|
LANGUAGE: Generate all content in DE language. All text, titles, headings, paragraphs, and content must be written in DE.
|
||||||
|
|
||||||
|
## SECTION METADATA
|
||||||
|
- Section ID: section_1
|
||||||
|
- Content Type: paragraph
|
||||||
|
- Generation Hint: Abschluss der E-Mail mit einer Zusammenfassung oder einem abschließenden Gedanken
|
||||||
|
- Target Output Format: TXT (accepted content types: table, bullet_list, heading, paragraph, code_block)
|
||||||
|
|
||||||
|
## CONTENT EFFICIENCY PRINCIPLES
|
||||||
|
- Generate COMPACT content: Focus on essential facts only
|
||||||
|
- AVOID verbose text, filler phrases, or redundant explanations
|
||||||
|
- Be CONCISE and direct - every word should add value
|
||||||
|
- NO introductory phrases like "This section describes..." or "Here we present..."
|
||||||
|
- Minimize output size for efficient processing
|
||||||
|
|
||||||
|
## INSTRUCTIONS
|
||||||
|
1. Generate content based on the Generation Hint above.
|
||||||
|
2. Create appropriate content that matches the content_type (paragraph).
|
||||||
|
3. The content should be relevant to the USER REQUEST and fit the context of surrounding sections.
|
||||||
|
4. Return only valid JSON with "elements" array.
|
||||||
|
5. No HTML/styling: Plain text only, no markup.
|
||||||
|
6. Keep content CONCISE - focus on substance, not length.
|
||||||
|
|
||||||
|
## OUTPUT FORMAT
|
||||||
|
Return a JSON object with this structure:
|
||||||
|
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {{"text": "This is paragraph text."}}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Output requirements:
|
||||||
|
- "content" must be an object (never a string)
|
||||||
|
- Return only valid JSON - no text before, no text after, no comments, no explanations, no markdown code fences
|
||||||
|
- Start with { and end with } - return ONLY the JSON object itself
|
||||||
|
- Generate meaningful content based on the Generation Hint
|
||||||
|
|
||||||
|
## USER REQUEST
|
||||||
|
```
|
||||||
|
entwirf eine email mit dem inhalt des files davor
|
||||||
|
```
|
||||||
|
|
||||||
|
## CONTEXT
|
||||||
|
|
||||||
|
## DOCUMENT CONTEXT
|
||||||
|
|
||||||
|
Following sections:
|
||||||
|
- section_2 (bullet_list):
|
||||||
|
- section_3 (paragraph):
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Abschließend möchte ich mich für Ihre Aufmerksamkeit und Unterstützung bedanken. Ich freue mich auf Ihre Rückmeldung und hoffe auf eine positive Zusammenarbeit. Bei weiteren Fragen stehe ich Ihnen gerne zur Verfügung."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Abschließend möchte ich mich für Ihre Aufmerksamkeit und Unterstützung bedanken. Ich freue mich auf Ihre Rückmeldung und hoffe auf eine positive Zusammenarbeit. Bei weiteren Fragen stehe ich Ihnen gerne zur Verfügung."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Beim Entwerfen einer E-Mail ist es wichtig, den Zweck klar zu definieren und die Nachricht präzise zu formulieren. Beginnen Sie mit einer höflichen Anrede, gefolgt von einer kurzen Einführung in das Thema. Der Hauptteil sollte die wesentlichen Informationen enthalten, die der Empfänger benötigt, um die Nachricht zu verstehen und darauf zu reagieren. Abschließend sollte die E-Mail mit einem klaren Aufruf zum Handeln oder einer Zusammenfassung der nächsten Schritte enden. Höfliche Grüße und eine Signatur runden die E-Mail ab."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "paragraph",
|
||||||
|
"content": {
|
||||||
|
"text": "Beim Entwerfen einer E-Mail ist es wichtig, den Zweck klar zu definieren und die Nachricht präzise zu formulieren. Beginnen Sie mit einer höflichen Anrede, gefolgt von einer kurzen Einführung in das Thema. Der Hauptteil sollte die wesentlichen Informationen enthalten, die der Empfänger benötigt, um die Nachricht zu verstehen und darauf zu reagieren. Abschließend sollte die E-Mail mit einem klaren Aufruf zum Handeln oder einer Zusammenfassung der nächsten Schritte enden. Höfliche Grüße und eine Signatur runden die E-Mail ab."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"content": {
|
||||||
|
"headers": ["Betreff", "Inhalt"],
|
||||||
|
"rows": [
|
||||||
|
["Anrede", "Sehr geehrte Damen und Herren,"],
|
||||||
|
["Einleitung", "Ich hoffe, diese Nachricht trifft Sie wohl."],
|
||||||
|
["Hauptteil", "Im Anhang finden Sie die erforderlichen Informationen."],
|
||||||
|
["Schluss", "Vielen Dank für Ihre Aufmerksamkeit."],
|
||||||
|
["Grüße", "Mit freundlichen Grüßen, [Ihr Name]"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue