refactor(llm): elevate prompt engineering with context grounding and contrastive taxonomy
This commit is contained in:
@@ -148,7 +148,7 @@
|
||||
"146": "Specification Quality Checklist: Convert Article JSON to Markdown",
|
||||
"147": "CLI Contract: `convert_article_to_markdown.py`",
|
||||
"148": "9. Interface CLI",
|
||||
"149": "get_hl_gl_ceid",
|
||||
"149": "sample_rss_xml",
|
||||
"150": "13. Estratégia de testes",
|
||||
"151": "6. Contrato de entrada",
|
||||
"152": "InherenceClassifier",
|
||||
@@ -164,7 +164,7 @@
|
||||
"162": "test_normalize_date_iso_8601_variants",
|
||||
"163": "test_metadata_priority_original_url_all_fallbacks",
|
||||
"164": "test_normalize_scalar_non_string_types",
|
||||
"165": "LLMFallbackAdapter",
|
||||
"165": ".disambiguate",
|
||||
"166": "remove_duplicate_initial_h1",
|
||||
"167": "test_normalize_scalar_whitespace_collapsing"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"0": "36bdb6f09c457f7c", "1": "8c5bf6244cf710c6", "2": "efbcc9c62a3ee78b", "3": "8599153989b07faa", "4": "b5952a1f7fee9f20", "5": "5b8462a3f82d188c", "6": "80f79e9e2011a3e3", "7": "4654167fd211d027", "8": "50acfa00fe353440", "9": "c6d2f770737823f1", "10": "44f2ca451aea24be", "11": "feaac5ab67a8c17a", "12": "b71bd92e5edbf2e0", "13": "219d65ba6d2689e4", "14": "8e30bb8112fd02d1", "15": "03906ab80b99db85", "16": "5d51c60ba1bc2be0", "17": "a1da914f522dcd21", "18": "fbad840891b90569", "19": "0686ff2d6fe29fb3", "20": "060baa9e1924b465", "21": "a5c8f2c3080b8243", "22": "0d76852f1d29eeb1", "23": "6ff68619f2d72924", "24": "3da11675eee7ec46", "25": "a6696589e9556f97", "26": "6c752999e8a4d4b6", "27": "2d4e13ea2111d750", "28": "4b60cb0ee1ac186a", "29": "f56fbca9bb8235ec", "30": "c7beed940704509f", "31": "38be2d254fb31ae8", "32": "ee5596fcf7e7c0b3", "33": "e4d4e0a440bc599f", "34": "c897e49c001acdae", "35": "3aad272a2cf5d495", "36": "0a197439d306b956", "37": "f43acf5c8b1329af", "38": "6775efafc9b33338", "39": "8176a164778526f9", "40": "66b69189c0acc3ff", "41": "0322ff824966a4d8", "42": "784c9e3d336a7f53", "43": "4b8bb6c3f7b64856", "44": "18c0ff3e6225bcb2", "45": "b18defdea7d53e37", "46": "54c0fceb01591230", "47": "0fad42a4989aa7e3", "48": "0237e1e02ee47a27", "49": "0d0f9f015921feef", "50": "8d0c81e5ca23e9a6", "51": "f79963571b9c15ee", "52": "5935824c825606cb", "53": "9685f9cbe158e50b", "54": "3d5ab759f350bc79", "55": "d549f24931a990e9", "56": "3cc031dcb648797c", "57": "a0ab88e6c629251d", "58": "76bd6412e2a22ecd", "59": "54827845564490c9", "60": "0a9736c416c0c6b9", "61": "77358620ac528153", "62": "3b0c585df09df48a", "63": "7e78cd3b28828c20", "64": "1c0c958231735f61", "65": "60b0f81225f62f69", "66": "920754c65cc94b88", "67": "df911472140a9b94", "68": "8e17bc11bcea91b9", "69": "7e905b75e4f28b95", "70": "a28424eca5d36c55", "71": "2cdb53d5b6051ab6", "72": "e42fbd3dc744e730", "73": "7fe2cac980de160c", "74": "2b1343a6a9db1487", "75": "54a1bb232f1d4ceb", "76": "442ba11d31ec0e0a", "77": "852a25b8b95bf8d1", "78": "1810ab370b9cd608", "79": "0fc5dca02a3f02f6", "80": "6ff8a97e63c9a2f3", "81": "a38f84ae3d895236", "82": "dc6ddc157a3b9efb", "83": "a05140495d7a0353", "84": "24ca89fec34df075", "85": "f8bfd0cfe9e8b478", "86": "410d15a346bd5894", "87": "6b41d288cfd834ab", "88": "5aa6db96312a8811", "89": "80225792bb62ba04", "90": "e18a0a239fe528ba", "91": "d4579c5b7aa2742a", "92": "7b9ba7c3bff11361", "93": "71cd9c1fa4a857f0", "94": "34cd980be3c32d21", "95": "970093453f3b7d90", "96": "9e96780a2b7c4bd6", "97": "b7c10b0e09caac0b", "98": "089ea6a55861c693", "99": "cb6165a7dc822d29", "100": "8c97d8c400895e15", "101": "bd22248d0516e5d4", "102": "6aa00d5a83295f11", "103": "f58668f5b10ccdeb", "104": "4ec787414cc6f50b", "105": "1cf3077fd45d874a", "106": "edcd5d9bb3c4b00f", "107": "37f2f47110fe3eaa", "108": "b7ad5abb1da8cf8d", "109": "cb48a9c4f54efa38", "110": "f6dd36fd7f3edbe5", "111": "2925b620f0b1fd17", "112": "d8b3099917c3b711", "113": "3bb61caa0302c804", "114": "0d4f1d08dd056bb9", "115": "4ac2dcddeec2ff11", "116": "07da9aae9668f573", "117": "196f63e0c4536d30", "118": "ade84262e3cfac12", "119": "ebe4e5e0c42c613f", "120": "27256931b19a2867", "121": "5396e68ca6c185ad", "122": "aa8a1de55696b666", "123": "96618c9a362af46c", "124": "83f104cbb62fd03e", "125": "6db738fb27190349", "126": "6a087a22cbcef972", "127": "85fd71a0cad8d3a5", "128": "22dd4feed96c4229", "129": "c4d2f60f532e6f16", "130": "f6b0aa8a1568926b", "131": "142d0db70bad18fe", "132": "67ea4284cbc02c54", "133": "d899cfc86c7a4a27", "134": "ba9464410a9b4168", "135": "0d496a12149eca27", "136": "521f5c7b9d566b4d", "137": "9e37828bdd2ba8c5", "138": "ec03c97194c56f91", "139": "f4e6d5dfa30034c5", "140": "d9b47fa423cf0748", "141": "1e0330b8757f333e", "142": "f35d75e1194c008d", "143": "4d2ae7190b514a34", "144": "4a98716cabf43f86", "145": "56b2431193739c38", "146": "edc785fd71bb0675", "147": "4c7347f8f86e1fbd", "148": "8ca77cc4fd6fd437", "149": "09850697b717469a", "150": "f4f4ce1a1180ddb1", "151": "e426746f6e9ee15f", "152": "756d0fd1d69866c1", "153": "a3593e6f45bafb20", "154": "56747bad6345d66b", "155": "a8e7498fa7e257df", "156": "56e7b2355898077f", "157": "f2fc88f7d8214711", "158": "c966f6f8570c8c29", "159": "5f6094aa385f3bfe", "160": "2834e7d59672e756", "161": "cc6e436d94fd0033", "162": "64f33a2fc8969cd2", "163": "26ac1c0a00eabce1", "164": "cdcea44a6805ae55", "165": "5faccba309eb478d", "166": "85c97dab928b9b1b", "167": "7ab5695391e32126"}
|
||||
{"0": "36bdb6f09c457f7c", "1": "8c5bf6244cf710c6", "2": "efbcc9c62a3ee78b", "3": "8599153989b07faa", "4": "b5952a1f7fee9f20", "5": "5b8462a3f82d188c", "6": "80f79e9e2011a3e3", "7": "4654167fd211d027", "8": "50acfa00fe353440", "9": "c6d2f770737823f1", "10": "44f2ca451aea24be", "11": "feaac5ab67a8c17a", "12": "b71bd92e5edbf2e0", "13": "219d65ba6d2689e4", "14": "8e30bb8112fd02d1", "15": "03906ab80b99db85", "16": "5d51c60ba1bc2be0", "17": "a1da914f522dcd21", "18": "fbad840891b90569", "19": "0686ff2d6fe29fb3", "20": "060baa9e1924b465", "21": "a5c8f2c3080b8243", "22": "0d76852f1d29eeb1", "23": "6ff68619f2d72924", "24": "3da11675eee7ec46", "25": "a6696589e9556f97", "26": "6c752999e8a4d4b6", "27": "2d4e13ea2111d750", "28": "4b60cb0ee1ac186a", "29": "f56fbca9bb8235ec", "30": "c7beed940704509f", "31": "38be2d254fb31ae8", "32": "ee5596fcf7e7c0b3", "33": "e4d4e0a440bc599f", "34": "c897e49c001acdae", "35": "3aad272a2cf5d495", "36": "0a197439d306b956", "37": "f43acf5c8b1329af", "38": "6775efafc9b33338", "39": "8176a164778526f9", "40": "66b69189c0acc3ff", "41": "0322ff824966a4d8", "42": "784c9e3d336a7f53", "43": "4b8bb6c3f7b64856", "44": "18c0ff3e6225bcb2", "45": "b18defdea7d53e37", "46": "54c0fceb01591230", "47": "0fad42a4989aa7e3", "48": "0237e1e02ee47a27", "49": "0d0f9f015921feef", "50": "8d0c81e5ca23e9a6", "51": "f79963571b9c15ee", "52": "5935824c825606cb", "53": "9685f9cbe158e50b", "54": "3d5ab759f350bc79", "55": "d549f24931a990e9", "56": "3cc031dcb648797c", "57": "a0ab88e6c629251d", "58": "76bd6412e2a22ecd", "59": "54827845564490c9", "60": "0a9736c416c0c6b9", "61": "77358620ac528153", "62": "3b0c585df09df48a", "63": "7e78cd3b28828c20", "64": "1c0c958231735f61", "65": "60b0f81225f62f69", "66": "920754c65cc94b88", "67": "df911472140a9b94", "68": "8e17bc11bcea91b9", "69": "7e905b75e4f28b95", "70": "a28424eca5d36c55", "71": "2cdb53d5b6051ab6", "72": "e42fbd3dc744e730", "73": "7fe2cac980de160c", "74": "2b1343a6a9db1487", "75": "54a1bb232f1d4ceb", "76": "442ba11d31ec0e0a", "77": "852a25b8b95bf8d1", "78": "1810ab370b9cd608", "79": "0fc5dca02a3f02f6", "80": "6ff8a97e63c9a2f3", "81": "a38f84ae3d895236", "82": "08e48bd11f9714df", "83": "5095122914e83cf5", "84": "1aef305bd7d7d63f", "85": "f8bfd0cfe9e8b478", "86": "410d15a346bd5894", "87": "6b41d288cfd834ab", "88": "5aa6db96312a8811", "89": "80225792bb62ba04", "90": "fd291228c3311f40", "91": "d4579c5b7aa2742a", "92": "7b9ba7c3bff11361", "93": "71cd9c1fa4a857f0", "94": "34cd980be3c32d21", "95": "970093453f3b7d90", "96": "9e96780a2b7c4bd6", "97": "b7c10b0e09caac0b", "98": "089ea6a55861c693", "99": "cb6165a7dc822d29", "100": "8c97d8c400895e15", "101": "bd22248d0516e5d4", "102": "6aa00d5a83295f11", "103": "f58668f5b10ccdeb", "104": "4ec787414cc6f50b", "105": "1cf3077fd45d874a", "106": "edcd5d9bb3c4b00f", "107": "37f2f47110fe3eaa", "108": "b7ad5abb1da8cf8d", "109": "cb48a9c4f54efa38", "110": "f6dd36fd7f3edbe5", "111": "2925b620f0b1fd17", "112": "d8b3099917c3b711", "113": "3bb61caa0302c804", "114": "0d4f1d08dd056bb9", "115": "4ac2dcddeec2ff11", "116": "07da9aae9668f573", "117": "196f63e0c4536d30", "118": "ade84262e3cfac12", "119": "ebe4e5e0c42c613f", "120": "27256931b19a2867", "121": "5396e68ca6c185ad", "122": "aa8a1de55696b666", "123": "96618c9a362af46c", "124": "83f104cbb62fd03e", "125": "6db738fb27190349", "126": "6a087a22cbcef972", "127": "85fd71a0cad8d3a5", "128": "22dd4feed96c4229", "129": "c4d2f60f532e6f16", "130": "f6b0aa8a1568926b", "131": "142d0db70bad18fe", "132": "67ea4284cbc02c54", "133": "d899cfc86c7a4a27", "134": "ba9464410a9b4168", "135": "0d496a12149eca27", "136": "521f5c7b9d566b4d", "137": "9e37828bdd2ba8c5", "138": "ec03c97194c56f91", "139": "f4e6d5dfa30034c5", "140": "d9b47fa423cf0748", "141": "1e0330b8757f333e", "142": "f35d75e1194c008d", "143": "4d2ae7190b514a34", "144": "4a98716cabf43f86", "145": "56b2431193739c38", "146": "edc785fd71bb0675", "147": "4c7347f8f86e1fbd", "148": "8ca77cc4fd6fd437", "149": "8968e9e7d55afcbe", "150": "f4f4ce1a1180ddb1", "151": "e426746f6e9ee15f", "152": "b2337918dbdaf257", "153": "a3593e6f45bafb20", "154": "56747bad6345d66b", "155": "a8e7498fa7e257df", "156": "56e7b2355898077f", "157": "f2fc88f7d8214711", "158": "c966f6f8570c8c29", "159": "5f6094aa385f3bfe", "160": "2834e7d59672e756", "161": "cc6e436d94fd0033", "162": "64f33a2fc8969cd2", "163": "26ac1c0a00eabce1", "164": "cdcea44a6805ae55", "165": "a6e35f4937a5000c", "166": "85c97dab928b9b1b", "167": "7ab5695391e32126"}
|
||||
@@ -45,7 +45,7 @@
|
||||
"43": "2. Basic CLI Usage Examples",
|
||||
"44": "2. Standard Streams & Exit Codes",
|
||||
"45": "ClassificationResult",
|
||||
"46": "InherenceClassifier",
|
||||
"46": "test_adversarial.py",
|
||||
"47": "classifier.py",
|
||||
"48": "test_convert_article_to_markdown.py",
|
||||
"49": "content_northvolt_de.md",
|
||||
@@ -151,7 +151,7 @@
|
||||
"149": "get_hl_gl_ceid",
|
||||
"150": "13. Estratégia de testes",
|
||||
"151": "6. Contrato de entrada",
|
||||
"152": "assemble_markdown_document",
|
||||
"152": "InherenceClassifier",
|
||||
"153": "convert_html_to_markdown",
|
||||
"154": "JSON Schema Contract: Deterministic Article Content Selection",
|
||||
"155": "5. Escopo",
|
||||
@@ -163,5 +163,8 @@
|
||||
"161": "test_normalize_list_deduplication_preserves_case_and_order",
|
||||
"162": "test_normalize_date_iso_8601_variants",
|
||||
"163": "test_metadata_priority_original_url_all_fallbacks",
|
||||
"164": "test_normalize_scalar_non_string_types"
|
||||
"164": "test_normalize_scalar_non_string_types",
|
||||
"165": "LLMFallbackAdapter",
|
||||
"166": "remove_duplicate_initial_h1",
|
||||
"167": "test_normalize_scalar_whitespace_collapsing"
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# Graph Report - TextNLPClassifierApp (2026-08-21)
|
||||
|
||||
## Corpus Check
|
||||
- 200 files · ~108,772 words
|
||||
- 201 files · ~110,162 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 1527 nodes · 1899 edges · 165 communities (118 shown, 47 thin omitted)
|
||||
- Extraction: 97% EXTRACTED · 3% INFERRED · 0% AMBIGUOUS · INFERRED: 51 edges (avg confidence: 0.95)
|
||||
- 1554 nodes · 1970 edges · 168 communities (120 shown, 48 thin omitted)
|
||||
- Extraction: 97% EXTRACTED · 3% INFERRED · 0% AMBIGUOUS · INFERRED: 59 edges (avg confidence: 0.95)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `926a6b8c`
|
||||
- Built from commit: `cb33dafa`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
- 2. Basic CLI Usage Examples
|
||||
- 2. Standard Streams & Exit Codes
|
||||
- ClassificationResult
|
||||
- InherenceClassifier
|
||||
- test_adversarial.py
|
||||
- classifier.py
|
||||
- test_convert_article_to_markdown.py
|
||||
- content_northvolt_de.md
|
||||
@@ -160,7 +160,7 @@
|
||||
- get_hl_gl_ceid
|
||||
- 13. Estratégia de testes
|
||||
- 6. Contrato de entrada
|
||||
- assemble_markdown_document
|
||||
- InherenceClassifier
|
||||
- convert_html_to_markdown
|
||||
- JSON Schema Contract: Deterministic Article Content Selection
|
||||
- 5. Escopo
|
||||
@@ -173,35 +173,38 @@
|
||||
- test_normalize_date_iso_8601_variants
|
||||
- test_metadata_priority_original_url_all_fallbacks
|
||||
- test_normalize_scalar_non_string_types
|
||||
- LLMFallbackAdapter
|
||||
- remove_duplicate_initial_h1
|
||||
- test_normalize_scalar_whitespace_collapsing
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
1. `ECPSnapshot` - 31 edges
|
||||
2. `InherenceClassifier` - 25 edges
|
||||
3. `select_article_extractor()` - 23 edges
|
||||
4. `ExtractorName` - 21 edges
|
||||
5. `DecisionCategory` - 17 edges
|
||||
6. `ClassificationResult` - 17 edges
|
||||
7. `PRD — Conversão de artigo JSON para Markdown` - 16 edges
|
||||
8. `process_batch()` - 15 edges
|
||||
9. `8. Regras funcionais` - 15 edges
|
||||
10. `resolve_article_metadata()` - 14 edges
|
||||
1. `ECPSnapshot` - 40 edges
|
||||
2. `InherenceClassifier` - 29 edges
|
||||
3. `DecisionCategory` - 28 edges
|
||||
4. `LLMFallbackAdapter` - 26 edges
|
||||
5. `ClassificationResult` - 24 edges
|
||||
6. `select_article_extractor()` - 23 edges
|
||||
7. `ExtractorName` - 21 edges
|
||||
8. `PRD — Conversão de artigo JSON para Markdown` - 16 edges
|
||||
9. `process_batch()` - 15 edges
|
||||
10. `8. Regras funcionais` - 15 edges
|
||||
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `main()` --uses--> `ECPSnapshot` [INFERRED]
|
||||
classify.py → src/models.py
|
||||
- `test_e2e_extract_google_news_live_pipeline()` --uses--> `ExtractionResult` [INFERRED]
|
||||
tests/test_extract_google_news.py → scripts/extract_google_news.py
|
||||
- `test_llm_adapter_interface()` --calls--> `LLMFallbackAdapter` [EXTRACTED]
|
||||
tests/test_adapters.py → src/adapters/llm.py
|
||||
- `classifier()` --uses--> `InherenceClassifier` [INFERRED]
|
||||
tests/test_benchmark_24.py → src/classifier.py
|
||||
- `test_classification_result_serialization()` --uses--> `DecisionCategory` [INFERRED]
|
||||
tests/test_models.py → src/models.py
|
||||
- `petrobras_ecp()` --uses--> `ECPSnapshot` [INFERRED]
|
||||
tests/test_classifier.py → src/models.py
|
||||
- `test_adversarial_apple_fruit_recipe()` --uses--> `DecisionCategory` [INFERRED]
|
||||
tests/test_adversarial.py → src/models.py
|
||||
|
||||
## Import Cycles
|
||||
- None detected.
|
||||
|
||||
## Communities (165 total, 47 thin omitted)
|
||||
## Communities (168 total, 48 thin omitted)
|
||||
|
||||
### Community 0 - "Task Planning"
|
||||
Cohesion: 0.07
|
||||
@@ -344,20 +347,20 @@ Cohesion: 0.29
|
||||
Nodes (6): 1.1 Arguments & Options, 1. Command Line Interface, 2.1 Exit Codes, 2.2 Standard Output (`stdout`) / Standard Error (`stderr`), 2. Standard Streams & Exit Codes, CLI Contract & Interface Specification (POC)
|
||||
|
||||
### Community 45 - "ClassificationResult"
|
||||
Cohesion: 0.09
|
||||
Nodes (19): ABC, BaseNLPAdapter, Base abstract adapter interface for optional Tier 2 / Tier 3 NLP enhancers., Abstract interface for pluggable NLP classification adapters., Return True if the underlying provider or model is installed and configured., Compute semantic similarity score between text and a set of candidate terms., Optionally refine an ambiguous classification result., LocalEmbeddingsAdapter (+11 more)
|
||||
Cohesion: 0.11
|
||||
Nodes (17): ABC, BaseNLPAdapter, Base abstract adapter interface for optional Tier 2 / Tier 3 NLP enhancers., Abstract interface for pluggable NLP classification adapters., Return True if the underlying provider or model is installed and configured., Compute semantic similarity score between text and a set of candidate terms., Optionally refine an ambiguous classification result., LocalEmbeddingsAdapter (+9 more)
|
||||
|
||||
### Community 46 - "InherenceClassifier"
|
||||
Cohesion: 0.12
|
||||
Nodes (27): InherenceClassifier, Tier 1 Deterministic NLP Entity Inherence Classifier., DecisionCategory, RelatedEntity, Adversarial and robustness test suite for Multilingual NLP Entity Inherence…, Run CLI via subprocess without --output and verify stdout is pure parseable…, Run CLI via subprocess with empty content and verify error code and exit code., Content about city/state governance of São Paulo against ECP for São Paulo FC. (+19 more)
|
||||
### Community 46 - "test_adversarial.py"
|
||||
Cohesion: 0.10
|
||||
Nodes (19): Any, RelatedEntity, Adversarial and robustness test suite for Multilingual NLP Entity Inherence…, Run CLI via subprocess without --output and verify stdout is pure parseable…, Run CLI via subprocess with empty content and verify error code and exit code., Content about city/state governance of São Paulo against ECP for São Paulo FC., Run CLI via subprocess with missing target_name and verify error payload., Run CLI via subprocess with corrupted JSON and verify error payload. (+11 more)
|
||||
|
||||
### Community 47 - "classifier.py"
|
||||
Cohesion: 0.16
|
||||
Nodes (16): count_phrase_occurrences(), match_phrase_in_text(), Core deterministic classification engine (Tier 1 core)., Check if a normalized phrase appears in normalized text with word boundary…, Count occurrences of a phrase in text., Classify inherence of content against an ECP snapshot., extract_evidence_snippets(), extract_sentences() (+8 more)
|
||||
Nodes (15): count_phrase_occurrences(), match_phrase_in_text(), Core deterministic classification engine (Tier 1 core)., Check if a normalized phrase appears in normalized text with word boundary…, Count occurrences of a phrase in text., Classify inherence of content against an ECP snapshot., extract_evidence_snippets(), extract_sentences() (+7 more)
|
||||
|
||||
### Community 48 - "test_convert_article_to_markdown.py"
|
||||
Cohesion: 0.07
|
||||
Nodes (27): Suíte de Testes Automatizados para Conversão de Artigo JSON para Markdown.…, Testa comportamento com listas vazias, nulas ou contendo apenas placeholders., Valida parsing de datas no formato RFC 2822 (usado em feeds RSS e cabeçalhos…, Valida a cadeia de fallback completa para o campo TÍTULO (6 níveis)., Garante que subtítulo idêntico ao título seja automaticamente omitido (None)., Valida decodificação de entidades HTML nomeadas e numéricas., Garante que listas de autores/tags usem apenas a primeira fonte válida, sem…, Garante correspondência exata byte a byte para Trafilatura, Newspaper4k e… (+19 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (25): Suíte de Testes Automatizados para Conversão de Artigo JSON para Markdown.…, Testa divisão por ponto e vírgula na string e vírgulas em elementos de lista…, Valida parsing de datas no formato RFC 2822 (usado em feeds RSS e cabeçalhos…, Valida a cadeia de fallback completa para o campo TÍTULO (6 níveis)., Garante que subtítulo idêntico ao título seja automaticamente omitido (None)., Valida decodificação de entidades HTML nomeadas e numéricas., Garante correspondência exata byte a byte para Trafilatura, Newspaper4k e…, Garante que múltiplas execuções no mesmo arquivo produzam hashes SHA-256… (+17 more)
|
||||
|
||||
### Community 80 - "test_extract_article_contents.py"
|
||||
Cohesion: 0.06
|
||||
@@ -436,8 +439,8 @@ Cohesion: 0.15
|
||||
Nodes (17): emit_error(), main(), parse_args(), Namespace, ClassificationError, ErrorCode, MatchedGraphEntity, Enum (+9 more)
|
||||
|
||||
### Community 101 - "ECPSnapshot"
|
||||
Cohesion: 0.20
|
||||
Nodes (10): ECPSnapshot, Any, classifier(), fixture, parametrize, Controlled 24-case benchmark suite for Multilingual NLP Entity Inherence…, test_benchmark_case(), test_ecp_snapshot_defaults() (+2 more)
|
||||
Cohesion: 0.24
|
||||
Nodes (10): ECPSnapshot, classifier(), fixture, parametrize, Controlled 24-case benchmark suite for Multilingual NLP Entity Inherence…, test_benchmark_case(), Unit tests for ECP models, schema validation, and structured error handling., test_ecp_snapshot_defaults() (+2 more)
|
||||
|
||||
### Community 102 - "Feature Specification: Multilingual NLP Entity Inherence Classifier (POC)"
|
||||
Cohesion: 0.14
|
||||
@@ -585,7 +588,7 @@ Nodes (11): 1. Validação de Entrada, Tipagem & Isolamento de Lotes, 2. Isolame
|
||||
|
||||
### Community 140 - "convert_article"
|
||||
Cohesion: 0.15
|
||||
Nodes (13): clean_body_images(), convert_article(), Path, Remove o primeiro título H1 do corpo somente quando ele for igual ao título…, Preserva imagens com URL absoluta http/https, remove relativas/data:/vazias e…, Executa a leitura do JSON, validação, conversão e escrita atômica do arquivo…, remove_duplicate_initial_h1(), Testa remoção de H1 inicial coincidente com título com variações de espaços e… (+5 more)
|
||||
Nodes (13): assemble_markdown_document(), clean_body_images(), convert_article(), Path, Preserva imagens com URL absoluta http/https, remove relativas/data:/vazias e…, Monta a estrutura final do documento Markdown respeitando a ordem estrita do…, Executa a leitura do JSON, validação, conversão e escrita atômica do arquivo…, Valida descarte de data:, relativos e deduplicação mantendo a primeira… (+5 more)
|
||||
|
||||
### Community 141 - "005-convert-json-markdown/plan.md"
|
||||
Cohesion: 0.33
|
||||
@@ -631,9 +634,9 @@ Nodes (4): 13.1 Testes unitários, 13.2 Testes de integração do CLI, 13.3 Caso
|
||||
Cohesion: 0.50
|
||||
Nodes (4): 6.1 Formato, 6.2 Valores aceitos para `selected_extractor`, 6.3 Campos obrigatórios após a resolução, 6. Contrato de entrada
|
||||
|
||||
### Community 152 - "assemble_markdown_document"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): assemble_markdown_document(), Monta a estrutura final do documento Markdown respeitando a ordem estrita do…, Testa montagem com todos os campos e apenas com campos obrigatórios., test_assemble_markdown_document_full_and_minimal()
|
||||
### Community 152 - "InherenceClassifier"
|
||||
Cohesion: 0.14
|
||||
Nodes (24): InherenceClassifier, Tier 1 Deterministic NLP Entity Inherence Classifier with optional Tier 2 /…, DecisionCategory, Unit tests for deterministic classification decision logic., test_contextual_inherent(), test_direct_inherent(), test_negative_anchor_suppression(), test_not_related() (+16 more)
|
||||
|
||||
### Community 153 - "convert_html_to_markdown"
|
||||
Cohesion: 0.33
|
||||
@@ -647,25 +650,33 @@ Nodes (3): 1. Input JSON Schema, 2. Output JSON Schema, JSON Schema Contract: De
|
||||
Cohesion: 0.67
|
||||
Nodes (3): 5.1 Incluído, 5.2 Fora do escopo, 5. Escopo
|
||||
|
||||
### Community 165 - "LLMFallbackAdapter"
|
||||
Cohesion: 0.13
|
||||
Nodes (11): LLMFallbackAdapter, Optional adapter for LLM fallback boundary disambiguation., Returns True if an API key or custom provider function is configured., Constructs a structured disambiguation prompt for the LLM., Executes LLM fallback for ambiguous boundary cases. Returns a refined…, Parses and validates structured JSON response from LLM., Any, Valida detecção de disponibilidade por chave de API ou provider customizado. (+3 more)
|
||||
|
||||
### Community 166 - "remove_duplicate_initial_h1"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Remove o primeiro título H1 do corpo somente quando ele for igual ao título…, remove_duplicate_initial_h1(), Testa remoção de H1 inicial coincidente com título com variações de espaços e…, test_remove_duplicate_initial_h1_exact_and_variations()
|
||||
|
||||
## Knowledge Gaps
|
||||
- **696 isolated node(s):** `text-nlp-classifier`, `MatchedGraphEntity`, `graphify`, `Usage`, `What graphify is for` (+691 more)
|
||||
These have ≤1 connection - possible missing edges or undocumented components.
|
||||
- **47 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||
- **48 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||
|
||||
## Suggested Questions
|
||||
_Questions this graph is uniquely positioned to answer:_
|
||||
|
||||
- **Why does `PRD — Conversão de artigo JSON para Markdown` connect `PRD — Conversão de artigo JSON para Markdown` to `8. Regras funcionais`, `12. Critérios de aceite`, `11. Requisitos não funcionais`, `9. Interface CLI`, `13. Estratégia de testes`, `6. Contrato de entrada`, `5. Escopo`?**
|
||||
_High betweenness centrality (0.007) - this node is a cross-community bridge._
|
||||
_High betweenness centrality (0.008) - this node is a cross-community bridge._
|
||||
- **Why does `Implementation Plan: Convert Article JSON to Markdown` connect `Implementation Plan: Convert Article JSON to Markdown` to `005-convert-json-markdown/plan.md`?**
|
||||
_High betweenness centrality (0.004) - this node is a cross-community bridge._
|
||||
- **Why does `Tasks: Convert Article JSON to Markdown` connect `Tasks: Convert Article JSON to Markdown` to `005-convert-json-markdown/plan.md`?**
|
||||
_High betweenness centrality (0.004) - this node is a cross-community bridge._
|
||||
- **Are the 10 inferred relationships involving `ECPSnapshot` (e.g. with `main()` and `BaseNLPAdapter`) actually correct?**
|
||||
_`ECPSnapshot` has 10 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 6 inferred relationships involving `InherenceClassifier` (e.g. with `LocalEmbeddingsAdapter` and `LLMFallbackAdapter`) actually correct?**
|
||||
_`InherenceClassifier` has 6 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 12 inferred relationships involving `ExtractorName` (e.g. with `test_article_1_regression_technical_tie_markdown_images()` and `test_ct_001_three_candidates_clear_winner()`) actually correct?**
|
||||
_`ExtractorName` has 12 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 10 inferred relationships involving `DecisionCategory` (e.g. with `InherenceClassifier` and `test_adversarial_apple_fruit_recipe()`) actually correct?**
|
||||
_`DecisionCategory` has 10 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **What connects `text-nlp-classifier`, `MatchedGraphEntity`, `graphify` to the rest of the system?**
|
||||
_696 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
- **Should `Task Planning` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.07407407407407407 - nodes in this community are weakly interconnected._
|
||||
- **Are the 18 inferred relationships involving `DecisionCategory` (e.g. with `LLMFallbackAdapter` and `InherenceClassifier`) actually correct?**
|
||||
_`DecisionCategory` has 18 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 4 inferred relationships involving `LLMFallbackAdapter` (e.g. with `ClassificationResult` and `DecisionCategory`) actually correct?**
|
||||
_`LLMFallbackAdapter` has 4 INFERRED edges - model-reasoned connections that need verification._
|
||||
+1826
-699
File diff suppressed because it is too large
Load Diff
@@ -294,9 +294,9 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"classify.py": {
|
||||
"mtime": 1787264412.2457643,
|
||||
"seen": 1787264519.0539427,
|
||||
"ast_hash": "e89fc4b64bd7606fc466d5338108705b",
|
||||
"mtime": 1787320064.0177462,
|
||||
"seen": 1787320239.022448,
|
||||
"ast_hash": "3679326c88a59f796f587e0c61c31417",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"pyproject.toml": {
|
||||
@@ -330,15 +330,15 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/adapters/llm.py": {
|
||||
"mtime": 1787264412.2437606,
|
||||
"seen": 1787264519.0542035,
|
||||
"ast_hash": "ba2990328f5b25ac6cdfc3b57acc9d39",
|
||||
"mtime": 1787320047.0352886,
|
||||
"seen": 1787320239.0258572,
|
||||
"ast_hash": "ffcf26cb4e89395aa8771ddb4f5de785",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/classifier.py": {
|
||||
"mtime": 1787264459.052089,
|
||||
"seen": 1787264519.0542045,
|
||||
"ast_hash": "b8fb440374ecd66bb8bf67c70c19ed1f",
|
||||
"mtime": 1787320047.0362887,
|
||||
"seen": 1787320239.025866,
|
||||
"ast_hash": "d6cc674d407a99ab52f6d5156f9b3d8e",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/language.py": {
|
||||
@@ -654,9 +654,9 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"README.md": {
|
||||
"mtime": 1787319775.4204426,
|
||||
"seen": 1787319817.9012172,
|
||||
"ast_hash": "f809a191cb40e8a0367c748b9c8d3e84",
|
||||
"mtime": 1787320219.5852203,
|
||||
"seen": 1787320239.0933797,
|
||||
"ast_hash": "ce59670fbaebc5e408a30a1009a58d12",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"scripts/extract_article_contents.py": {
|
||||
@@ -816,15 +816,15 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"scripts/convert_article_to_markdown.py": {
|
||||
"mtime": 1787318905.723034,
|
||||
"seen": 1787319817.895658,
|
||||
"ast_hash": "b58fbd8b426de464df2c269c32831583",
|
||||
"mtime": 1787320071.2809863,
|
||||
"seen": 1787320239.0233297,
|
||||
"ast_hash": "7939a71acd9b264f9d00eab5c652cd36",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"tests/test_convert_article_to_markdown.py": {
|
||||
"mtime": 1787318905.723034,
|
||||
"seen": 1787319817.8974621,
|
||||
"ast_hash": "95c041594afec14ed25bc237b7ff8b89",
|
||||
"mtime": 1787320111.811304,
|
||||
"seen": 1787320239.0292969,
|
||||
"ast_hash": "5223f35131b8e952e05c44710f3988b2",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"docs/prd_convert_json_markdown.md": {
|
||||
@@ -910,5 +910,11 @@
|
||||
"seen": 1787317712.8280091,
|
||||
"ast_hash": "c63c1c39e34e08a239aa8bea3c264756",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"tests/test_llm_fallback.py": {
|
||||
"mtime": 1787320089.2120655,
|
||||
"seen": 1787320239.0310187,
|
||||
"ast_hash": "74bc17c4668551e77214d6581baf206c",
|
||||
"semantic_hash": ""
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Graph Report - TextNLPClassifierApp (2026-08-21)
|
||||
|
||||
## Corpus Check
|
||||
- 201 files · ~110,162 words
|
||||
- 201 files · ~110,615 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
@@ -10,7 +10,7 @@
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `cb33dafa`
|
||||
- Built from commit: `31152d50`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
- Specification Quality Checklist: Convert Article JSON to Markdown
|
||||
- CLI Contract: `convert_article_to_markdown.py`
|
||||
- 9. Interface CLI
|
||||
- get_hl_gl_ceid
|
||||
- sample_rss_xml
|
||||
- 13. Estratégia de testes
|
||||
- 6. Contrato de entrada
|
||||
- InherenceClassifier
|
||||
@@ -173,7 +173,7 @@
|
||||
- test_normalize_date_iso_8601_variants
|
||||
- test_metadata_priority_original_url_all_fallbacks
|
||||
- test_normalize_scalar_non_string_types
|
||||
- LLMFallbackAdapter
|
||||
- .disambiguate
|
||||
- remove_duplicate_initial_h1
|
||||
- test_normalize_scalar_whitespace_collapsing
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `main()` --uses--> `ECPSnapshot` [INFERRED]
|
||||
classify.py → src/models.py
|
||||
- `test_e2e_extract_google_news_live_pipeline()` --uses--> `ExtractionResult` [INFERRED]
|
||||
- `test_extract_google_news_orchestration_mocked()` --uses--> `ExtractionResult` [INFERRED]
|
||||
tests/test_extract_google_news.py → scripts/extract_google_news.py
|
||||
- `test_llm_adapter_interface()` --calls--> `LLMFallbackAdapter` [EXTRACTED]
|
||||
tests/test_adapters.py → src/adapters/llm.py
|
||||
@@ -371,16 +371,16 @@ Cohesion: 0.08
|
||||
Nodes (24): 1. Visão geral (arquitetura), 2.1 DTO de entrada (`googlenews_etl/application/dtos/extract_news_dto.py`), 2.2 Value Object de validação (`googlenews_etl/domain/entities/search_query.py`), 2. Entrada, 3.1 O caso de uso (`googlenews_etl/application/use_cases/extract_news_use_case.py`), 3.2 A porta (`googlenews_etl/domain/ports/news_extractor_port.py`), 3.3.1 Inicialização: sessão HTTP com impersonação de browser, 3.3.2 Mapeamento idioma → parâmetros `hl`/`gl` (`_get_hl_gl`) (+16 more)
|
||||
|
||||
### Community 82 - "extract_google_news.py"
|
||||
Cohesion: 0.20
|
||||
Nodes (14): extract_google_news(), _fetch_rss_content(), NewsArticle, _normalize_text_for_comparison(), parse_google_news_rss(), Remove pontuação e espaços extras para comparação de redundância., Parseia o XML do RSS do Google News e extrai os itens estruturados., Resolve em paralelo as URLs intermediárias do Google News para os links finais… (+6 more)
|
||||
Cohesion: 0.15
|
||||
Nodes (18): extract_google_news(), _fetch_rss_content(), get_hl_gl_ceid(), NewsArticle, _normalize_text_for_comparison(), parse_google_news_rss(), Mapeia idioma e locale para os parâmetros hl, gl e ceid do Google News., Remove pontuação e espaços extras para comparação de redundância. (+10 more)
|
||||
|
||||
### Community 83 - "ExtractionResult"
|
||||
Cohesion: 0.29
|
||||
Nodes (5): ExtractionResult, Any, Resultado consolidado da extração., Valida a consolidação do ExtractionResult a partir da busca mockada com URLs…, test_extract_google_news_orchestration_mocked()
|
||||
Nodes (5): ExtractionResult, Any, Resultado consolidado da extração., Valida E2E o fluxo completo de busca, parsing e resolução de URLs reais ao vivo., test_e2e_extract_google_news_live_pipeline()
|
||||
|
||||
### Community 84 - "test_extract_google_news.py"
|
||||
Cohesion: 0.16
|
||||
Nodes (14): Resolve a URL intermediária do Google News para a URL real do veículo., resolve_article_url(), fixture, Testes unitários e de integração para o Extrator de Manchetes do Google News.…, Valida o parsing do feed RSS, higienização de tags HTML e deduplicação., Valida fallback gracioso de URL quando não é link do Google News ou em erro., Valida resolução bem-sucedida de URL do Google News para o portal destino., Valida E2E que o decodificador resolve uma URL real do Google News para o… (+6 more)
|
||||
Cohesion: 0.15
|
||||
Nodes (15): Resolve a URL intermediária do Google News para a URL real do veículo., resolve_article_url(), Testes unitários e de integração para o Extrator de Manchetes do Google News.…, Valida fallback gracioso de URL quando não é link do Google News ou em erro., Valida resolução bem-sucedida de URL do Google News para o portal destino., Valida E2E que o decodificador resolve uma URL real do Google News para o…, Valida o mapeamento padrão de idiomas para pares (hl, gl, ceid)., Valida a sobrescrita geográfica quando o argumento locale é especificado. (+7 more)
|
||||
|
||||
### Community 85 - "Implementation Tasks: Google News Headlines Extractor"
|
||||
Cohesion: 0.14
|
||||
@@ -400,7 +400,7 @@ Nodes (7): Architecture & Pipeline, Documentation (this feature), Implementation
|
||||
|
||||
### Community 90 - "SearchQuery"
|
||||
Cohesion: 0.20
|
||||
Nodes (6): Value Object com parâmetros de busca validados., SearchQuery, Valida E2E o fluxo completo de busca, parsing e resolução de URLs reais ao vivo., Valida as regras de negócio e limites de SearchQuery., test_e2e_extract_google_news_live_pipeline(), test_search_query_validation()
|
||||
Nodes (6): Value Object com parâmetros de busca validados., SearchQuery, Valida a consolidação do ExtractionResult a partir da busca mockada com URLs…, Valida as regras de negócio e limites de SearchQuery., test_extract_google_news_orchestration_mocked(), test_search_query_validation()
|
||||
|
||||
### Community 91 - "1. Technical Decisions & Tradeoffs"
|
||||
Cohesion: 0.25
|
||||
@@ -622,9 +622,9 @@ Nodes (5): 1. Script Signature, 2. Command-Line Arguments, 3. Exit Codes, 4. Sta
|
||||
Cohesion: 0.40
|
||||
Nodes (5): 9.1 Script, 9.2 Argumentos, 9.3 Exemplos, 9.4 Saída do processo, 9. Interface CLI
|
||||
|
||||
### Community 149 - "get_hl_gl_ceid"
|
||||
Cohesion: 0.25
|
||||
Nodes (8): get_hl_gl_ceid(), Mapeia idioma e locale para os parâmetros hl, gl e ceid do Google News., Valida o mapeamento padrão de idiomas para pares (hl, gl, ceid)., Valida a sobrescrita geográfica quando o argumento locale é especificado., Valida fallback dinâmico para idiomas regionais não listados explicitamente., test_get_hl_gl_ceid_default_mappings(), test_get_hl_gl_ceid_dynamic_fallback(), test_get_hl_gl_ceid_with_custom_locale()
|
||||
### Community 149 - "sample_rss_xml"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): fixture, Fixture que fornece o conteúdo do XML de exemplo para testes offline., sample_rss_xml()
|
||||
|
||||
### Community 150 - "13. Estratégia de testes"
|
||||
Cohesion: 0.50
|
||||
@@ -635,8 +635,8 @@ Cohesion: 0.50
|
||||
Nodes (4): 6.1 Formato, 6.2 Valores aceitos para `selected_extractor`, 6.3 Campos obrigatórios após a resolução, 6. Contrato de entrada
|
||||
|
||||
### Community 152 - "InherenceClassifier"
|
||||
Cohesion: 0.14
|
||||
Nodes (24): InherenceClassifier, Tier 1 Deterministic NLP Entity Inherence Classifier with optional Tier 2 /…, DecisionCategory, Unit tests for deterministic classification decision logic., test_contextual_inherent(), test_direct_inherent(), test_negative_anchor_suppression(), test_not_related() (+16 more)
|
||||
Cohesion: 0.11
|
||||
Nodes (31): LLMFallbackAdapter, Optional adapter for LLM fallback boundary disambiguation., InherenceClassifier, Any, Tier 1 Deterministic NLP Entity Inherence Classifier with optional Tier 2 /…, DecisionCategory, Unit tests for deterministic classification decision logic., test_contextual_inherent() (+23 more)
|
||||
|
||||
### Community 153 - "convert_html_to_markdown"
|
||||
Cohesion: 0.33
|
||||
@@ -650,9 +650,9 @@ Nodes (3): 1. Input JSON Schema, 2. Output JSON Schema, JSON Schema Contract: De
|
||||
Cohesion: 0.67
|
||||
Nodes (3): 5.1 Incluído, 5.2 Fora do escopo, 5. Escopo
|
||||
|
||||
### Community 165 - "LLMFallbackAdapter"
|
||||
Cohesion: 0.13
|
||||
Nodes (11): LLMFallbackAdapter, Optional adapter for LLM fallback boundary disambiguation., Returns True if an API key or custom provider function is configured., Constructs a structured disambiguation prompt for the LLM., Executes LLM fallback for ambiguous boundary cases. Returns a refined…, Parses and validates structured JSON response from LLM., Any, Valida detecção de disponibilidade por chave de API ou provider customizado. (+3 more)
|
||||
### Community 165 - ".disambiguate"
|
||||
Cohesion: 0.25
|
||||
Nodes (4): Executes LLM fallback for ambiguous boundary cases. Returns a refined…, Parses and validates structured JSON response from LLM., Returns True if an API key or custom provider function is configured., Constructs an expert-engineered prompt for multilingual entity inherence…
|
||||
|
||||
### Community 166 - "remove_duplicate_initial_h1"
|
||||
Cohesion: 0.50
|
||||
|
||||
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+371
-371
File diff suppressed because it is too large
Load Diff
@@ -330,9 +330,9 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/adapters/llm.py": {
|
||||
"mtime": 1787320047.0352886,
|
||||
"seen": 1787320239.0258572,
|
||||
"ast_hash": "ffcf26cb4e89395aa8771ddb4f5de785",
|
||||
"mtime": 1787320797.2485664,
|
||||
"seen": 1787320818.2953389,
|
||||
"ast_hash": "a5cd6f66048ee1d443c2c91ae9947a14",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/classifier.py": {
|
||||
@@ -912,9 +912,9 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"tests/test_llm_fallback.py": {
|
||||
"mtime": 1787320089.2120655,
|
||||
"seen": 1787320239.0310187,
|
||||
"ast_hash": "74bc17c4668551e77214d6581baf206c",
|
||||
"mtime": 1787320797.249565,
|
||||
"seen": 1787320818.2967606,
|
||||
"ast_hash": "e5d98de814ceeecd8bd601a7c206e92d",
|
||||
"semantic_hash": ""
|
||||
}
|
||||
}
|
||||
+81
-10
@@ -37,17 +37,88 @@ class LLMFallbackAdapter(BaseNLPAdapter):
|
||||
def build_prompt(
|
||||
self, ecp: ECPSnapshot, content_md: str, initial_result: ClassificationResult
|
||||
) -> str:
|
||||
"""Constructs a structured disambiguation prompt for the LLM."""
|
||||
return (
|
||||
f"You are an NLP Entity Inherence Evaluator.\n"
|
||||
f"Target Entity: {ecp.target_name} (Aliases: {', '.join(ecp.aliases)})\n"
|
||||
f"Domain: {ecp.domain}\n"
|
||||
f"Initial Tier-1 Decision: {initial_result.decision.value} (Confidence: {initial_result.confidence})\n\n"
|
||||
f"Document Content:\n```markdown\n{content_md[:2000]}\n```\n\n"
|
||||
f"Evaluate if the document is substantively inherent to the target entity.\n"
|
||||
f'Respond with JSON: {{"decision": "DIRECT_INHERENT"|"CONTEXTUAL_INHERENT"|"TANGENTIAL"|"NOT_RELATED", '
|
||||
f'"confidence": 0.0-1.0, "rationale": "explanation"}}'
|
||||
"""Constructs an expert-engineered prompt for multilingual entity inherence disambiguation."""
|
||||
matched_pos = (
|
||||
", ".join(initial_result.matched_anchors) if initial_result.matched_anchors else "None"
|
||||
)
|
||||
matched_neg = (
|
||||
", ".join(initial_result.negative_matches)
|
||||
if initial_result.negative_matches
|
||||
else "None"
|
||||
)
|
||||
matched_graph = (
|
||||
", ".join([f"{g['name']} ({g['relation_type']})" for g in initial_result.graph_matches])
|
||||
if initial_result.graph_matches
|
||||
else "None"
|
||||
)
|
||||
warnings_str = "; ".join(initial_result.warnings) if initial_result.warnings else "None"
|
||||
top_anchors = ", ".join(ecp.anchors[:20]) if ecp.anchors else "None"
|
||||
top_negatives = ", ".join(ecp.negative_anchors[:15]) if ecp.negative_anchors else "None"
|
||||
related_entities_summary = (
|
||||
", ".join(
|
||||
[
|
||||
f"{r.name} [{r.relation_type}, weight: {r.weight}]"
|
||||
for r in ecp.related_entities[:10]
|
||||
]
|
||||
)
|
||||
if ecp.related_entities
|
||||
else "None"
|
||||
)
|
||||
|
||||
return f"""You are a Principal Knowledge Graph & Multilingual NLP Entity Inherence Specialist.
|
||||
|
||||
### OBJECTIVE
|
||||
Your task is to resolve an AMBIGUOUS boundary classification case flagged by the deterministic Tier-1 NLP pipeline for the target entity: **{ecp.target_name}**.
|
||||
|
||||
### 1. TARGET ENTITY CONTEXT PROFILE (ECP)
|
||||
- **Target Entity ID**: `{ecp.target_entity_id}`
|
||||
- **Canonical Name**: {ecp.target_name}
|
||||
- **Domain / Industry**: {ecp.domain}
|
||||
- **Known Valid Aliases**: {", ".join(ecp.aliases)}
|
||||
- **Expected Thematic Anchors (Positive Signals)**: {top_anchors}
|
||||
- **Disambiguation Negative Anchors (Known Homonyms / Distractors)**: {top_negatives}
|
||||
- **Knowledge Graph Connected Entities**: {related_entities_summary}
|
||||
|
||||
### 2. TIER-1 NLP DIAGNOSIS (WHY IT WAS FLAGGED AS AMBIGUOUS)
|
||||
- **Initial Tier-1 Decision**: `{initial_result.decision.value}` (Confidence: {initial_result.confidence})
|
||||
- **Tier-1 Rationale**: {initial_result.rationale}
|
||||
- **Telemetry Warnings**: {warnings_str}
|
||||
- **Positive Term Matches**: {matched_pos}
|
||||
- **Negative / Distractor Matches**: {matched_neg}
|
||||
- **Graph Node Matches**: {matched_graph}
|
||||
|
||||
### 3. CONTRASTIVE TAXONOMY & DECISION DEFINITIONS
|
||||
1. **DIRECT_INHERENT** (`is_inherent = true`):
|
||||
- The document is primarily, directly, or substantively about `{ecp.target_name}`.
|
||||
- The narrative explores the entity's direct actions, performances, strategy, status, or key personnel.
|
||||
2. **CONTEXTUAL_INHERENT** (`is_inherent = true`):
|
||||
- The document is not exclusively about the target entity, but the entity is an active, material participant in the discussed ecosystem (e.g. key rival in an active match, crucial partner in a corporate deal, subsidiary with material parent impact, or direct regulatory subject).
|
||||
3. **TANGENTIAL** (`is_inherent = false`):
|
||||
- The target entity is mentioned only in passing, as a figure of speech / metaphor, in an incidental illustrative list, or as mere background trivia without playing an active role in the article's core narrative.
|
||||
4. **NOT_RELATED** (`is_inherent = false`):
|
||||
- The document is completely unrelated, or the mention refers to a homonym/distractor (matching negative anchors or an entirely different entity with a similar name).
|
||||
|
||||
### 4. DISAMBIGUATION EVALUATION PROTOCOL
|
||||
1. **Language & Intent**: Read the document in its native language (`{initial_result.detected_language}`). Determine the primary subject matter.
|
||||
2. **Homonym Filtering**: Verify whether mentions of `{ecp.target_name}` refer to the intended entity in domain `{ecp.domain}` or to an unrelated namesake.
|
||||
3. **Substantive Role vs. Passing Footnote**: Evaluate whether the mention is central (DIRECT), systemic/contextual (CONTEXTUAL), or merely incidental (TANGENTIAL).
|
||||
4. **Final Decision**: Provide your definitive calibrated resolution in strict JSON format.
|
||||
|
||||
### 5. DOCUMENT CONTENT (MARKDOWN)
|
||||
```markdown
|
||||
{content_md[:3500]}
|
||||
```
|
||||
|
||||
### 6. OUTPUT FORMAT
|
||||
Respond ONLY with a valid JSON object matching this schema:
|
||||
```json
|
||||
{{
|
||||
"analysis_summary": "Brief 1-sentence synthesis of the document's main focus and entity relation.",
|
||||
"decision": "DIRECT_INHERENT" | "CONTEXTUAL_INHERENT" | "TANGENTIAL" | "NOT_RELATED",
|
||||
"confidence": 0.80 to 0.99,
|
||||
"rationale": "Clear, concise justification explaining why this decision resolves the Tier-1 NLP ambiguity."
|
||||
}}
|
||||
```"""
|
||||
|
||||
def disambiguate(
|
||||
self,
|
||||
|
||||
@@ -69,7 +69,7 @@ def test_llm_adapter_build_prompt_structure():
|
||||
)
|
||||
|
||||
prompt = adapter.build_prompt(ecp, "# Título do Artigo\n\nConteúdo sobre o jogo.", initial_res)
|
||||
assert "Target Entity: River Plate" in prompt
|
||||
assert "River Plate" in prompt
|
||||
assert "Futebol" in prompt
|
||||
assert "TANGENTIAL" in prompt
|
||||
assert "Título do Artigo" in prompt
|
||||
@@ -148,9 +148,11 @@ def test_llm_adapter_parsing_json_wrapped_in_markdown_codeblock():
|
||||
|
||||
def test_llm_adapter_handling_invalid_and_corrupt_responses():
|
||||
"""Valida que respostas corrompidas ou JSONs sem campos obrigatórios retornem None com segurança."""
|
||||
|
||||
def make_bad_provider(resp_str: str):
|
||||
def _prov(prompt: str) -> str:
|
||||
return resp_str
|
||||
|
||||
return _prov
|
||||
|
||||
for bad_response in [
|
||||
|
||||
Reference in New Issue
Block a user