feat: add custom API endpoint support for Google Gemini

This commit is contained in:
Jonathan Zhang
2025-01-06 14:20:15 +08:00
parent 473f73c23f
commit ceca769a20
3 changed files with 20 additions and 4 deletions
@@ -23,7 +23,7 @@ const DEFAULT_GEMINI_HOST = 'https://generativelanguage.googleapis.com';
export function geminiAccess(access: GeminiAccessSchema, modelRefId: string | null, apiPath: string): { headers: HeadersInit, url: string } {
const geminiKey = access.geminiKey || env.GEMINI_API_KEY || '';
const geminiHost = fixupHost(DEFAULT_GEMINI_HOST, apiPath);
const geminiHost = fixupHost(access.geminiHost || DEFAULT_GEMINI_HOST, apiPath);
// update model-dependent paths
if (apiPath.includes('{model=models/*}')) {
@@ -59,6 +59,7 @@ async function geminiPOST<TOut extends object, TPostBody extends object>(access:
export const geminiAccessSchema = z.object({
dialect: z.enum(['gemini']),
geminiKey: z.string(),
geminiHost: z.string(),
minSafetyLevel: GeminiWire_Safety.HarmBlockThreshold_enum,
});
export type GeminiAccessSchema = z.infer<typeof geminiAccessSchema>;
+15 -3
View File
@@ -17,9 +17,11 @@ import { useLlmUpdateModels } from '../../llm.client.hooks';
import { useServiceSetup } from '../useServiceSetup';
import { ModelVendorGemini } from './gemini.vendor';
import { useToggleableBoolean } from '~/common/util/hooks/useToggleableBoolean';
import { FormTextField } from '~/common/components/forms/FormTextField';
const GEMINI_API_KEY_LINK = 'https://makersuite.google.com/app/apikey';
const GEMINI_API_KEY_LINK = 'https://aistudio.google.com/app/apikey';
const SAFETY_OPTIONS: { value: GeminiWire_Safety.HarmBlockThreshold, label: string }[] = [
{ value: 'HARM_BLOCK_THRESHOLD_UNSPECIFIED', label: 'Default' },
@@ -32,12 +34,14 @@ const SAFETY_OPTIONS: { value: GeminiWire_Safety.HarmBlockThreshold, label: stri
export function GeminiServiceSetup(props: { serviceId: DModelsServiceId }) {
// advanced mode
const advanced = useToggleableBoolean(true);
// external state
const { service, serviceAccess, serviceHasBackendCap, serviceHasLLMs, serviceSetupValid, updateSettings } =
useServiceSetup(props.serviceId, ModelVendorGemini);
// derived state
const { geminiKey, minSafetyLevel } = serviceAccess;
const { geminiKey, geminiHost, minSafetyLevel } = serviceAccess;
const needsUserKey = !serviceHasBackendCap;
const shallFetchSucceed = !needsUserKey || (!!geminiKey && serviceSetupValid);
@@ -90,7 +94,15 @@ export function GeminiServiceSetup(props: { serviceId: DModelsServiceId }) {
{/*of being unsafe.*/}
</FormHelperText>
<SetupFormRefetchButton refetch={refetch} disabled={!shallFetchSucceed || isFetching} loading={isFetching} error={isError} />
{advanced.on && <FormTextField
autoCompleteId='openai-host'
title='API Endpoint'
placeholder={`https://generativelanguage.googleapis.com`}
value={geminiHost}
onChange={text => updateSettings({ geminiHost: text })}
/>}
<SetupFormRefetchButton refetch={refetch} disabled={!shallFetchSucceed || isFetching} loading={isFetching} error={isError} advanced={advanced} />
{isError && <InlineError error={error} />}
+3
View File
@@ -10,6 +10,7 @@ import { GeminiServiceSetup } from './GeminiServiceSetup';
interface DGeminiServiceSettings {
geminiKey: string;
geminiHost: string;
minSafetyLevel: GeminiWire_Safety.HarmBlockThreshold;
}
@@ -39,6 +40,7 @@ export const ModelVendorGemini: IModelVendor<DGeminiServiceSettings, GeminiAcces
// functions
initializeSetup: () => ({
geminiKey: '',
geminiHost: '',
minSafetyLevel: 'HARM_BLOCK_THRESHOLD_UNSPECIFIED',
}),
validateSetup: (setup) => {
@@ -47,6 +49,7 @@ export const ModelVendorGemini: IModelVendor<DGeminiServiceSettings, GeminiAcces
getTransportAccess: (partialSetup): GeminiAccessSchema => ({
dialect: 'gemini',
geminiKey: partialSetup?.geminiKey || '',
geminiHost: partialSetup?.geminiHost || '',
minSafetyLevel: partialSetup?.minSafetyLevel || 'HARM_BLOCK_THRESHOLD_UNSPECIFIED',
}),