-
-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1209 from samchon/feat/chat-bbs
Add a new A.I. chabot example composed by TypeScript controller class instead of HTTP server.
- Loading branch information
Showing
18 changed files
with
362 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta | ||
name="viewport" | ||
content="width=device-width, height=device-height, initial-scale=1, minimum-scale=1.0, maximum-scale=3.0s" | ||
/> | ||
<script type="text/javascript"> | ||
(function(c,l,a,r,i,t,y){ | ||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; | ||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; | ||
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); | ||
})(window, document, "clarity", "script", "gu5qz1srj3"); | ||
</script> | ||
<title>Nestia A.I. Chatbot (TypeScript Class Demonstration)</title> | ||
</head> | ||
<body style="width: 100%; height: 100%; margin: 0px; overflow: hidden;"> | ||
<div id="root" style="width: 100%; height: 100%"></div> | ||
<script type="module" src="../src/html/bbs.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import { | ||
Button, | ||
Divider, | ||
FormControl, | ||
FormControlLabel, | ||
Radio, | ||
RadioGroup, | ||
TextField, | ||
Typography, | ||
} from "@mui/material"; | ||
import { NestiaAgent } from "@nestia/agent"; | ||
import OpenAI from "openai"; | ||
import { useState } from "react"; | ||
import { createRoot } from "react-dom/client"; | ||
import typia from "typia"; | ||
|
||
import { NestiaChatApplication } from "../applications/NestiaChatApplication"; | ||
import { BbsArticleService } from "../services/BbsArticleService"; | ||
|
||
function BbsChatApplication() { | ||
const [apiKey, setApiKey] = useState(""); | ||
const [model, setModel] = useState("gpt-4o-mini"); | ||
const [locale, setLocale] = useState(window.navigator.language); | ||
|
||
const [agent, setAgent] = useState<NestiaAgent | null>(null); | ||
|
||
const startChatApplication = (): void => { | ||
const service: BbsArticleService = new BbsArticleService(); | ||
const agent: NestiaAgent = new NestiaAgent({ | ||
provider: { | ||
type: "chatgpt", | ||
api: new OpenAI({ | ||
apiKey, | ||
dangerouslyAllowBrowser: true, | ||
}), | ||
model: "gpt-4o-mini", | ||
}, | ||
controllers: [ | ||
{ | ||
protocol: "class", | ||
name: "bbs", | ||
application: typia.llm.applicationOfValidate< | ||
BbsArticleService, | ||
"chatgpt" | ||
>(), | ||
execute: async (props) => { | ||
return (service as any)[props.function.name](props.arguments); | ||
}, | ||
}, | ||
], | ||
config: { | ||
locale, | ||
}, | ||
}); | ||
setAgent(agent); | ||
}; | ||
|
||
return ( | ||
<div | ||
style={{ | ||
width: "100%", | ||
height: "100%", | ||
overflow: agent ? undefined : "auto", | ||
}} | ||
> | ||
{agent ? ( | ||
<NestiaChatApplication agent={agent} /> | ||
) : ( | ||
<FormControl | ||
style={{ | ||
width: "calc(100% - 60px)", | ||
padding: 15, | ||
margin: 15, | ||
}} | ||
> | ||
<Typography variant="h6">BBS A.I. Chatbot</Typography> | ||
<br /> | ||
<Divider /> | ||
<br /> | ||
Demonstration of Nestia A.I. Chatbot with TypeScript Controller Class. | ||
<br /> | ||
<br /> | ||
<Typography variant="h6"> OpenAI Configuration </Typography> | ||
<TextField | ||
onChange={(e) => setApiKey(e.target.value)} | ||
defaultValue={apiKey} | ||
label="OpenAI API Key" | ||
variant="outlined" | ||
placeholder="Your OpenAI API Key" | ||
error={apiKey.length === 0} | ||
/> | ||
<br /> | ||
<RadioGroup | ||
defaultValue={model} | ||
onChange={(_e, value) => setModel(value)} | ||
style={{ paddingLeft: 15 }} | ||
> | ||
<FormControlLabel | ||
control={<Radio />} | ||
label="GPT-4o Mini" | ||
value="gpt-4o-mini" | ||
/> | ||
<FormControlLabel | ||
control={<Radio />} | ||
label="GPT-4o" | ||
value="gpt-4o" | ||
/> | ||
</RadioGroup> | ||
<br /> | ||
<Typography variant="h6"> Membership Information </Typography> | ||
<br /> | ||
<TextField | ||
onChange={(e) => setLocale(e.target.value)} | ||
defaultValue={locale} | ||
label="Locale" | ||
variant="outlined" | ||
error={locale.length === 0} | ||
/> | ||
<br /> | ||
<br /> | ||
<Button | ||
component="a" | ||
fullWidth | ||
variant="contained" | ||
color={"info"} | ||
size="large" | ||
disabled={apiKey.length === 0 || locale.length === 0} | ||
onClick={() => startChatApplication()} | ||
> | ||
Start A.I. Chatbot | ||
</Button> | ||
</FormControl> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
const main = async (): Promise<void> => { | ||
createRoot(window.document.getElementById("root")!).render( | ||
<BbsChatApplication />, | ||
); | ||
}; | ||
main().catch(console.error); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
packages/chat/src/main.tsx → packages/chat/src/html/uploader.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { tags } from "typia"; | ||
import { v4 } from "uuid"; | ||
|
||
import { IBbsArticle } from "./IBbsArticle"; | ||
|
||
export class BbsArticleService { | ||
private readonly articles: IBbsArticle[] = []; | ||
|
||
/** | ||
* Create a new article. | ||
* | ||
* Writes a new article and archives it into the DB. | ||
* | ||
* @param props Properties of create function | ||
* @returns Newly created article | ||
*/ | ||
public create(props: { | ||
/** | ||
* Information of the article to create | ||
*/ | ||
input: IBbsArticle.ICreate; | ||
}): IBbsArticle { | ||
const article: IBbsArticle = { | ||
id: v4(), | ||
title: props.input.title, | ||
body: props.input.body, | ||
thumbnail: props.input.thumbnail, | ||
created_at: new Date().toISOString(), | ||
updated_at: new Date().toISOString(), | ||
}; | ||
this.articles.push(article); | ||
return article; | ||
} | ||
|
||
/** | ||
* Update an article. | ||
* | ||
* Updates an article with new content. | ||
* | ||
* @param props Properties of update function | ||
* @param input New content to update | ||
*/ | ||
public update(props: { | ||
/** | ||
* Target article's {@link IBbsArticle.id}. | ||
*/ | ||
id: string & tags.Format<"uuid">; | ||
|
||
/** | ||
* New content to update. | ||
*/ | ||
input: IBbsArticle.IUpdate; | ||
}): void { | ||
const article: IBbsArticle | undefined = this.articles.find( | ||
(a) => a.id === props.id, | ||
); | ||
if (article === undefined) | ||
throw new Error("Unable to find the matched article."); | ||
if (props.input.title !== undefined) article.title = props.input.title; | ||
if (props.input.body !== undefined) article.body = props.input.body; | ||
if (props.input.thumbnail !== undefined) | ||
article.thumbnail = props.input.thumbnail; | ||
article.updated_at = new Date().toISOString(); | ||
} | ||
|
||
/** | ||
* Erase an article. | ||
* | ||
* Erases an article from the DB. | ||
* | ||
* @param props Properties of erase function | ||
*/ | ||
public erase(props: { | ||
/** | ||
* Target article's {@link IBbsArticle.id}. | ||
*/ | ||
id: string & tags.Format<"uuid">; | ||
}): void { | ||
const index: number = this.articles.findIndex((a) => a.id === props.id); | ||
if (index === -1) throw new Error("Unable to find the matched article."); | ||
this.articles.splice(index, 1); | ||
} | ||
} |
Oops, something went wrong.