Support Helicone Keys

This commit is contained in:
Enrico Ros
2023-05-03 11:14:15 -07:00
parent d3d526423f
commit ba6d368226
7 changed files with 55 additions and 24 deletions
+5 -2
View File
@@ -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=
+11 -9
View File
@@ -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<SettingsStore>()(
// 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 }),
+4 -1
View File
@@ -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;
+26 -7
View File
@@ -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 (
<Section title='Advanced AI settings'
@@ -62,6 +65,22 @@ export function OpenAIAdvancedSettings() {
/>
</FormControl>
<FormControl orientation='horizontal' sx={{ justifyContent: 'space-between' }}>
<Box sx={{ minWidth: settingsCol1Width }}>
<FormLabel>
Organization ID
</FormLabel>
<FormHelperText sx={{ display: 'block' }}>
<Link level='body2' href={`${Brand.URIs.OpenRepo}/issues/63`} target='_blank'>What is this</Link>
</FormHelperText>
</Box>
<Input
variant='outlined' placeholder='Optional, for org users'
value={apiOrganizationId} onChange={handleApiOrganizationIdChange}
sx={{ flexGrow: 1 }}
/>
</FormControl>
<FormControl orientation='horizontal' sx={{ justifyContent: 'space-between' }}>
<Box sx={{ minWidth: settingsCol1Width }}>
<FormLabel>
@@ -84,15 +103,15 @@ export function OpenAIAdvancedSettings() {
<FormControl orientation='horizontal' sx={{ justifyContent: 'space-between' }}>
<Box sx={{ minWidth: settingsCol1Width }}>
<FormLabel>
Organization ID
Helicone Key
</FormLabel>
<FormHelperText sx={{ display: 'block' }}>
<Link level='body2' href={`${Brand.URIs.OpenRepo}/issues/63`} target='_blank'>What is this</Link>
Generate <Link level='body2' href='https://www.helicone.ai/keys' target='_blank'>here</Link>
</FormHelperText>
</Box>
<Input
variant='outlined' placeholder='Optional, for org users'
value={apiOrganizationId} onChange={handleApiOrganizationIdChange}
variant='outlined' placeholder='sk-...'
value={heliconeKey} onChange={handleHeliconeKeyChange}
sx={{ flexGrow: 1 }}
/>
</FormControl>
+3 -2
View File
@@ -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 } : {}),
};
};
+4 -2
View File
@@ -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<TOut extends object>(api: OpenAI.API.Configurati
return await response.json();
}
export async function openaiPostResponse<TBody extends object>(api: OpenAI.API.Configuration, path: string, body: TBody, signal?: AbortSignal,): Promise<Response> {
export async function openaiPostResponse<TBody extends object>(api: OpenAI.API.Configuration, path: string, body: TBody, signal?: AbortSignal): Promise<Response> {
const response = await fetch(`https://${api.apiHost}${path}`, {
method: 'POST',
headers: openAIHeaders(api),
@@ -63,8 +64,9 @@ export function toApiChatRequest(body: Partial<OpenAI.API.Chat.Request>): 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).');
+2 -1
View File
@@ -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 {