167 lines
6.1 KiB
Python
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.")
|