Skip to content
New issue

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

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

Already on GitHub? # to your account

Complete @nestia/chat #1188

Merged
merged 1 commit into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion packages/agent/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestia/agent",
"version": "0.3.3",
"version": "0.3.5",
"main": "lib/index.js",
"module": "lib/index.mjs",
"typings": "lib/index.d.ts",
Expand Down
19 changes: 19 additions & 0 deletions packages/agent/src/NestiaAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import { NestiaAgentCostAggregator } from "./internal/NestiaAgentCostAggregator"
import { NestiaAgentOperationComposer } from "./internal/NestiaAgentOperationComposer";
import { NestiaAgentPromptTransformer } from "./internal/NestiaAgentPromptTransformer";
import { __map_take } from "./internal/__map_take";
import { INestiaAgentController } from "./structures/INestiaAgentController";
import { INestiaAgentEvent } from "./structures/INestiaAgentEvent";
import { INestiaAgentOperationCollection } from "./structures/INestiaAgentOperationCollection";
import { INestiaAgentOperationSelection } from "./structures/INestiaAgentOperationSelection";
import { INestiaAgentPrompt } from "./structures/INestiaAgentPrompt";
import { INestiaAgentProps } from "./structures/INestiaAgentProps";
import { INestiaAgentProvider } from "./structures/INestiaAgentProvider";
import { INestiaAgentTokenUsage } from "./structures/INestiaAgentTokenUsage";

/**
Expand Down Expand Up @@ -155,6 +157,23 @@ export class NestiaAgent {
return [prompt, ...newbie];
}

/**
* Get LLM Provider.
*/
public getProvider(): INestiaAgentProvider {
return this.props.provider;
}

/**
* Get controllers.
*
* Get list of controllers, which are the collection of functions that
* the "Super A.I. Chatbot" can execute.
*/
public getControllers(): ReadonlyArray<INestiaAgentController> {
return this.props.controllers;
}

