Minimaler C#-Proxy, der OpenAI-kompatible Endpunkte auf die Nele.AI API uebersetzt.
- Windows x64
- Kein .NET Runtime noetig, wenn du die Self-Contained EXE nutzt
- OpenAI-kompatibel:
GET /v1/modelsPOST /v1/chat/completions(sync + stream)POST /v1/responses(sync)POST /v1/audio/transcriptionsPOST /v1/images/generations
- Knowledge (Nele-Payload 1:1, fuer Agents/n8n):
GET /v1/knowledge/modelsGET /v1/knowledge/collectionsPOST /v1/knowledge/collectionsGET /v1/knowledge/collections/{id}PUT /v1/knowledge/collections/{id}DELETE /v1/knowledge/collections/{id}POST /v1/knowledge/collections/{id}/itemsPOST /v1/knowledge/collections/{id}/from-urlPUT /v1/knowledge/collections/{id}/embedPOST /v1/knowledge/collections/{id}/searchGET /v1/knowledge/items/{item}DELETE /v1/knowledge/items/{item}PUT /v1/knowledge/items/{item}/embed
- Optionaler Default fuer Chat-Modelle via Config
- Konfiguration wird immer aus dem Ordner der EXE gelesen
Proxy/enthaelt den Web-ProxyClients/NeleDesktop/enthaelt die WPF-Desktop-App
Eine schlanke WPF-App (net9.0) fuer den direkten Zugriff auf Nele AI.
Funktionen:
- Kompaktes Widget-Fenster mit globalem Hotkey (Default:
Ctrl+Alt+Space) - Dark/Light Mode Toggle oben rechts
- Chat-Verlauf mit mehreren Konversationen
- Ordner fuer Chats (Drag & Drop oder Rechtsklick -> Move to folder)
- Settings-Fenster fuer API-Key, Base-URL, Model-Liste und Hotkey
- Startet automatisch, wenn noch kein API-Key gesetzt ist
dotnet build .\NeleOpenAIProxy.sln
dotnet run --project .\Clients\NeleDesktop\NeleDesktop.csprojDie App speichert ihre Daten lokal als JSON:
%AppData%\NeleAIProxy\settings.json%AppData%\NeleAIProxy\conversations.json
Beispiel settings.json:
{
"apiKey": "YOUR_NELE_API_KEY",
"baseUrl": "https://api.aieva.io/api:v1/",
"selectedModel": "google-claude-4.5-sonnet",
"darkMode": true,
"hotkey": "Ctrl+Alt+Space"
}Lege appsettings.Local.json im gleichen Ordner wie die EXE ab (oder nutze appsettings.json). Im Repo liegen die Proxy-Configs unter Proxy/.
Beispiel:
{
"Urls": "http://localhost:5155",
"Nele": {
"BaseUrl": "https://api.aieva.io/api:v1/",
"ApiKey": "YOUR_NELE_API_KEY",
"DefaultChatModel": "google-claude-4.5-sonnet",
"ForceStream": false,
"DefaultDocumentCollectionId": "",
"ToolDescriptionMaxLength": 1000,
"ModelConfiguration": {
"ReasoningEffort": "high"
}
}
}Hinweis:
ToolDescriptionMaxLengthbegrenzttools[].function.description(Werte > 1000 werden auf 1000 gekappt).
cd .\Proxy\bin\Release\net9.0\win-x64\publish
.\NeleOpenAIProxy.exeInvoke-RestMethod http://localhost:5155/v1/modelsBeispielausgabe:
{
"object": "list",
"data": [
{
"id": "google-claude-4.5-sonnet",
"object": "model",
"created": 1769121744,
"owned_by": "nele"
}
]
}$body = @{
model = "google-claude-4.5-sonnet"
messages = @(
@{ role = "user"; content = "Sag kurz Hallo." }
)
temperature = 0.2
} | ConvertTo-Json -Depth 6
Invoke-RestMethod http://localhost:5155/v1/chat/completions `
-Method Post -ContentType "application/json" -Body $bodyAntwort anzeigen (komplett + nur Text):
$response = Invoke-RestMethod http://localhost:5155/v1/chat/completions `
-Method Post -ContentType "application/json" -Body $body
$response | ConvertTo-Json -Depth 6
$response.choices[0].message.contentBeispielausgabe:
{
"id": "chatcmpl-0123456789abcdef",
"object": "chat.completion",
"created": 1769121744,
"model": "google-claude-4.5-sonnet",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hallo."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}$body = @{
model = "google-claude-4.5-sonnet"
messages = @(@{ role = "user"; content = "Sag kurz Hallo." })
stream = $true
} | ConvertTo-Json -Depth 6
curl.exe -N http://localhost:5155/v1/chat/completions `
-H "Content-Type: application/json" -d $bodyBeispielausgabe (SSE, gekuerzt):
data: {"id":"chatcmpl-...","object":"chat.completion.chunk",...}
data: [DONE]
$body = @{
model = "google-claude-4.5-sonnet"
input = "Sag kurz Hallo."
} | ConvertTo-Json -Depth 6
Invoke-RestMethod http://localhost:5155/v1/responses `
-Method Post -ContentType "application/json" -Body $bodyAntwort anzeigen:
$response = Invoke-RestMethod http://localhost:5155/v1/responses `
-Method Post -ContentType "application/json" -Body $body
$response | ConvertTo-Json -Depth 6
$response.output_textBeispielausgabe:
{
"id": "resp_0123456789abcdef",
"object": "response",
"created_at": 1769121744,
"model": "google-claude-4.5-sonnet",
"status": "completed",
"output": [
{
"id": "msg_0123456789abcdef",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{
"type": "output_text",
"text": "Hallo."
}
]
}
],
"output_text": "Hallo."
}curl.exe -X POST http://localhost:5155/v1/audio/transcriptions `
-F "model=whisper-1" -F "file=@C:\path\audio.mp3"Beispielausgabe:
{
"text": "Transkribierter Text..."
}$body = @{
model = "gpt-image-1"
prompt = "A colorful abstract landscape"
} | ConvertTo-Json -Depth 6
Invoke-RestMethod http://localhost:5155/v1/images/generations `
-Method Post -ContentType "application/json" -Body $bodyBeispielausgabe:
{
"created": 1769121744,
"data": [
{
"url": "https://example.com/generated-image.png"
}
]
}- Wenn
modelfehlt, wirdNele:DefaultChatModelgenutzt. Nele:ForceStream=trueerzwingt Streaming-Antworten fuer/v1/chat/completions(SSE), auch wenn der Client keinstream: truesendet.Nele:ModelConfiguration:ReasoningEffortsteuert den Default fuermodelConfiguration.reasoning_effort(kann per Request ueberschrieben werden).Nele:DefaultDocumentCollectionIdsetzt eine Standard-Collection fuer/v1/chat/completions, sofern keindocumentCollectionIdim Request gesetzt ist und keinweb_searchverwendet wird.- Die API liefert keine offiziellen Kontext-Fenster-Groessen pro Modell.