import { ConfigService } from "@nestjs/config"; import { z } from "zod"; import { BaseConfigInterface } from "../../../config/interfaces"; import { LLMService } from "../../../core/llm/services/llm.service"; import { AppLoggingService } from "../../../core/logging/services/logging.service"; import { ChunkAnalysisInterface } from "../../../common/interfaces/agents/graph.creator.interface"; export declare const prompt = "\nYou are an intelligent assistant that extracts structured knowledge from text.\n\n## CRITICAL: Garbage Detection\n\n**BEFORE attempting any extraction, evaluate if the text is intelligible.**\n\nIf the text contains:\n- Unintelligible OCR garbage or random characters (e.g., \"!\u00A7Ydsv$\", \"aitsru{.*U\", \"Q\u00A7tvllvll\")\n- Mostly punctuation marks with no semantic meaning (e.g., \"!!!\", \"===\", \"|||\")\n- Random character sequences that form no recognizable words\n- Repetitive meaningless patterns\n- No coherent sentences or semantic content\n\n**Then you MUST:**\n- Return EMPTY atomicFacts array: []\n- Return EMPTY keyConceptsRelationships array: []\n- Do NOT attempt to extract anything from garbage text\n\n## Definitions\n\n**Atomic Fact**: A single, indivisible statement containing **ONE action, ONE event, or ONE relationship**. Each atomic fact must represent the smallest unit of meaningful information that cannot be broken down further.\n\n**CRITICAL: ONE ACTION PER FACT**\n- Each atomic fact must contain ONLY ONE verb/action\n- If a sentence contains multiple actions connected by \"and\", \"but\", commas, split it into separate atomic facts\n- Each action, decision, or event gets its own atomic fact\n\n**Examples of CORRECT Atomic Facts (one action each):**\n- \u2705 \"The president detects the ambiguity of the notification\"\n- \u2705 \"The president grants an extension until 15/2/2023\"\n- \u2705 \"The president postpones the hearing to 29/3/2023\"\n- \u2705 \"Joe Bauer was born in London on 03.04.1985\"\n\n**Examples of INCORRECT Atomic Facts (multiple actions - MUST BE SPLIT):**\n- \u274C \"The president detects the ambiguity of the notification, grants an extension until 15/2/2023 and postpones the hearing to 29/3/2023\"\n \u2192 WRONG: Contains 3 actions (detects, grants, postpones) - must be split into 3 atomic facts\n- \u274C \"Joe Bauer was born in London and studied at university\"\n \u2192 WRONG: Contains 2 actions (was born, studied) - must be split into 2 atomic facts\n\n**Key Concept**: ONLY semantically meaningful entities - proper nouns, specific terms, named entities:\n\n**VALID Key Concepts (extract these):**\n- **Proper names**: \"joe bauer\", \"mike modano\", ...\n- **Places**: \"london\", \"italy\", \"rome\", \"washington\", ...\n- **Organizations**: \"microsoft\", \"apple\", \"united nations\", \"tribunale di roma\", ...\n- **Complete dates with legal significance**: \"28.12.2019\", \"15/2/2023\", \"29/3/2023\", \"03.04.1985\", \"15 january 2023\"\n - \u2705 ONLY extract dates that are significant to the atomic fact\n - \u2705 Include time ONLY when paired with a date AND relevant to the atomic fact: \"29/3/2023 alle 10.40\"\n- **Acronyms**: \"upu\", \"nlp\", \"api\", \"crm\", \"d.p.r.\", \"c.c.\", \"c.p.\" (always lowercase)\n- **Technical terms**: \"knowledge base\", \"semantic search\", \"blockchain\"\n- **Products/systems**: \"kubernetes\", \"microsoft\", \"s3\"\n\n**INVALID Key Concepts (NEVER extract these):**\n- \u274C Single characters: \"!\", \"e\", \"i\", \"a\", \"o\", \"n\", \"'\"\n- \u274C Pure punctuation: \".\", \",\", \":\", \";\", \"(\", \")\", \"[\", \"]\"\n- \u274C Random garbage: \"!\u00A7Ydsv$\", \"Q\u00A7tvllvll\", \"aitsru{.*U\", \"ourpEl}r\"\n- \u274C Meaningless sequences: \"||!\", \"===\", \"___\", \"***\"\n- \u274C Pure numbers without context: \"254\", \"819\", \"123\"\n- \u274C **Isolated times without dates**: \"12.40\", \"10:30\", \"15.00\" (unless part of legally significant event like \"udienza alle 10.40\" with date)\n- \u274C **Administrative timestamps**: \"verbale chiuso alle 12.40\", \"documento firmato alle 15.00\" (not legally significant)\n- \u274C Generic words without specific meaning: \"thing\", \"way\", \"type\", \"method\"\n\n**Markdown Headers**: Structural elements like \"## Data Architecture\" that organize content.\n\n## Instructions\n\n1. **Evaluate text quality** - Is this intelligible text or garbage? If garbage, return empty arrays.\n2. **Check for markdown headers** - If text starts with ##, ###, etc., note the complete header text\n3. **Decompose compound sentences** - If a sentence contains multiple actions/verbs (connected by \"and\", \"but\", commas):\n - Break it into separate atomic facts\n - Each action gets its own atomic fact\n - Example: \"The president detects the ambiguity, grants an extension and postpones the hearing\" \u2192 3 atomic facts\n4. **Extract atomic facts** - Only from intelligible, meaningful text. ONE ACTION PER FACT.\n5. **MANDATORY: Create summary atomic fact** - Must include the markdown header if present. Example: \"Recommendation 1 focuses on improving UPU service standards\" (key concepts: \"recommendation 1\", \"upu\", \"service standards\")\n6. **Identify key concepts** - Only SEMANTICALLY MEANINGFUL entities (names, places, significant dates, organizations, legal terms)\n7. **Create relationships** - Between valid key concepts based on how they connect in atomic facts\n\n## Atomic Fact Rules\n\n**CRITICAL: ONE ACTION/EVENT PER ATOMIC FACT**\n- Each atomic fact must contain ONLY ONE verb/action\n- If you see multiple verbs in a sentence (e.g., \"detects\", \"grants\", \"postpones\"), create separate atomic facts for each\n- Use the subject from the original sentence for each split fact\n- Each atomic fact must be a complete, grammatically correct sentence\n\n**Decomposition Process:**\n1. Identify all verbs/actions in the sentence\n2. Count them - if more than one, decomposition is required\n3. Create one atomic fact per action, maintaining the subject\n4. Example:\n - Input: \"The president detects the ambiguity, grants an extension and postpones the hearing\"\n - Actions found: \"detects\" (1), \"grants\" (2), \"postpones\" (3) = 3 actions\n - Output: 3 atomic facts:\n 1. \"The president detects the ambiguity\"\n 2. \"The president grants an extension\"\n 3. \"The president postpones the hearing\"\n\n## Key Concept Rules\n\n- Key concepts **MUST** be semantically meaningful entities (see examples above)\n- **COPY VERBATIM** from the text (lowercasing allowed, no other changes)\n- Minimum 2 characters length\n- Must contain actual semantic meaning (not punctuation, not single letters)\n- **DO NOT change** spelling, letters, or structure\n- Always include acronyms and technical terms found in text\n- Include complete markdown headers as Key Concepts: \"## Recommendation 1\" becomes \"recommendation 1\"\n- Every key concept must appear in at least one atomic fact\n\n**Character Requirements:**\n- Must have at least 40% alphanumeric characters (not mostly punctuation)\n- Cannot be pure punctuation or special characters\n- Cannot be random character sequences\n\n## Key Concept Descriptions\n\nFor each unique key concept extracted, generate a brief description (1-2 sentences) that:\n- Explains what the entity is in the context of the document\n- Captures its role, type, or significance\n- Uses information from the text to provide context\n\n**Examples:**\n- \"joe bauer\" \u2192 \"A person born in London who studied at university\"\n- \"tribunale di roma\" \u2192 \"The court of Rome, an Italian judicial institution\"\n- \"upu\" \u2192 \"Universal Postal Union, an international postal organization\"\n- \"15/2/2023\" \u2192 \"Date when the president granted an extension\"\n\n## Relationships Rules\n\n**Key Concepts Relationships**: Analyze relationships between key concepts to create a network graph.\n- For each relationship:\n - **node_1**: First key concept (must be a valid key concept from extraction)\n - **node_2**: Second key concept (must be a valid key concept from extraction)\n - **edge**: Sentence describing the relationship in present tense\n- Only create relationships between VALID key concepts\n- Both nodes must be semantically meaningful entities\n\n## Additional Considerations\n\n- **DECOMPOSE compound sentences** - Always split sentences with multiple actions into separate atomic facts\n- Focus on extracting **named entities** and **specific domain terminology**\n- Ignore filler words, articles, prepositions, conjunctions\n- Pay special attention to proper names, places, significant dates, organizations, and legal entities\n- Terms mentioned in the same sentence or paragraph are typically related\n\n## CRITICAL: Quality over Quantity\n\n- It is BETTER to return empty arrays than to extract garbage\n- Only extract from intelligible, meaningful text\n- Every key concept must be a real entity with semantic meaning\n- Single characters, punctuation, and random sequences are NEVER valid key concepts\n\n## CRITICAL: Atomic Fact Decomposition\n\n**MANDATORY PROCESS FOR EVERY SENTENCE:**\n1. Count the number of actions/verbs in the sentence\n2. If count > 1, YOU MUST split into separate atomic facts\n3. Each action gets its own atomic fact with complete subject and context\n4. NEVER create compound atomic facts with multiple actions\n\n**Remember:**\n- \u274C WRONG: \"The president detects, grants and postpones\" (3 actions in 1 fact)\n- \u2705 RIGHT: Three separate facts - one for \"detects\", one for \"grants\", one for \"postpones\"\n\n## **Strictly follow the above instructions. Evaluate text quality first, then decompose compound sentences. Begin.**\n"; /** * The default Graph Creator system prompt, exported under a descriptive name. * * This single prompt drives ONE LLM call whose schema demands `atomicFacts`, * `keyConceptsRelationships` AND `keyConceptDescriptions`. An app that overrides * `prompts.graphCreator` must therefore COMPOSE on top of this default (append a * domain tail) rather than replace it — replacing it with a facts-only prompt * leaves the relationship and description fields uninstructed, and they come * back empty. */ export declare const defaultGraphCreatorPrompt = "\nYou are an intelligent assistant that extracts structured knowledge from text.\n\n## CRITICAL: Garbage Detection\n\n**BEFORE attempting any extraction, evaluate if the text is intelligible.**\n\nIf the text contains:\n- Unintelligible OCR garbage or random characters (e.g., \"!\u00A7Ydsv$\", \"aitsru{.*U\", \"Q\u00A7tvllvll\")\n- Mostly punctuation marks with no semantic meaning (e.g., \"!!!\", \"===\", \"|||\")\n- Random character sequences that form no recognizable words\n- Repetitive meaningless patterns\n- No coherent sentences or semantic content\n\n**Then you MUST:**\n- Return EMPTY atomicFacts array: []\n- Return EMPTY keyConceptsRelationships array: []\n- Do NOT attempt to extract anything from garbage text\n\n## Definitions\n\n**Atomic Fact**: A single, indivisible statement containing **ONE action, ONE event, or ONE relationship**. Each atomic fact must represent the smallest unit of meaningful information that cannot be broken down further.\n\n**CRITICAL: ONE ACTION PER FACT**\n- Each atomic fact must contain ONLY ONE verb/action\n- If a sentence contains multiple actions connected by \"and\", \"but\", commas, split it into separate atomic facts\n- Each action, decision, or event gets its own atomic fact\n\n**Examples of CORRECT Atomic Facts (one action each):**\n- \u2705 \"The president detects the ambiguity of the notification\"\n- \u2705 \"The president grants an extension until 15/2/2023\"\n- \u2705 \"The president postpones the hearing to 29/3/2023\"\n- \u2705 \"Joe Bauer was born in London on 03.04.1985\"\n\n**Examples of INCORRECT Atomic Facts (multiple actions - MUST BE SPLIT):**\n- \u274C \"The president detects the ambiguity of the notification, grants an extension until 15/2/2023 and postpones the hearing to 29/3/2023\"\n \u2192 WRONG: Contains 3 actions (detects, grants, postpones) - must be split into 3 atomic facts\n- \u274C \"Joe Bauer was born in London and studied at university\"\n \u2192 WRONG: Contains 2 actions (was born, studied) - must be split into 2 atomic facts\n\n**Key Concept**: ONLY semantically meaningful entities - proper nouns, specific terms, named entities:\n\n**VALID Key Concepts (extract these):**\n- **Proper names**: \"joe bauer\", \"mike modano\", ...\n- **Places**: \"london\", \"italy\", \"rome\", \"washington\", ...\n- **Organizations**: \"microsoft\", \"apple\", \"united nations\", \"tribunale di roma\", ...\n- **Complete dates with legal significance**: \"28.12.2019\", \"15/2/2023\", \"29/3/2023\", \"03.04.1985\", \"15 january 2023\"\n - \u2705 ONLY extract dates that are significant to the atomic fact\n - \u2705 Include time ONLY when paired with a date AND relevant to the atomic fact: \"29/3/2023 alle 10.40\"\n- **Acronyms**: \"upu\", \"nlp\", \"api\", \"crm\", \"d.p.r.\", \"c.c.\", \"c.p.\" (always lowercase)\n- **Technical terms**: \"knowledge base\", \"semantic search\", \"blockchain\"\n- **Products/systems**: \"kubernetes\", \"microsoft\", \"s3\"\n\n**INVALID Key Concepts (NEVER extract these):**\n- \u274C Single characters: \"!\", \"e\", \"i\", \"a\", \"o\", \"n\", \"'\"\n- \u274C Pure punctuation: \".\", \",\", \":\", \";\", \"(\", \")\", \"[\", \"]\"\n- \u274C Random garbage: \"!\u00A7Ydsv$\", \"Q\u00A7tvllvll\", \"aitsru{.*U\", \"ourpEl}r\"\n- \u274C Meaningless sequences: \"||!\", \"===\", \"___\", \"***\"\n- \u274C Pure numbers without context: \"254\", \"819\", \"123\"\n- \u274C **Isolated times without dates**: \"12.40\", \"10:30\", \"15.00\" (unless part of legally significant event like \"udienza alle 10.40\" with date)\n- \u274C **Administrative timestamps**: \"verbale chiuso alle 12.40\", \"documento firmato alle 15.00\" (not legally significant)\n- \u274C Generic words without specific meaning: \"thing\", \"way\", \"type\", \"method\"\n\n**Markdown Headers**: Structural elements like \"## Data Architecture\" that organize content.\n\n## Instructions\n\n1. **Evaluate text quality** - Is this intelligible text or garbage? If garbage, return empty arrays.\n2. **Check for markdown headers** - If text starts with ##, ###, etc., note the complete header text\n3. **Decompose compound sentences** - If a sentence contains multiple actions/verbs (connected by \"and\", \"but\", commas):\n - Break it into separate atomic facts\n - Each action gets its own atomic fact\n - Example: \"The president detects the ambiguity, grants an extension and postpones the hearing\" \u2192 3 atomic facts\n4. **Extract atomic facts** - Only from intelligible, meaningful text. ONE ACTION PER FACT.\n5. **MANDATORY: Create summary atomic fact** - Must include the markdown header if present. Example: \"Recommendation 1 focuses on improving UPU service standards\" (key concepts: \"recommendation 1\", \"upu\", \"service standards\")\n6. **Identify key concepts** - Only SEMANTICALLY MEANINGFUL entities (names, places, significant dates, organizations, legal terms)\n7. **Create relationships** - Between valid key concepts based on how they connect in atomic facts\n\n## Atomic Fact Rules\n\n**CRITICAL: ONE ACTION/EVENT PER ATOMIC FACT**\n- Each atomic fact must contain ONLY ONE verb/action\n- If you see multiple verbs in a sentence (e.g., \"detects\", \"grants\", \"postpones\"), create separate atomic facts for each\n- Use the subject from the original sentence for each split fact\n- Each atomic fact must be a complete, grammatically correct sentence\n\n**Decomposition Process:**\n1. Identify all verbs/actions in the sentence\n2. Count them - if more than one, decomposition is required\n3. Create one atomic fact per action, maintaining the subject\n4. Example:\n - Input: \"The president detects the ambiguity, grants an extension and postpones the hearing\"\n - Actions found: \"detects\" (1), \"grants\" (2), \"postpones\" (3) = 3 actions\n - Output: 3 atomic facts:\n 1. \"The president detects the ambiguity\"\n 2. \"The president grants an extension\"\n 3. \"The president postpones the hearing\"\n\n## Key Concept Rules\n\n- Key concepts **MUST** be semantically meaningful entities (see examples above)\n- **COPY VERBATIM** from the text (lowercasing allowed, no other changes)\n- Minimum 2 characters length\n- Must contain actual semantic meaning (not punctuation, not single letters)\n- **DO NOT change** spelling, letters, or structure\n- Always include acronyms and technical terms found in text\n- Include complete markdown headers as Key Concepts: \"## Recommendation 1\" becomes \"recommendation 1\"\n- Every key concept must appear in at least one atomic fact\n\n**Character Requirements:**\n- Must have at least 40% alphanumeric characters (not mostly punctuation)\n- Cannot be pure punctuation or special characters\n- Cannot be random character sequences\n\n## Key Concept Descriptions\n\nFor each unique key concept extracted, generate a brief description (1-2 sentences) that:\n- Explains what the entity is in the context of the document\n- Captures its role, type, or significance\n- Uses information from the text to provide context\n\n**Examples:**\n- \"joe bauer\" \u2192 \"A person born in London who studied at university\"\n- \"tribunale di roma\" \u2192 \"The court of Rome, an Italian judicial institution\"\n- \"upu\" \u2192 \"Universal Postal Union, an international postal organization\"\n- \"15/2/2023\" \u2192 \"Date when the president granted an extension\"\n\n## Relationships Rules\n\n**Key Concepts Relationships**: Analyze relationships between key concepts to create a network graph.\n- For each relationship:\n - **node_1**: First key concept (must be a valid key concept from extraction)\n - **node_2**: Second key concept (must be a valid key concept from extraction)\n - **edge**: Sentence describing the relationship in present tense\n- Only create relationships between VALID key concepts\n- Both nodes must be semantically meaningful entities\n\n## Additional Considerations\n\n- **DECOMPOSE compound sentences** - Always split sentences with multiple actions into separate atomic facts\n- Focus on extracting **named entities** and **specific domain terminology**\n- Ignore filler words, articles, prepositions, conjunctions\n- Pay special attention to proper names, places, significant dates, organizations, and legal entities\n- Terms mentioned in the same sentence or paragraph are typically related\n\n## CRITICAL: Quality over Quantity\n\n- It is BETTER to return empty arrays than to extract garbage\n- Only extract from intelligible, meaningful text\n- Every key concept must be a real entity with semantic meaning\n- Single characters, punctuation, and random sequences are NEVER valid key concepts\n\n## CRITICAL: Atomic Fact Decomposition\n\n**MANDATORY PROCESS FOR EVERY SENTENCE:**\n1. Count the number of actions/verbs in the sentence\n2. If count > 1, YOU MUST split into separate atomic facts\n3. Each action gets its own atomic fact with complete subject and context\n4. NEVER create compound atomic facts with multiple actions\n\n**Remember:**\n- \u274C WRONG: \"The president detects, grants and postpones\" (3 actions in 1 fact)\n- \u2705 RIGHT: Three separate facts - one for \"detects\", one for \"grants\", one for \"postpones\"\n\n## **Strictly follow the above instructions. Evaluate text quality first, then decompose compound sentences. Begin.**\n"; /** The library's historical field descriptions, kept as the default. */ export declare const defaultKeyConceptsDescription = "Only semantically meaningful entities: proper names (people, organizations), places, significant dates (with full date like \"15/2/2023\", NOT isolated times like \"12.40\"). Preserve exact characters. NO common nouns, NO isolated times without dates, NO administrative timestamps. Examples: \"andrea ciampaglia\", \"tribunale di roma\", \"15/2/2023\", \"notifica\", \"presidente\" - NOT \"verbale\", \"12.40\", \"player\", \"thing\""; export declare const defaultAtomicFactDescription = "A single, indivisible fact containing ONLY ONE action/event/relationship. Each fact must have exactly ONE verb. If source text has multiple actions (e.g., \"detects, grants and postpones\"), split into separate atomic facts. NO compound sentences. Examples: \"The president detects the ambiguity of the notification\" (one action: detects). NOT: \"The president detects the ambiguity and grants an extension\" (two actions - must split)."; export declare const defaultKeyConceptDescriptionDescription = "Brief 1-2 sentence description of what this entity is in the context of the document. Explains its role, type, or significance."; /** * The extraction contract every Graph Creator prompt must satisfy. * * Three field descriptions are overridable through * `ConfigPromptsInterface.graphCreatorSchemaDescriptions`; everything else is * fixed. Called with no arguments the schema is identical to the historical * hardcoded one, so existing consumers are unaffected. * * The three that open up are the three that say WHAT COUNTS as an entity, a * fact and a description — the only places in the contract where the answer is * domain-specific. An app extracting invented fiction and an app extracting * legal filings disagree completely about them, and a description travels * inline with the field it governs, which is where a model actually reads it. */ export declare const buildGraphCreatorOutputSchema: (descriptions?: { keyConcepts?: string; atomicFact?: string; keyConceptDescription?: string; }) => z.ZodObject<{ atomicFacts: z.ZodArray; atomicFact: z.ZodString; }, z.core.$strip>>; keyConceptsRelationships: z.ZodArray>; keyConceptDescriptions: z.ZodArray>; dates: z.ZodOptional>>; }, z.core.$strip>; /** * The contract built with the library's own descriptions. * * Kept as a named export so a consumer evaluating one prompt or model against * another issues the SAME schema the production call issues, rather than a * hand-copied twin that silently drifts. */ export declare const graphCreatorOutputSchema: z.ZodObject<{ atomicFacts: z.ZodArray; atomicFact: z.ZodString; }, z.core.$strip>>; keyConceptsRelationships: z.ZodArray>; keyConceptDescriptions: z.ZodArray>; dates: z.ZodOptional>>; }, z.core.$strip>; /** * Check if a key concept is valid (not pure punctuation, has minimum length, meaningful characters) * * Exported because this is the gate that decides what actually reaches the graph: * a concept rejected here was tokens spent for nothing, so the rejection RATE is * the honest measure of how well a given prompt/model pair is extracting. Any * evaluation that scores raw model output rather than what survives this filter * is scoring something the application never stores. * * @param concept - The key concept to validate * @returns true if the concept is valid and should be kept */ export declare function isValidKeyConcept(concept: string): boolean; export declare class GraphCreatorService { private readonly llmService; private readonly logger; private readonly configService; private readonly systemPrompt; private readonly outputSchema; constructor(llmService: LLMService, logger: AppLoggingService, configService: ConfigService); generateGraph(params: { content: string; relationshipId?: string; relationshipType?: string; }): Promise; } //# sourceMappingURL=graph.creator.service.d.ts.map