Files
Munich-news/tests/crawler/test_clustering_real.py
2025-11-12 11:34:33 +01:00

167 lines
6.1 KiB
Python

#!/usr/bin/env python3
"""
Test AI clustering with realistic fake articles
"""
from pymongo import MongoClient
from datetime import datetime
import sys
# Connect to MongoDB
client = MongoClient("mongodb://admin:changeme@mongodb:27017/")
db = client["munich_news"]
# Create test articles about the same Munich story from different sources
test_articles = [
{
"title": "München: Stadtrat beschließt neue Regelungen für Wohnungsbau",
"content": """Der Münchner Stadtrat hat am Dienstag neue Regelungen für den Wohnungsbau beschlossen.
Die Maßnahmen sollen den Bau von bezahlbarem Wohnraum in der bayerischen Landeshauptstadt fördern.
Oberbürgermeister Dieter Reiter (SPD) sprach von einem wichtigen Schritt zur Lösung der Wohnungskrise.
Die neuen Regelungen sehen vor, dass bei Neubauprojekten mindestens 40 Prozent der Wohnungen
als Sozialwohnungen gebaut werden müssen. Zudem werden Bauvorschriften vereinfacht.""",
"source": "abendzeitung-muenchen",
"link": "https://example.com/az-wohnungsbau-1",
"published_at": datetime.utcnow(),
"category": "local",
"word_count": 85
},
{
"title": "Stadtrat München stimmt für neue Wohnungsbau-Verordnung",
"content": """In einer Sitzung am Dienstag stimmte der Münchner Stadtrat für neue Wohnungsbau-Verordnungen.
Die Beschlüsse zielen darauf ab, mehr bezahlbaren Wohnraum in München zu schaffen.
OB Reiter bezeichnete die Entscheidung als Meilenstein im Kampf gegen die Wohnungsnot.
Künftig müssen 40 Prozent aller Neubauwohnungen als Sozialwohnungen errichtet werden.
Außerdem werden bürokratische Hürden beim Bauen abgebaut.""",
"source": "sueddeutsche",
"link": "https://example.com/sz-wohnungsbau-1",
"published_at": datetime.utcnow(),
"category": "local",
"word_count": 72
},
{
"title": "FC Bayern München verpflichtet neuen Stürmer aus Brasilien",
"content": """Der FC Bayern München hat einen neuen Stürmer verpflichtet. Der 23-jährige Brasilianer
wechselt für eine Ablösesumme von 50 Millionen Euro nach München. Sportdirektor Christoph Freund
zeigte sich begeistert von der Verpflichtung. Der Spieler soll die Offensive verstärken.""",
"source": "abendzeitung-muenchen",
"link": "https://example.com/az-bayern-1",
"published_at": datetime.utcnow(),
"category": "sports",
"word_count": 52
},
{
"title": "Bayern München holt brasilianischen Angreifer",
"content": """Der deutsche Rekordmeister Bayern München hat einen brasilianischen Stürmer unter Vertrag genommen.
Für 50 Millionen Euro wechselt der 23-Jährige an die Isar. Sportdirektor Freund lobte den Transfer.
Der Neuzugang soll die Münchner Offensive beleben und für mehr Torgefahr sorgen.""",
"source": "sueddeutsche",
"link": "https://example.com/sz-bayern-1",
"published_at": datetime.utcnow(),
"category": "sports",
"word_count": 48
}
]
print("Testing AI Clustering with Realistic Articles")
print("=" * 70)
print()
# Clear previous test articles
print("Cleaning up previous test articles...")
db.articles.delete_many({"link": {"$regex": "^https://example.com/"}})
print("✓ Cleaned up")
print()
# Import clustering
sys.path.insert(0, '/app')
from ollama_client import OllamaClient
from article_clustering import ArticleClusterer
from config import Config
# Initialize
ollama_client = OllamaClient(
base_url=Config.OLLAMA_BASE_URL,
model=Config.OLLAMA_MODEL,
enabled=Config.OLLAMA_ENABLED,
timeout=30
)
clusterer = ArticleClusterer(
ollama_client=ollama_client,
similarity_threshold=0.50,
time_window_hours=24
)
print("Processing articles with AI clustering...")
print()
clustered_articles = []
for i, article in enumerate(test_articles, 1):
print(f"{i}. Processing: {article['title'][:60]}...")
print(f" Source: {article['source']}")
# Cluster with previously processed articles
clustered = clusterer.cluster_article(article, clustered_articles)
clustered_articles.append(clustered)
print(f" → Cluster ID: {clustered['cluster_id']}")
print(f" → Is Primary: {clustered['is_primary']}")
# Insert into database
db.articles.insert_one(clustered)
print(f" ✓ Saved to database")
print()
print("=" * 70)
print("Clustering Results:")
print()
# Analyze results
clusters = {}
for article in clustered_articles:
cluster_id = article['cluster_id']
if cluster_id not in clusters:
clusters[cluster_id] = []
clusters[cluster_id].append(article)
for cluster_id, articles in clusters.items():
print(f"Cluster {cluster_id}: {len(articles)} article(s)")
for article in articles:
print(f" - [{article['source']}] {article['title'][:60]}...")
print()
# Expected results
print("=" * 70)
print("Expected Results:")
print(" ✓ Articles 1&2 should be in same cluster (housing story)")
print(" ✓ Articles 3&4 should be in same cluster (Bayern transfer)")
print(" ✓ Total: 2 clusters with 2 articles each")
print()
# Actual results
housing_cluster = [a for a in clustered_articles if 'Wohnungsbau' in a['title'] or 'Wohnungsbau' in a['title']]
bayern_cluster = [a for a in clustered_articles if 'Bayern' in a['title'] or 'Stürmer' in a['title']]
housing_cluster_ids = set(a['cluster_id'] for a in housing_cluster)
bayern_cluster_ids = set(a['cluster_id'] for a in bayern_cluster)
print("Actual Results:")
if len(housing_cluster_ids) == 1:
print(" ✓ Housing articles clustered together")
else:
print(f" ✗ Housing articles in {len(housing_cluster_ids)} different clusters")
if len(bayern_cluster_ids) == 1:
print(" ✓ Bayern articles clustered together")
else:
print(f" ✗ Bayern articles in {len(bayern_cluster_ids)} different clusters")
if len(clusters) == 2:
print(" ✓ Total clusters: 2 (correct)")
else:
print(f" ✗ Total clusters: {len(clusters)} (expected 2)")
print()
print("=" * 70)
print("✓ Test complete! Check the results above.")