You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
5.6 KiB
PowerShell

<#
.SYNOPSIS
Semantische Suche in TED Ausschreibungen
.DESCRIPTION
Fuehrt eine semantische Aehnlichkeitssuche gegen die TED Procurement Datenbank durch.
.PARAMETER Query
Der Suchtext fuer die semantische Suche
.PARAMETER TopK
Anzahl der zurueckgegebenen Ergebnisse (Standard: 10, Max: 100)
.PARAMETER Threshold
Minimaler Aehnlichkeitsschwellwert 0.0-1.0 (Standard: 0.5)
.PARAMETER ApiUrl
URL des API-Servers (Standard: http://localhost:8888/api)
.EXAMPLE
.\Search-TED.ps1 -Query "Software Entwicklung Cloud Services"
.EXAMPLE
.\Search-TED.ps1 -Query "IT Beratung Digitalisierung" -TopK 20 -Threshold 0.6
#>
param(
[Parameter(Mandatory=$true, Position=0, HelpMessage="Suchtext fuer semantische Suche")]
[string]$Query,
[Parameter(Mandatory=$false)]
[ValidateRange(1, 100)]
[int]$TopK = 100,
[Parameter(Mandatory=$false)]
[ValidateRange(0.0, 1.0)]
[double]$Threshold = 0.5,
[Parameter(Mandatory=$false)]
[string]$ApiUrl = "http://localhost:8888/api"
)
# Farben fuer Ausgabe
$colors = @{
Header = "Cyan"
Success = "Green"
Warning = "Yellow"
Error = "Red"
Info = "White"
Highlight = "Magenta"
}
function Write-Header {
param([string]$Text)
Write-Host ""
Write-Host ("=" * 80) -ForegroundColor $colors.Header
Write-Host $Text -ForegroundColor $colors.Header
Write-Host ("=" * 80) -ForegroundColor $colors.Header
}
function Write-Result {
param(
[int]$Rank,
[PSObject]$Doc
)
$similarity = if ($Doc.similarityPercent) { "$($Doc.similarityPercent)%" } else { "N/A" }
$deadline = "-"
if ($Doc.submissionDeadline) {
try {
# Handle ISO 8601 format (e.g., "2025-04-28T06:00:59Z")
$deadline = ([DateTime]::Parse($Doc.submissionDeadline, [System.Globalization.CultureInfo]::InvariantCulture)).ToString("dd.MM.yyyy")
} catch {
$deadline = $Doc.submissionDeadline.Substring(0, 10) # Fallback: first 10 chars (YYYY-MM-DD)
}
}
Write-Host ""
Write-Host "[$Rank] " -NoNewline -ForegroundColor $colors.Highlight
Write-Host "$similarity Aehnlichkeit" -ForegroundColor $colors.Success
Write-Host " Titel: " -NoNewline -ForegroundColor $colors.Info
Write-Host $Doc.projectTitle -ForegroundColor $colors.Warning
Write-Host " Auftraggeber: " -NoNewline -ForegroundColor $colors.Info
Write-Host "$($Doc.buyerName) ($($Doc.buyerCountryCode))" -ForegroundColor White
Write-Host " Vertragsart: " -NoNewline -ForegroundColor $colors.Info
Write-Host $Doc.contractNature -ForegroundColor White
Write-Host " Einreichfrist:" -NoNewline -ForegroundColor $colors.Info
Write-Host " $deadline" -ForegroundColor White
Write-Host " TED Link: " -NoNewline -ForegroundColor $colors.Info
Write-Host $Doc.noticeUrl -ForegroundColor Cyan
if ($Doc.projectDescription) {
$desc = $Doc.projectDescription
if ($desc.Length -gt 200) {
$desc = $desc.Substring(0, 197) + "..."
}
Write-Host " Beschreibung: " -NoNewline -ForegroundColor $colors.Info
Write-Host $desc -ForegroundColor DarkGray
}
}
# Hauptprogramm
try {
Write-Header "TED Semantische Suche"
Write-Host "Suchtext: " -NoNewline -ForegroundColor $colors.Info
Write-Host $Query -ForegroundColor $colors.Warning
Write-Host "Parameter: TopK=$TopK, Threshold=$Threshold" -ForegroundColor DarkGray
Write-Host ""
# Request Body erstellen
$body = @{
text = $Query
topK = $TopK
threshold = $Threshold
} | ConvertTo-Json
# API aufrufen
Write-Host "Suche laeuft..." -ForegroundColor $colors.Info
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$response = Invoke-RestMethod -Uri "$ApiUrl/similarity/text" `
-Method Post `
-ContentType "application/json; charset=utf-8" `
-Body $body `
-ErrorAction Stop
$stopwatch.Stop()
# Ergebnisse anzeigen
$resultCount = $response.resultCount
$embeddingTime = $response.embeddingTimeMs
$searchTime = $response.searchTimeMs
$totalTime = $stopwatch.ElapsedMilliseconds
Write-Header "Suchergebnisse: $resultCount Treffer"
Write-Host "Zeiten: Embedding=${embeddingTime}ms, Suche=${searchTime}ms, Gesamt=${totalTime}ms" -ForegroundColor DarkGray
if ($resultCount -eq 0) {
Write-Host ""
Write-Host "Keine passenden Ausschreibungen gefunden." -ForegroundColor $colors.Warning
Write-Host "Versuchen Sie:" -ForegroundColor $colors.Info
Write-Host " - Andere Suchbegriffe" -ForegroundColor DarkGray
Write-Host " - Niedrigeren Schwellwert (-Threshold 0.3)" -ForegroundColor DarkGray
}
else {
$rank = 1
foreach ($doc in $response.results) {
Write-Result -Rank $rank -Doc $doc
$rank++
}
}
Write-Host ""
Write-Host ("-" * 80) -ForegroundColor DarkGray
Write-Host "Suche abgeschlossen." -ForegroundColor $colors.Success
} catch {
Write-Host ""
Write-Host "FEHLER: $_" -ForegroundColor $colors.Error
if ($_.Exception.Response.StatusCode -eq 503) {
Write-Host "Der Vektorisierungsdienst ist nicht verfuegbar." -ForegroundColor $colors.Warning
Write-Host "Stellen Sie sicher, dass der Embedding-Service auf Port 8001 laeuft." -ForegroundColor $colors.Info
}
elseif ($_.Exception.Message -like "*Unable to connect*") {
Write-Host "Konnte keine Verbindung zum Server herstellen." -ForegroundColor $colors.Warning
Write-Host "Stellen Sie sicher, dass die Anwendung auf $ApiUrl laeuft." -ForegroundColor $colors.Info
}
exit 1
}