Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for DALL-E #1358 #1428

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
36adfe8
fix: #1401 try to disable zoom
Yidadaa May 11, 2023
09feeea
Add support for DALL-E #1358
SPWwj May 11, 2023
c49dbab
Merge pull request #1431 from Yidadaa/bugfix-0511
Yidadaa May 11, 2023
377579e
Update README.md
Yidadaa May 12, 2023
93c9974
feat: scrolling effect when switching chat windows
wsw2000 May 12, 2023
170936a
fix: the theme-color selector
yorunning May 12, 2023
dd5604f
style: move nextjs supported meta tags to metadata
yorunning May 12, 2023
dc3fa6c
Update settings.tsx
PaRaD1SE98 May 12, 2023
a0e192b
fix: show Vitenamese in it's own language
yanCode May 12, 2023
f07e4fc
docs: add supported languages to README.md
yanCode May 13, 2023
e2be9ae
Add Setting to imageModel
SPWwj May 13, 2023
5b9b120
增加文生图面具
InitialXKO May 13, 2023
f7edac9
Merge pull request #1456 from yanCode/fix/doc
Yidadaa May 13, 2023
b22988e
Merge pull request #1459 from InitialXKO/patch-1
Yidadaa May 13, 2023
6bb0166
Merge pull request #1454 from yanCode/fix/i18n
Yidadaa May 13, 2023
330504b
Merge pull request #1446 from wsw2000/feat/switchWindowScrollIntoView
Yidadaa May 13, 2023
1a626a6
Merge pull request #1450 from yorunning/fix-1
Yidadaa May 13, 2023
d9be63e
Merge pull request #1452 from PaRaD1SE98/main
Yidadaa May 13, 2023
dec19d6
Fix missing Locale image properties
SPWwj May 13, 2023
3e8fad0
Add support for DALL-E #1358
SPWwj May 11, 2023
2a7edc8
Add Setting to imageModel
SPWwj May 13, 2023
8608d2d
Fix missing Locale image properties
SPWwj May 13, 2023
36ddd84
Merge branch 'feature/dalle-support-1358' of https://github.com/Whale…
SPWwj May 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ One-Click to deploy well-designed ChatGPT web UI on Vercel.
- New in v2: create, share and debug your chat tools with prompt templates (mask)
- Awesome prompts powered by [awesome-chatgpt-prompts-zh](https://github.com/PlexPt/awesome-chatgpt-prompts-zh) and [awesome-chatgpt-prompts](https://github.com/f/awesome-chatgpt-prompts)
- Automatically compresses chat history to support long conversations while also saving your tokens
- I18n: English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch
- I18n: English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch, Tiếng Việt, Русский, Čeština

## Roadmap

Expand Down Expand Up @@ -62,7 +62,7 @@ One-Click to deploy well-designed ChatGPT web UI on Vercel.
- 预制角色功能(面具),方便地创建、分享和调试你的个性化对话
- 海量的内置 prompt 列表,来自[中文](https://github.com/PlexPt/awesome-chatgpt-prompts-zh)和[英文](https://github.com/f/awesome-chatgpt-prompts)
- 自动压缩上下文聊天记录,在节省 Token 的同时支持超长对话
- 多国语言支持:English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch
- 多国语言支持:English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch, Tiếng Việt, Русский, Čeština
- 拥有自己的域名?好上加好,绑定后即可在任何地方**无障碍**快速访问

## 开发计划
Expand Down Expand Up @@ -265,6 +265,7 @@ bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/s
[@jhansion](https://github.com/jhansion)
[@Sha1rholder](https://github.com/Sha1rholder)
[@AnsonHyq](https://github.com/AnsonHyq)
[@synwith](https://github.com/synwith)

### Contributor

Expand Down
3 changes: 2 additions & 1 deletion app/api/openai/typing.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type {
CreateChatCompletionRequest,
CreateChatCompletionResponse,
CreateImageRequestSizeEnum,
} from "openai";

export type ChatRequest = CreateChatCompletionRequest;
export type ChatResponse = CreateChatCompletionResponse;

export type ImageRequestSizeEnum = CreateImageRequestSizeEnum;
export type Updater<T> = (updater: (value: T) => void) => void;
16 changes: 16 additions & 0 deletions app/components/ImageList.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.imageGrid,
.imageGridSingle {
display: inline-flex;
flex-wrap: wrap;
justify-content: flex-start;
}

.imageGrid img {
max-width: calc(50% - 10px);
margin: 5px;
}

.imageGridSingle img {
max-width: 100%;
margin: 5px;
}
20 changes: 20 additions & 0 deletions app/components/ImageList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ImagesResponseDataInner } from "openai";
import React, { FC } from "react";
import styles from "./imageList.module.scss";

interface ImageListProps {
images?: ImagesResponseDataInner[];
}
const ImageList: FC<ImageListProps> = ({ images }) => {
const singleImage = images && images.length === 1;

return (
<div className={singleImage ? styles.imageGridSingle : styles.imageGrid}>
{images &&
images.map((image, index) => (
<img key={index} src={image.url} alt={`Image ${index}`} />
))}
</div>
);
};
export default ImageList;
14 changes: 13 additions & 1 deletion app/components/chat-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Link, useNavigate } from "react-router-dom";
import { Path } from "../constant";
import { MaskAvatar } from "./mask";
import { Mask } from "../store/mask";
import { useRef, useEffect } from "react";

export function ChatItem(props: {
onClick?: () => void;
Expand All @@ -29,6 +30,14 @@ export function ChatItem(props: {
narrow?: boolean;
mask: Mask;
}) {
const draggableRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (props.selected && draggableRef.current) {
draggableRef.current?.scrollIntoView({
block: "center",
});
}
}, [props.selected]);
return (
<Draggable draggableId={`${props.id}`} index={props.index}>
{(provided) => (
Expand All @@ -37,7 +46,10 @@ export function ChatItem(props: {
props.selected && styles["chat-item-selected"]
}`}
onClick={props.onClick}
ref={provided.innerRef}
ref={(ele) => {
draggableRef.current = ele;
provided.innerRef(ele);
}}
{...provided.draggableProps}
{...provided.dragHandleProps}
title={`${props.title}\n${Locale.ChatItem.ChatItemCount(
Expand Down
7 changes: 4 additions & 3 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
Message,
SubmitKey,
useChatStore,
BOT_HELLO,
createMessage,
useAccessStore,
Theme,
Expand Down Expand Up @@ -560,9 +559,9 @@ export function Chat() {

if (
context.length === 0 &&
session.messages.at(0)?.content !== BOT_HELLO.content
session.messages.at(0)?.content !== session.botHello.content
) {
const copiedHello = Object.assign({}, BOT_HELLO);
const copiedHello = Object.assign({}, session.botHello);
if (!accessStore.isAuthorized()) {
copiedHello.content = Locale.Error.Unauthorized;
}
Expand Down Expand Up @@ -760,6 +759,8 @@ export function Chat() {
)}
<Markdown
content={message.content}
images={message.images}
image_alt={message.image_alt}
loading={
(message.preview || message.content.length === 0) &&
!isUser
Expand Down
6 changes: 3 additions & 3 deletions app/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,17 @@ export function useSwitchTheme() {
}

const metaDescriptionDark = document.querySelector(
'meta[name="theme-color"][media]',
'meta[name="theme-color"][media*="dark"]',
);
const metaDescriptionLight = document.querySelector(
'meta[name="theme-color"]:not([media])',
'meta[name="theme-color"][media*="light"]',
);

if (config.theme === "auto") {
metaDescriptionDark?.setAttribute("content", "#151515");
metaDescriptionLight?.setAttribute("content", "#fafafa");
} else {
const themeColor = getCSSVar("--themeColor");
const themeColor = getCSSVar("--theme-color");
metaDescriptionDark?.setAttribute("content", themeColor);
metaDescriptionLight?.setAttribute("content", themeColor);
}
Expand Down
74 changes: 74 additions & 0 deletions app/components/image-model-config.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
ALL_MODELS,
ImageModalConfigValidator,
ImageModelConfig,
ModalConfigValidator,
ModelConfig,
} from "../store";

import Locale from "../locales";
import { InputRange } from "./input-range";
import { Input, List, ListItem, Select } from "./ui-lib";
import { ImageRequestSizeEnum } from "../api/openai/typing";
import { CreateImageRequestSizeEnum } from "openai";

export function ImageModelConfigList(props: {
imageModelConfig: ImageModelConfig;
updateConfig: (updater: (config: ImageModelConfig) => void) => void;
}) {
return (
<>
<ListItem title={Locale.Settings.ImageModel.Title}>
<input value={Locale.Settings.ImageModel.Model} disabled={true} />
</ListItem>
<ListItem title={Locale.Settings.ImageModel.Command}>
<input
value={props.imageModelConfig.command}
onChange={(e) => {
props.updateConfig((config) => {
config.command = e.currentTarget.value; // Assign the parsed value
return config;
});
}}
/>
</ListItem>
<ListItem title={Locale.Settings.ImageModel.NoOfImage}>
<InputRange
value={props.imageModelConfig.noOfImage.toString()} // Keep the value as a string
onChange={(e) => {
const newValue = parseInt(e.currentTarget.value, 10); // Parse the value as an integer
if (!isNaN(newValue)) {
props.updateConfig((config) => {
config.noOfImage = newValue; // Assign the parsed value
return config;
});
}
}}
min={"1"} // Convert the min value to a string
max={"10"} // Convert the max value to a string
step={"1"} // Convert the step value to a string
/>
</ListItem>
<ListItem title={Locale.Settings.ImageModel.Size}>
<Select
value={props.imageModelConfig.size}
onChange={(e) => {
const newSize = ImageModalConfigValidator.size(
e.currentTarget.value,
);
props.updateConfig((config) => {
config.size = newSize;
return config;
});
}}
>
{Object.values(CreateImageRequestSizeEnum).map((v) => (
<option value={v} key={v}>
{v}
</option>
))}
</Select>
</ListItem>
</>
);
}
29 changes: 26 additions & 3 deletions app/components/markdown.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import styles from "./markdown.tsx.module.scss";

import ReactMarkdown from "react-markdown";
import "katex/dist/katex.min.css";
import RemarkMath from "remark-math";
Expand All @@ -11,7 +13,11 @@ import mermaid from "mermaid";

import LoadingIcon from "../icons/three-dots.svg";
import React from "react";

import ImagePlaceHolder from "../icons/image-placeholder.svg";
import ImageError from "../icons/image-error.svg";
import { IMAGE_PLACEHOLDER } from "../constant";
import { ImagesResponseDataInner } from "openai";
import ImageList from "./imageList";
export function Mermaid(props: { code: string; onError: () => void }) {
const ref = useRef<HTMLDivElement>(null);

Expand Down Expand Up @@ -119,6 +125,8 @@ export const MarkdownContent = React.memo(_MarkDownContent);
export function Markdown(
props: {
content: string;
images?: ImagesResponseDataInner[];
image_alt?: string;
loading?: boolean;
fontSize?: number;
parentRef: RefObject<HTMLDivElement>;
Expand Down Expand Up @@ -171,9 +179,24 @@ export function Markdown(
>
{inView.current &&
(props.loading ? (
<LoadingIcon />
<div className={styles.loader}>
{props.image_alt && <MarkdownContent content={props.image_alt} />}
{props.image_alt &&
(props.image_alt === IMAGE_PLACEHOLDER ? (
<ImagePlaceHolder width="100px" height="100px" />
) : (
<ImageError width="100px" height="100px" />
))}
<LoadingIcon />
</div>
) : (
<MarkdownContent content={props.content} />
<div>
<MarkdownContent content={props.content} />
<div className={styles.content_image}>
{props.images && <ImageList images={props.images} />}
{props.image_alt && <ImageError width="100px" height="100px" />}
</div>
</div>
))}
</div>
);
Expand Down
10 changes: 10 additions & 0 deletions app/components/markdown.tsx.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.loader {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%; // Adjust as necessary
}
.content_image {
text-align: center;
}
17 changes: 15 additions & 2 deletions app/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { ErrorBoundary } from "./error";
import { InputRange } from "./input-range";
import { useNavigate } from "react-router-dom";
import { Avatar, AvatarPicker } from "./emoji";
import { ImageModelConfigList } from "./image-model-config";

function EditPromptModal(props: { id: number; onClose: () => void }) {
const promptStore = usePromptStore();
Expand Down Expand Up @@ -573,13 +574,25 @@ export function Settings() {
<List>
<ModelConfigList
modelConfig={config.modelConfig}
updateConfig={(upater) => {
updateConfig={(updater) => {
const modelConfig = { ...config.modelConfig };
upater(modelConfig);
updater(modelConfig);
config.update((config) => (config.modelConfig = modelConfig));
}}
/>
</List>
<List>
<ImageModelConfigList
imageModelConfig={config.imageModelConfig}
updateConfig={(upater) => {
const imageModelConfig = { ...config.imageModelConfig };
upater(imageModelConfig);
config.update(
(config) => (config.imageModelConfig = imageModelConfig),
);
}}
/>
</List>

{shouldShowPromptModal && (
<UserPromptModal onClose={() => setShowPromptModal(false)} />
Expand Down
3 changes: 3 additions & 0 deletions app/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ export const NARROW_SIDEBAR_WIDTH = 100;
export const ACCESS_CODE_PREFIX = "ak-";

export const LAST_INPUT_KEY = "last-input";
export const IMAGE_PLACEHOLDER = "Loading your image...";
export const IMAGE_ERROR = "IMAGE_ERROR";
export const COMMAND_IMAGE = "/image";
33 changes: 33 additions & 0 deletions app/icons/image-error.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading