mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Support Helicone Keys
This commit is contained in:
+5
-2
@@ -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=
|
||||
|
||||
@@ -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 }),
|
||||
|
||||
Vendored
+4
-1
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 } : {}),
|
||||
};
|
||||
};
|
||||
@@ -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).');
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user