/**
* Get the chatbot's prompt histories.
*
Expand Down
2 changes: 1 addition & 1 deletion packages/agent/src/functional/createHttpLlmApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const createHttpLlmApplication = (props: {
| OpenApiV3.IDocument
| OpenApiV3_1.IDocument
| OpenApi.IDocument;
options?: IHttpLlmApplication.IOptions<"chatgpt">;
options?: Partial<IHttpLlmApplication.IOptions<"chatgpt">>;
}): IValidation<IHttpLlmApplication<"chatgpt">> => {
const inspect: IValidation<
| SwaggerV2.IDocument
Expand Down
54 changes: 54 additions & 0 deletions packages/chat/build/publish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const cp = require("child_process");
const fs = require("fs");

const getAgentVersion = async () => {
const packageJson = JSON.parse(
await fs.promises.readFile(
`${__dirname}/../../agent/package.json`,
"utf-8",
),
);
return packageJson.version;
};

const main = async () => {
const agent = await getAgentVersion();
const packageJson = JSON.parse(
await fs.promises.readFile(`${__dirname}/../package.json`, "utf8"),
);
const tag = packageJson.version.includes("dev") ? "next" : "latest";

await fs.promises.writeFile(
`${__dirname}/../package.json`,
JSON.stringify(
{
...packageJson,
dependencies: {
...packageJson.dependencies,
"@nestia/agent": `^${agent}`,
},
},
null,
2,
),
"utf8",
);

const execute = (str) =>
cp.execSync(str, {
cwd: `${__dirname}/..`,
stdio: "inherit",
});
execute("npm run build");
execute(`npm publish --tag ${tag}`);

await fs.promises.writeFile(
`${__dirname}/../package.json`,
JSON.stringify(packageJson, null, 2),
"utf8",
);
};
main().catch((error) => {
console.log(error);
process.exit(-1);
});
20 changes: 14 additions & 6 deletions packages/chat/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestia/chat",
"version": "0.2.1",
"version": "0.1.0",
"main": "lib/index.js",
"module": "lib/index.mjs",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -36,12 +36,18 @@
"dependencies": {
"@mui/icons-material": "^6.3.1",
"@mui/material": "^5.15.6",
"@nestia/agent": "workspace:^",
"@samchon/openapi": "^2.3.2",
"@nestia/agent": "^0.3.4",
"@samchon/openapi": "^2.3.4",
"html2canvas": "^1.4.1",
"js-file-download": "^0.4.12",
"js-yaml": "^4.1.0",
"prettier": "3.3.3",
"react-json-editor-ajrm": "^2.5.14",
"react-markdown": "^9.0.3",
"react-mui-fileuploader": "^0.5.2",
"rehype-raw": "^7.0.0",
"rehype-stringify": "^10.0.1",
"remark-mermaid-plugin": "^1.0.2",
"typia": "^7.5.1"
},
"devDependencies": {
Expand All @@ -54,15 +60,16 @@
"@rollup/plugin-typescript": "^12.1.1",
"@samchon/shopping-api": "^0.11.0",
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.8.6",
"@types/node": "^22.10.5",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"@types/react-json-editor-ajrm": "^2.5.6",
"@vitejs/plugin-react": "^4.3.3",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.13",
"globals": "^15.11.0",
"openai": "^4.77.0",
"openai": "^4.77.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rollup": "^4.24.2",
Expand All @@ -77,6 +84,7 @@
"package.json",
"dist",
"lib",
"src"
"src",
"!src/test.ts"
]
}
158 changes: 153 additions & 5 deletions packages/chat/src/NestiaChatUploader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,158 @@
import { IChatGptService } from "@nestia/agent";
import { IHttpConnection } from "@samchon/openapi";
import {
Button,
FormControl,
FormControlLabel,
FormLabel,
Radio,
RadioGroup,
TextField,
Typography,
} from "@mui/material";
import { INestiaAgentProvider, NestiaAgent } from "@nestia/agent";
import { IHttpLlmApplication } from "@samchon/openapi";
import OpenAI from "openai";
import React, { useState } from "react";
import JsonInput from "react-json-editor-ajrm";
// @ts-ignore
import locale from "react-json-editor-ajrm/locale/en";

export const NestiaChatUploader = () => {};
import { NestiaChatApplication } from "./NestiaChatApplication";
import { NestiaChatFileUploadMovie } from "./movies/uploader/NestiaChatFileUploadMovie";

export const NestiaChatUploader = (props: NestiaChatUploader.IProps) => {
// PARAMETERS
const [host, setHost] = useState("http://localhost:37001");
const [headers, setHeaders] = useState<Record<string, string>>({
Authorization: "YOUR_SERVER_API_KEY",
});
const [model, setModel] = useState("gpt-4o");
const [apiKey, setApiKey] = useState("YOUR-OPENAI-API-KEY");

// RESULT
const [application, setApplication] =
useState<IHttpLlmApplication<"chatgpt"> | null>(null);
const [progress, setProgress] = useState(false);

// HANDLERS
const handleApplication = (
application: IHttpLlmApplication<"chatgpt"> | null,
error: string | null,
) => {
setApplication(application);
if (error !== null) handleError(error);
};
const handleError = (error: string) => {
if (props.onError) props.onError(error);
else alert(error);
};

const open = async () => {
if (application === null) return;
setProgress(true);
try {
const provider: INestiaAgentProvider = {
type: "chatgpt",
api: new OpenAI({
apiKey,
dangerouslyAllowBrowser: true,
}),
model: model as "gpt-4o",
};
const agent: NestiaAgent = new NestiaAgent({
provider,
controllers: [
{
protocol: "http",
name: "main",
application,
connection: {
host,
headers,
},
},
],
});
props.onSuccess(<NestiaChatApplication agent={agent} />);
} catch (error) {
handleError(error instanceof Error ? error.message : "unknown error");
setProgress(false);
}
};

return (
<React.Fragment>
<NestiaChatFileUploadMovie onChange={handleApplication} />
<br />
<FormControl fullWidth style={{ paddingLeft: 15 }}>
<Typography variant="h6">HTTP Connection</Typography>
<br />
<TextField
onChange={(e) => setHost(e.target.value)}
defaultValue={host}
label="Host URL"
variant="outlined"
/>
<br />
<FormLabel> Headers </FormLabel>
<JsonInput
locale={locale}
theme="dark_vscode_tribute"
placeholder={headers}
onChange={setHeaders}
height="100px"
/>
<br />
<br />
<Typography variant="h6">LLM Arguments</Typography>
<br />
<FormLabel> LLM Provider </FormLabel>
<RadioGroup defaultValue={"chatgpt"} style={{ paddingLeft: 15 }}>
<FormControlLabel
value="chatgpt"
control={<Radio />}
label="OpenAI (ChatGPT)"
/>
</RadioGroup>
<FormLabel style={{ paddingTop: 20 }}> OpenAI Model </FormLabel>
<RadioGroup
defaultValue={model}
onChange={(_e, value) => setModel(value)}
style={{ paddingLeft: 15 }}
>
<FormControlLabel value="gpt-4o" control={<Radio />} label="GPT-4o" />
<FormControlLabel
value="gpt-4o-mini"
control={<Radio />}
label="GPT-4o Mini"
/>
</RadioGroup>
<br />
<TextField
onChange={(e) => setApiKey(e.target.value)}
defaultValue={apiKey}
label="OpenAI API Key"
variant="outlined"
/>
</FormControl>
<br />
<br />
<Button
component="a"
fullWidth
variant="contained"
color={"info"}
size="large"
disabled={progress === true || document === null}
onClick={() => open()}
>
{progress ? "Generating..." : "Generate Editor"}
</Button>
</React.Fragment>
);
};
export namespace NestiaChatUploader {
export interface IProps {
connection?: IHttpConnection;
service?: IChatGptService;
onError?: (error: string) => void;
onSuccess: (element: JSX.Element) => void;
}
}
20 changes: 20 additions & 0 deletions packages/chat/src/components/MarkdownViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Markdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import rehypeStringify from "rehype-stringify";
import remarkMermaidPlugin from "remark-mermaid-plugin";

export const MarkdownViewer = (props: MarkdownViewer.IProps) => {
return (
<Markdown
remarkPlugins={[remarkMermaidPlugin as any]}
rehypePlugins={[rehypeRaw, rehypeStringify]}
>
{props.children}
</Markdown>
);
};
export namespace MarkdownViewer {
export interface IProps {
children: string | null | undefined;
}
}
2 changes: 2 additions & 0 deletions packages/chat/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./NestiaChatApplication";
export * from "./NestiaChatUploader";
Loading
Loading