From ba6d3682264d7a0207c584e2b5ff976db856b952 Mon Sep 17 00:00:00 2001 From: Enrico Ros Date: Wed, 3 May 2023 11:14:15 -0700 Subject: [PATCH] Support Helicone Keys --- .env.example | 7 ++-- src/common/state/store-settings.ts | 20 ++++++----- src/common/types/env.d.ts | 5 ++- src/modules/openai/OpenAIAdvancedSettings.tsx | 33 +++++++++++++++---- src/modules/openai/openai.client.ts | 5 +-- src/modules/openai/openai.server.ts | 6 ++-- src/modules/openai/openai.types.ts | 3 +- 7 files changed, 55 insertions(+), 24 deletions(-) diff --git a/.env.example b/.env.example index 9a1f55210..49e6c7f52 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,13 @@ # [Recommended for local deployments] Backend API key for OpenAI, so that users don't need one (UI > this > '') OPENAI_API_KEY= -# [Not needed] Set the backend host for the OpenAI API, to enable platforms such as Helicone (UI > this > api.openai.com) -OPENAI_API_HOST= # [Not needed] Sets the "OpenAI-Organization" header field to support organization users (UI > this > '') OPENAI_API_ORG_ID= +# [Optional] Set the backend host for the OpenAI API, to enable platforms such as Helicone (UI > this > api.openai.com) +OPENAI_API_HOST= +# [Optional, Helicone] Helicone API key: https://www.helicone.ai/keys +HELICONE_API_KEY= + # [Optional] Enables ElevenLabs credentials on the server side - for optional text-to-speech ELEVENLABS_API_KEY= ELEVENLABS_API_HOST= diff --git a/src/common/state/store-settings.ts b/src/common/state/store-settings.ts index 6ae4b0132..98fe8613b 100644 --- a/src/common/state/store-settings.ts +++ b/src/common/state/store-settings.ts @@ -31,11 +31,14 @@ interface SettingsStore { apiKey: string; setApiKey: (apiKey: string) => void; + apiOrganizationId: string; + setApiOrganizationId: (apiOrganizationId: string) => void; + apiHost: string; setApiHost: (apiHost: string) => void; - apiOrganizationId: string; - setApiOrganizationId: (apiOrganizationId: string) => void; + heliconeKey: string; + setHeliconeKey: (heliconeKey: string) => void; modelTemperature: number; setModelTemperature: (modelTemperature: number) => void; @@ -108,18 +111,17 @@ export const useSettingsStore = create()( // OpenAI API settings - apiKey: (function() { - // this will be removed in April - if (typeof localStorage === 'undefined') return ''; - return localStorage.getItem('app-settings-openai-api-key') || ''; - })(), + apiKey: '', setApiKey: (apiKey: string) => set({ apiKey }), + apiOrganizationId: '', + setApiOrganizationId: (apiOrganizationId: string) => set({ apiOrganizationId }), + apiHost: '', setApiHost: (apiHost: string) => set({ apiHost }), - apiOrganizationId: '', - setApiOrganizationId: (apiOrganizationId: string) => set({ apiOrganizationId }), + heliconeKey: '', + setHeliconeKey: (heliconeKey: string) => set({ heliconeKey }), modelTemperature: 0.5, setModelTemperature: (modelTemperature: number) => set({ modelTemperature }), diff --git a/src/common/types/env.d.ts b/src/common/types/env.d.ts index 7cab81122..2c0f0ed74 100644 --- a/src/common/types/env.d.ts +++ b/src/common/types/env.d.ts @@ -7,8 +7,11 @@ declare namespace NodeJS { // OpenAI - chat.ts OPENAI_API_KEY: string; - OPENAI_API_HOST: string; OPENAI_API_ORG_ID: string; + OPENAI_API_HOST: string; + + // Helicone + HELICONE_API_KEY: string; // ElevenLabs - speech.ts ELEVENLABS_API_KEY: string; diff --git a/src/modules/openai/OpenAIAdvancedSettings.tsx b/src/modules/openai/OpenAIAdvancedSettings.tsx index ed1c957c0..f60c90b13 100644 --- a/src/modules/openai/OpenAIAdvancedSettings.tsx +++ b/src/modules/openai/OpenAIAdvancedSettings.tsx @@ -12,9 +12,10 @@ import { useSettingsStore } from '@/common/state/store-settings'; export function OpenAIAdvancedSettings() { // external state - const { apiHost, setApiHost, apiOrganizationId, setApiOrganizationId, modelTemperature, setModelTemperature, modelMaxResponseTokens, setModelMaxResponseTokens } = useSettingsStore(state => ({ - apiHost: state.apiHost, setApiHost: state.setApiHost, + const { apiOrganizationId, setApiOrganizationId, apiHost, setApiHost, heliconeKey, setHeliconeKey, modelTemperature, setModelTemperature, modelMaxResponseTokens, setModelMaxResponseTokens } = useSettingsStore(state => ({ apiOrganizationId: state.apiOrganizationId, setApiOrganizationId: state.setApiOrganizationId, + apiHost: state.apiHost, setApiHost: state.setApiHost, + heliconeKey: state.heliconeKey, setHeliconeKey: state.setHeliconeKey, modelTemperature: state.modelTemperature, setModelTemperature: state.setModelTemperature, modelMaxResponseTokens: state.modelMaxResponseTokens, setModelMaxResponseTokens: state.setModelMaxResponseTokens, }), shallow); @@ -23,9 +24,11 @@ export function OpenAIAdvancedSettings() { const handleMaxTokensChange = (event: Event, newValue: number | number[]) => setModelMaxResponseTokens(newValue as number); + const handleApiOrganizationIdChange = (e: React.ChangeEvent) => setApiOrganizationId((e.target as HTMLInputElement).value); + const handleApiHostChange = (e: React.ChangeEvent) => setApiHost((e.target as HTMLInputElement).value); - const handleApiOrganizationIdChange = (e: React.ChangeEvent) => setApiOrganizationId((e.target as HTMLInputElement).value); + const handleHeliconeKeyChange = (e: React.ChangeEvent) => setHeliconeKey((e.target as HTMLInputElement).value); return (
+ + + + Organization ID + + + What is this + + + + + @@ -84,15 +103,15 @@ export function OpenAIAdvancedSettings() { - Organization ID + Helicone Key - What is this + Generate here diff --git a/src/modules/openai/openai.client.ts b/src/modules/openai/openai.client.ts index ab982a58a..799a1f6da 100644 --- a/src/modules/openai/openai.client.ts +++ b/src/modules/openai/openai.client.ts @@ -51,10 +51,11 @@ export async function callChat(modelId: ChatModelId, messages: OpenAI.Wire.Chat. export const getOpenAISettings = (): OpenAI.API.Configuration => { - const { apiKey, apiHost, apiOrganizationId } = useSettingsStore.getState(); + const { apiKey, apiOrganizationId, apiHost, heliconeKey } = useSettingsStore.getState(); return { ...(apiKey ? { apiKey } : {}), - ...(apiHost ? { apiHost } : {}), ...(apiOrganizationId ? { apiOrganizationId } : {}), + ...(apiHost ? { apiHost } : {}), + ...(heliconeKey ? { heliconeKey } : {}), }; }; \ No newline at end of file diff --git a/src/modules/openai/openai.server.ts b/src/modules/openai/openai.server.ts index b9d063340..e4b3e29b2 100644 --- a/src/modules/openai/openai.server.ts +++ b/src/modules/openai/openai.server.ts @@ -11,6 +11,7 @@ function openAIHeaders(api: OpenAI.API.Configuration): HeadersInit { 'Content-Type': 'application/json', Authorization: `Bearer ${api.apiKey}`, ...(api.apiOrganizationId && { 'OpenAI-Organization': api.apiOrganizationId }), + ...(api.heliconeKey && { 'Helicone-Auth': `Bearer ${api.heliconeKey}` }), }; } @@ -35,7 +36,7 @@ export async function openaiGet(api: OpenAI.API.Configurati return await response.json(); } -export async function openaiPostResponse(api: OpenAI.API.Configuration, path: string, body: TBody, signal?: AbortSignal,): Promise { +export async function openaiPostResponse(api: OpenAI.API.Configuration, path: string, body: TBody, signal?: AbortSignal): Promise { const response = await fetch(`https://${api.apiHost}${path}`, { method: 'POST', headers: openAIHeaders(api), @@ -63,8 +64,9 @@ export function toApiChatRequest(body: Partial): OpenAI // override with optional client configuration const api: OpenAI.API.Configuration = { apiKey: (body.api?.apiKey || process.env.OPENAI_API_KEY || '').trim(), - apiHost: (body?.api?.apiHost || process.env.OPENAI_API_HOST || 'api.openai.com').trim().replaceAll('https://', ''), apiOrganizationId: (body.api?.apiOrganizationId || process.env.OPENAI_API_ORG_ID || '').trim(), + apiHost: (body?.api?.apiHost || process.env.OPENAI_API_HOST || 'api.openai.com').trim().replaceAll('https://', ''), + heliconeKey: (body?.api?.heliconeKey || process.env.HELICONE_API_KEY || '').trim(), }; if (!api.apiKey) throw new Error('Missing OpenAI API Key. Add it on the client side (Settings icon) or server side (your deployment).'); diff --git a/src/modules/openai/openai.types.ts b/src/modules/openai/openai.types.ts index 680f12f32..13837bf01 100644 --- a/src/modules/openai/openai.types.ts +++ b/src/modules/openai/openai.types.ts @@ -6,8 +6,9 @@ export namespace OpenAI { // the parameters are optional because they can be server-set export interface Configuration { apiKey?: string; - apiHost?: string; // default: api.openai.com apiOrganizationId?: string; // default: '' + apiHost?: string; // default: api.openai.com + heliconeKey?: string; // default: missing } export namespace Chat {