From 79becf6fbbf85a6c3ce7456d990fb3ec532b0162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Rehp=C3=B6hler?= Date: Sat, 29 Jul 2023 15:59:25 +0200 Subject: [PATCH 1/2] Updated and completed german translations --- app/locales/de.ts | 243 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 184 insertions(+), 59 deletions(-) diff --git a/app/locales/de.ts b/app/locales/de.ts index e8d4dc9c719..475c4cb5511 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -7,19 +7,57 @@ const de: PartialLocaleType = { Unauthorized: "Unbefugter Zugriff, bitte geben Sie den Zugangscode auf der Einstellungsseite ein.", }, + Auth: { + Title: "Zugangscode benötigt", + Tips: "Bitte geben sie den Zugangscode ein.", + Input: "Zugangs Code", + Confirm: "Bestätigen", + Later: "Später", + }, ChatItem: { ChatItemCount: (count: number) => `${count} Nachrichten`, }, Chat: { SubTitle: (count: number) => `${count} Nachrichten mit ChatGPT`, + EditMessage: { + Topic: { + Title: "Titel", + SubTitle: "Titel des Chats ändern", + }, + }, Actions: { ChatList: "Zur Chat-Liste gehen", - CompressedHistory: "Komprimierter Gedächtnis-Prompt", + CompressedHistory: "komprimierter Verlauf", Export: "Alle Nachrichten als Markdown exportieren", Copy: "Kopieren", Stop: "Stop", Retry: "Wiederholen", - Delete: "Delete", + Pin: "Anheften", + PinToastContent: "Es wurde eine Nachricht an den Context angeheftet", + PinToastAction: "Anzeigen", + Delete: "Löschen", + Edit: "Bearbeiten", + }, + Commands: { + new: "Neuen Chat starten", + newm: "Neuen Chat mit Persona starten", + next: "Nächster Chat", + prev: "Vorheriger Chat", + clear: "Kontext zurücksetzen", + del: "Chat löschen", + }, + InputActions: { + Stop: "Stop", + ToBottom: "zur letzen Nachricht", + Theme: { + auto: "Auto", + light: "Helle Farben", + dark: "Dunkle Farben", + }, + Prompt: "Prompts", + Masks: "Personas", + Clear: "Kontext löschen", + Settings: "Einstellungen", }, Rename: "Chat umbenennen", Typing: "Tippen...", @@ -32,9 +70,10 @@ const de: PartialLocaleType = { }, Send: "Senden", Config: { - Reset: "Reset to Default", - SaveAs: "Save as Mask", + Reset: "Zurücksetzen", + SaveAs: "Als Persona speichern", }, + IsContext: "Kontext Prompt", }, Export: { Title: "Alle Nachrichten", @@ -42,28 +81,65 @@ const de: PartialLocaleType = { Download: "Herunterladen", MessageFromYou: "Deine Nachricht", MessageFromChatGPT: "Nachricht von ChatGPT", + Share: "Teilen mit ShareGPT", + Format: { + Title: "Export Format", + SubTitle: "Markdown oder PNG Bild", + }, + IncludeContext: { + Title: "Kontext einschließen", + SubTitle: "Export Kontextprompts in eine Persona", + }, + Steps: { + Select: "Auswählen", + Preview: "Vorschau", + }, + Image: { + Toast: "Screenshot...", + Modal: "Langes klicken oder Rechtsklick um Chat als Bild zu speichern", + }, + }, + Select: { + Search: "Suche", + All: "Alles auswählen", + Latest: "Aktuellste Auswählen", + Clear: "Löschen", }, Memory: { - Title: "Gedächtnis-Prompt", - EmptyContent: "Noch nichts.", - Send: "Gedächtnis senden", - Copy: "Gedächtnis kopieren", + Title: "Verlauf", + EmptyContent: "Bisher kein Gesprächsverlauf.", + Send: "Verlauf senden", + Copy: "Verlauf kopieren", Reset: "Sitzung zurücksetzen", ResetConfirm: - "Das Zurücksetzen löscht den aktuellen Gesprächsverlauf und das Langzeit-Gedächtnis. Möchten Sie wirklich zurücksetzen?", + "Zurücksetzen löscht den aktuellen Gesprächsverlauf und das Langzeitgedächtnis. Möchten Sie wirklich zurücksetzen?", }, Home: { NewChat: "Neuer Chat", - DeleteChat: "Bestätigen Sie, um das ausgewählte Gespräch zu löschen?", + DeleteChat: "Den ausgewählten Chat wirklich löschen?", DeleteToast: "Chat gelöscht", Revert: "Zurücksetzen", }, Settings: { Title: "Einstellungen", SubTitle: "Alle Einstellungen", - + Danger: { + Reset: { + Title: "Alle Einstellungen zurücksetzen", + SubTitle: + "Alle Einstellungen auf die Standardeinstellungen zurücksetzen", + Action: "Zurücksetzen", + Confirm: "Wirklich auf Standardeinstellungen zurücksetzen?", + }, + Clear: { + Title: "Alle Daten löschen", + SubTitle: "Lösche alle Chats und Einstellungen", + Action: "Löschen", + Confirm: "Wirklich alle Chats und Einstellungen löschen?", + }, + }, Lang: { - Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` + Name: "Sprache", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` All: "Alle Sprachen", }, Avatar: "Avatar", @@ -72,29 +148,40 @@ const de: PartialLocaleType = { SubTitle: "Schriftgröße des Chat-Inhalts anpassen", }, InjectSystemPrompts: { - Title: "System-Prompts einfügen", + Title: "Systemprompts einfügen", SubTitle: "Erzwingt das Hinzufügen eines simulierten systemweiten Prompts von ChatGPT am Anfang der Nachrichtenliste bei jeder Anfrage", }, + InputTemplate: { + Title: "Eingabe Template", + SubTitle: "Neue Nachrichten werden mit diesem Template gesendet.", + }, + Update: { Version: (x: string) => `Version: ${x}`, IsLatest: "Neueste Version", - CheckUpdate: "Update prüfen", + CheckUpdate: "Auf Update prüfen", IsChecking: "Update wird geprüft...", FoundUpdate: (x: string) => `Neue Version gefunden: ${x}`, GoToUpdate: "Aktualisieren", }, - SendKey: "Senden-Taste", + SendKey: "Nachricht Senden", Theme: "Erscheinungsbild", - TightBorder: "Enger Rahmen", + TightBorder: "Schmaler Rahmen", SendPreviewBubble: { - Title: "Vorschau-Bubble senden", - SubTitle: "Preview markdown in bubble", + Title: "Nachricht als Vorschau-Bubble", + SubTitle: "Markdown-Vorschau der aktuellen Chat-Nachricht", }, Mask: { Splash: { - Title: "Mask Splash Screen", - SubTitle: "Show a mask splash screen before starting new chat", + Title: "Persona-Startbildschirm", + SubTitle: + "Vor dem Start eines neuen Chats einen Startbildschirm anzeigen", + }, + Builtin: { + Title: "Vorinstallierte Personas ausblenden", + SubTitle: + "Ausblenden der vorinstallierten Personas in der Auswahlliste", }, }, Prompt: { @@ -107,28 +194,29 @@ const de: PartialLocaleType = { `${builtin} integriert, ${custom} benutzerdefiniert`, Edit: "Bearbeiten", Modal: { - Title: "Prompt List", - Add: "Add One", - Search: "Search Prompts", + Title: "Prompt-Liste", + Add: "Hinzufügen", + Search: "Suche Prompts", }, EditModal: { - Title: "Edit Prompt", + Title: "Prompt bearbeiten", }, }, HistoryCount: { - Title: "Anzahl der angehängten Nachrichten", - SubTitle: "Anzahl der pro Anfrage angehängten gesendeten Nachrichten", + Title: "Anzahl angehängte Nachrichten", + SubTitle: + "Anzahl der pro Anfrage angehängten Nachrichten aus dem Verlauf", }, CompressThreshold: { Title: "Schwellenwert für Verlaufskomprimierung", SubTitle: - "Komprimierung, wenn die Länge der unkomprimierten Nachrichten den Wert überschreitet", + "Komprimiert den Verlauf, wenn die Länge der unkomprimierten Nachrichten den Wert überschreitet", }, Token: { Title: "API-Schlüssel", SubTitle: - "Verwenden Sie Ihren Schlüssel, um das Zugangscode-Limit zu ignorieren", - Placeholder: "OpenAI API-Schlüssel", + "Verwenden Sie Ihren eignen API-Schlüssel, um nicht an das Nutzungslimit gebunden zu sein", + Placeholder: "API-Schlüssel", }, Usage: { Title: "Kontostand", @@ -144,24 +232,38 @@ const de: PartialLocaleType = { SubTitle: "Zugangskontrolle aktiviert", Placeholder: "Zugangscode erforderlich", }, + Endpoint: { + Title: "Endpunkt", + SubTitle: "Benutzerdefinierter Endpunkt, muß mit http(s):// beginnen", + }, + CustomModel: { + Title: "Benutzerdefinierte Modelle", + SubTitle: + "Hinzufügen von eigenen, fine-getunten Modellen. Modellnamen sind durch Komma getrennt.", + }, Model: "Modell", Temperature: { - Title: "Temperature", //Temperatur + Title: "Temperatur", SubTitle: "Ein größerer Wert führt zu zufälligeren Antworten", }, + TopP: { + Title: "Top P", + SubTitle: + "Ändern sie diesen Werte nicht gleichzeitig mit der Temperatur.", + }, MaxTokens: { - Title: "Max Tokens", //Maximale Token + Title: "Max Tokens", SubTitle: "Maximale Anzahl der Anfrage- plus Antwort-Token", }, PresencePenalty: { - Title: "Presence Penalty", //Anwesenheitsstrafe + Title: "Presence Penalty", SubTitle: "Ein größerer Wert erhöht die Wahrscheinlichkeit, dass über neue Themen gesprochen wird", }, FrequencyPenalty: { - Title: "Frequency Penalty", // HäufigkeitStrafe + Title: "Frequency Penalty", SubTitle: - "Ein größerer Wert, der die Wahrscheinlichkeit verringert, dass dieselbe Zeile wiederholt wird", + "Ein größerer Wert verringert die Wahrscheinlichkeit, dass dieselbe Zeile wiederholt wird", }, }, Store: { @@ -171,12 +273,12 @@ const de: PartialLocaleType = { "Etwas ist schief gelaufen, bitte versuchen Sie es später noch einmal.", Prompt: { History: (content: string) => - "Dies ist eine Zusammenfassung des Chatverlaufs zwischen dem KI und dem Benutzer als Rückblick: " + + "Dies ist eine Zusammenfassung des Chatverlaufs zwischen der KI und dem Benutzer: " + content, Topic: - "Bitte erstellen Sie einen vier- bis fünfwörtigen Titel, der unser Gespräch zusammenfasst, ohne Einleitung, Zeichensetzung, Anführungszeichen, Punkte, Symbole oder zusätzlichen Text. Entfernen Sie Anführungszeichen.", + "Thema des Chats, darf aus vier bis fünf Wörtern bestehen und soll diesen Chat zusammenfassen. Nur Buchstaben, keine Sonderzeichen, Satzzeichen, Symbole/Emojis oder zusätzlichen Text.", Summarize: - "Fassen Sie unsere Diskussion kurz in 200 Wörtern oder weniger zusammen, um sie als Pronpt für zukünftige Gespräche zu verwenden.", + "Fasse diesen Chat kurz, in 200 Wörtern oder weniger, zusammen. Die Zusammenfassung sollte so beschrieben sein, das sie als Prompt für zukünftige Chats verwendet werden kann.", }, }, Copy: { @@ -186,55 +288,73 @@ const de: PartialLocaleType = { }, Context: { Toast: (x: any) => `Mit ${x} Kontext-Prompts`, - Edit: "Kontext- und Gedächtnis-Prompts", + Edit: "Kontext und Verlauf", Add: "Hinzufügen", + Clear: "Kontext gelöscht", + Revert: "Rückgängig machen", }, Plugin: { Name: "Plugin", }, Mask: { - Name: "Mask", + Name: "Persona", Page: { Title: "Prompt Template", SubTitle: (count: number) => `${count} prompt templates`, - Search: "Search Templates", - Create: "Create", + Search: "Templates suchen", + Create: "Anlegen", }, Item: { Info: (count: number) => `${count} prompts`, Chat: "Chat", - View: "View", - Edit: "Edit", - Delete: "Delete", - DeleteConfirm: "Confirm to delete?", + View: "Anzeigen", + Edit: "Bearbeiten", + Delete: "Löschen", + DeleteConfirm: "Wirklich löschen?", }, EditModal: { Title: (readonly: boolean) => - `Edit Prompt Template ${readonly ? "(readonly)" : ""}`, + `Prompt Template bearbeiten ${readonly ? "(schreibgeschützt)" : ""}`, Download: "Download", - Clone: "Clone", + Clone: "Duplizieren", }, Config: { Avatar: "Bot Avatar", Name: "Bot Name", + Sync: { + Title: "Globale Konfiguration", + SubTitle: "Globale Konfiguration für diesen Chat übernehmen", + Confirm: "Wirklich globale Konfiguration übernehmen?", + }, + HideContext: { + Title: "Kontextprompts ausblenden", + SubTitle: "Kontextabhängige Prompts im Chat nicht anzeigen", + }, + Share: { + Title: "Persona teilen", + SubTitle: "Generiere einen Link für diese Persona", + Action: "Link kopieren", + }, }, }, NewChat: { - Return: "Return", - Skip: "Skip", - Title: "Pick a Mask", - SubTitle: "Chat with the Soul behind the Mask", - More: "Find More", - NotShow: "Not Show Again", - ConfirmNoShow: "Confirm to disable?You can enable it in settings later.", + Return: "Zurück", + Skip: "Überspringen", + Title: "Persona wählen", + SubTitle: + "Eine Persona enthält eine Rollenbeschreibung für deinen Bot und einen vordefinierten Prompt.", + More: "Weitere finden", + NotShow: "Nicht nochmal anzeigen", + ConfirmNoShow: + "Wirklich deaktivieren? Du kannst diese Einstellung später wieder aktivieren.", }, UI: { - Confirm: "Confirm", - Cancel: "Cancel", - Close: "Close", - Create: "Create", - Edit: "Edit", + Confirm: "Bestätigen", + Cancel: "Abbrechen", + Close: "Schließen", + Create: "Anlegen", + Edit: "Bearbeiten", }, Exporter: { Model: "Modell", @@ -242,6 +362,11 @@ const de: PartialLocaleType = { Topic: "Thema", Time: "Zeit", }, + + URLCommand: { + Code: "Zugangscode-URL erkannt. Zugangscode übernehmen?", + Settings: "Konfigurations-URL erkannt. Konfiguration aus URL übernehmen?", + }, }; export default de; From 8d859c65151060c9510b3a36a627293753da9d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Rehpo=CC=88hler?= Date: Sun, 30 Jul 2023 15:29:14 +0200 Subject: [PATCH 2/2] Added the possibility to enable Azure OpenAI server side. To enable configure the following ENV vars: - OPENAI_API_KEY: set it to your Azure OpenAI API key - BASE_URL: set it to your Azure endpoint - OPENAI_ON_AZURE: set to "1" - AZURE_OPENAI_APIVERSION: choose an API version e.g. 2023-05-15 - AZURE_OPENAI_DEPLOYMENT_ID: set to your deployment id of the model that should be used --- .env.template | 19 +++++++++++++++++-- app/api/common.ts | 13 ++++++++++++- app/api/openai/[...path]/route.ts | 5 ++++- app/config/server.ts | 6 ++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/.env.template b/.env.template index 0f4bf0e7c00..644aa6cbd0b 100644 --- a/.env.template +++ b/.env.template @@ -1,5 +1,5 @@ -# Your openai api key. (required) +# Your openai or azure api key. (required) OPENAI_API_KEY=sk-xxxx # Access passsword, separated by comma. (optional) @@ -10,9 +10,24 @@ PROXY_URL=http://localhost:7890 # Override openai api request base url. (optional) # Default: https://api.openai.com -# Examples: http://your-openai-proxy.com +# Examples: http://your-openai-proxy.com, https://.openai.azure.com BASE_URL= +# Use OpenAI on Azure. Set to "1" for Azure +# Default: Empty +OPENAI_ON_AZURE= + +# (optional) +# Azure API version, e.g. 2023-05-15 +# Default: Empty +AZURE_OPENAI_APIVERSION= + +# (optional) +# Azure deployment id +# Default: Empty +# Examples: gpt-3.5-turbo, MY_Azure_Deployment +AZURE_OPENAI_DEPLOYMENT_ID= + # Specify OpenAI organization ID.(optional) # Default: Empty # If you do not want users to input their own API key, set this value to 1. diff --git a/app/api/common.ts b/app/api/common.ts index 3146b6bd99d..507376ef7f1 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -1,4 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; +import { getServerSideConfig } from "../config/server"; export const OPENAI_URL = "api.openai.com"; const DEFAULT_PROTOCOL = "https"; @@ -7,6 +8,7 @@ const BASE_URL = process.env.BASE_URL || OPENAI_URL; const DISABLE_GPT4 = !!process.env.DISABLE_GPT4; export async function requestOpenai(req: NextRequest) { + const config = getServerSideConfig(); const controller = new AbortController(); const authValue = req.headers.get("Authorization") ?? ""; const openaiPath = `${req.nextUrl.pathname}${req.nextUrl.search}`.replaceAll( @@ -31,11 +33,20 @@ export async function requestOpenai(req: NextRequest) { controller.abort(); }, 10 * 60 * 1000); - const fetchUrl = `${baseUrl}/${openaiPath}`; + let fetchUrl: string; + if (config.openaiOnAzure === "1") { + const deploymentId = config.azureDeploymentId; + const apiVersion = config.azureApiVersion; + fetchUrl = `${baseUrl}/openai/deployments/${deploymentId}/chat/completions?api-version=${apiVersion}`; + } else { + fetchUrl = `${baseUrl}/${openaiPath}`; + } + const fetchOptions: RequestInit = { headers: { "Content-Type": "application/json", "Cache-Control": "no-store", + "api-key": config.apiKey ? config.apiKey : "", Authorization: authValue, ...(process.env.OPENAI_ORG_ID && { "OpenAI-Organization": process.env.OPENAI_ORG_ID, diff --git a/app/api/openai/[...path]/route.ts b/app/api/openai/[...path]/route.ts index 9df005a317a..e9036634972 100644 --- a/app/api/openai/[...path]/route.ts +++ b/app/api/openai/[...path]/route.ts @@ -32,7 +32,10 @@ async function handle( const subpath = params.path.join("/"); - if (!ALLOWD_PATH.has(subpath)) { + if ( + !ALLOWD_PATH.has(subpath) && + !subpath.startsWith("/openai/deployments/") + ) { console.log("[OpenAI Route] forbidden path ", subpath); return NextResponse.json( { diff --git a/app/config/server.ts b/app/config/server.ts index 6eab9ebecc0..67d382ed3a3 100644 --- a/app/config/server.ts +++ b/app/config/server.ts @@ -6,6 +6,9 @@ declare global { OPENAI_API_KEY?: string; CODE?: string; BASE_URL?: string; + OPENAI_ON_AZURE?: string; + AZURE_OPENAI_APIVERSION?: string; + AZURE_OPENAI_DEPLOYMENT_ID?: string; PROXY_URL?: string; VERCEL?: string; HIDE_USER_API_KEY?: string; // disable user's api key input @@ -39,6 +42,9 @@ export const getServerSideConfig = () => { return { apiKey: process.env.OPENAI_API_KEY, + openaiOnAzure: process.env.OPENAI_ON_AZURE, + azureApiVersion: process.env.AZURE_OPENAI_APIVERSION, + azureDeploymentId: process.env.AZURE_OPENAI_DEPLOYMENT_ID, code: process.env.CODE, codes: ACCESS_CODES, needCode: ACCESS_CODES.size > 0,