Merge pull request #62 from Nothing1024/main
Feat: OpenAI Base URL supported
This commit is contained in:
commit
5e6b88994a
@ -5,8 +5,8 @@ from openai import AsyncOpenAI
|
|||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
|
||||||
async def process_tasks(prompts, api_key):
|
async def process_tasks(prompts, api_key, base_url):
|
||||||
tasks = [generate_image(prompt, api_key) for prompt in prompts]
|
tasks = [generate_image(prompt, api_key, base_url) for prompt in prompts]
|
||||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||||
|
|
||||||
processed_results = []
|
processed_results = []
|
||||||
@ -20,8 +20,8 @@ async def process_tasks(prompts, api_key):
|
|||||||
return processed_results
|
return processed_results
|
||||||
|
|
||||||
|
|
||||||
async def generate_image(prompt, api_key):
|
async def generate_image(prompt, api_key, base_url):
|
||||||
client = AsyncOpenAI(api_key=api_key)
|
client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
||||||
image_params = {
|
image_params = {
|
||||||
"model": "dall-e-3",
|
"model": "dall-e-3",
|
||||||
"quality": "standard",
|
"quality": "standard",
|
||||||
@ -60,7 +60,7 @@ def create_alt_url_mapping(code):
|
|||||||
return mapping
|
return mapping
|
||||||
|
|
||||||
|
|
||||||
async def generate_images(code, api_key, image_cache):
|
async def generate_images(code, api_key, base_url, image_cache):
|
||||||
# Find all images
|
# Find all images
|
||||||
soup = BeautifulSoup(code, "html.parser")
|
soup = BeautifulSoup(code, "html.parser")
|
||||||
images = soup.find_all("img")
|
images = soup.find_all("img")
|
||||||
@ -87,7 +87,7 @@ async def generate_images(code, api_key, image_cache):
|
|||||||
return code
|
return code
|
||||||
|
|
||||||
# Generate images
|
# Generate images
|
||||||
results = await process_tasks(prompts, api_key)
|
results = await process_tasks(prompts, api_key, base_url)
|
||||||
|
|
||||||
# Create a dict mapping alt text to image URL
|
# Create a dict mapping alt text to image URL
|
||||||
mapped_image_urls = dict(zip(prompts, results))
|
mapped_image_urls = dict(zip(prompts, results))
|
||||||
|
|||||||
@ -6,9 +6,12 @@ MODEL_GPT_4_VISION = "gpt-4-vision-preview"
|
|||||||
|
|
||||||
|
|
||||||
async def stream_openai_response(
|
async def stream_openai_response(
|
||||||
messages, api_key: str, callback: Callable[[str], Awaitable[None]]
|
messages,
|
||||||
|
api_key: str,
|
||||||
|
base_url: str | None,
|
||||||
|
callback: Callable[[str], Awaitable[None]],
|
||||||
):
|
):
|
||||||
client = AsyncOpenAI(api_key=api_key)
|
client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
||||||
|
|
||||||
model = MODEL_GPT_4_VISION
|
model = MODEL_GPT_4_VISION
|
||||||
|
|
||||||
|
|||||||
@ -111,6 +111,22 @@ async def stream_code(websocket: WebSocket):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Get the OpenAI Base URL from the request. Fall back to environment variable if not provided.
|
||||||
|
openai_base_url = None
|
||||||
|
# Disable user-specified OpenAI Base URL in prod
|
||||||
|
if not os.environ.get("IS_PROD"):
|
||||||
|
if "openAiBaseURL" in params and params["openAiBaseURL"]:
|
||||||
|
openai_base_url = params["openAiBaseURL"]
|
||||||
|
print("Using OpenAI Base URL from client-side settings dialog")
|
||||||
|
else:
|
||||||
|
openai_base_url = os.environ.get("OPENAI_BASE_URL")
|
||||||
|
if openai_base_url:
|
||||||
|
print("Using OpenAI Base URL from environment variable")
|
||||||
|
|
||||||
|
if not openai_base_url:
|
||||||
|
print("Using official OpenAI URL")
|
||||||
|
|
||||||
|
# Get the image generation flag from the request. Fall back to True if not provided.
|
||||||
should_generate_images = (
|
should_generate_images = (
|
||||||
params["isImageGenerationEnabled"]
|
params["isImageGenerationEnabled"]
|
||||||
if "isImageGenerationEnabled" in params
|
if "isImageGenerationEnabled" in params
|
||||||
@ -149,6 +165,7 @@ async def stream_code(websocket: WebSocket):
|
|||||||
completion = await stream_openai_response(
|
completion = await stream_openai_response(
|
||||||
prompt_messages,
|
prompt_messages,
|
||||||
api_key=openai_api_key,
|
api_key=openai_api_key,
|
||||||
|
base_url=openai_base_url,
|
||||||
callback=lambda x: process_chunk(x),
|
callback=lambda x: process_chunk(x),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -161,7 +178,10 @@ async def stream_code(websocket: WebSocket):
|
|||||||
{"type": "status", "value": "Generating images..."}
|
{"type": "status", "value": "Generating images..."}
|
||||||
)
|
)
|
||||||
updated_html = await generate_images(
|
updated_html = await generate_images(
|
||||||
completion, api_key=openai_api_key, image_cache=image_cache
|
completion,
|
||||||
|
api_key=openai_api_key,
|
||||||
|
base_url=openai_base_url,
|
||||||
|
image_cache=image_cache,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
updated_html = completion
|
updated_html = completion
|
||||||
|
|||||||
@ -47,6 +47,7 @@ function App() {
|
|||||||
const [settings, setSettings] = usePersistedState<Settings>(
|
const [settings, setSettings] = usePersistedState<Settings>(
|
||||||
{
|
{
|
||||||
openAiApiKey: null,
|
openAiApiKey: null,
|
||||||
|
openAiBaseURL: null,
|
||||||
screenshotOneApiKey: null,
|
screenshotOneApiKey: null,
|
||||||
isImageGenerationEnabled: true,
|
isImageGenerationEnabled: true,
|
||||||
editorTheme: EditorTheme.COBALT,
|
editorTheme: EditorTheme.COBALT,
|
||||||
|
|||||||
@ -109,6 +109,29 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{!IS_RUNNING_ON_CLOUD && (
|
||||||
|
<>
|
||||||
|
<Label htmlFor="openai-api-key">
|
||||||
|
<div>OpenAI Base URL (optional)</div>
|
||||||
|
<div className="font-light mt-2 leading-relaxed">
|
||||||
|
Replace with a proxy URL if you don't want to use the default.
|
||||||
|
</div>
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id="openai-base-url"
|
||||||
|
placeholder="OpenAI Base URL"
|
||||||
|
value={settings.openAiBaseURL || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSettings((s) => ({
|
||||||
|
...s,
|
||||||
|
openAiBaseURL: e.target.value,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Accordion type="single" collapsible className="w-full">
|
<Accordion type="single" collapsible className="w-full">
|
||||||
<AccordionItem value="item-1">
|
<AccordionItem value="item-1">
|
||||||
<AccordionTrigger>Screenshot by URL Config</AccordionTrigger>
|
<AccordionTrigger>Screenshot by URL Config</AccordionTrigger>
|
||||||
|
|||||||
@ -21,6 +21,7 @@ export interface OutputSettings {
|
|||||||
|
|
||||||
export interface Settings {
|
export interface Settings {
|
||||||
openAiApiKey: string | null;
|
openAiApiKey: string | null;
|
||||||
|
openAiBaseURL: string | null;
|
||||||
screenshotOneApiKey: string | null;
|
screenshotOneApiKey: string | null;
|
||||||
isImageGenerationEnabled: boolean;
|
isImageGenerationEnabled: boolean;
|
||||||
editorTheme: EditorTheme;
|
editorTheme: EditorTheme;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user