├── public ├── logo.png ├── bytebard.png ├── favicon.ico ├── openbb_logo.jpg ├── robots.txt ├── gptstonks_logo.png ├── gptstonks_tview.png ├── logo_oblongo_light.jpg ├── openbb_x_gptstonks.png ├── gptstonks_logo_small.png ├── gptstonks_chatbot_open_source.png └── bytebard.svg ├── .dockerignore ├── out ├── src │ ├── app │ │ ├── page.d.ts │ │ ├── streaming │ │ │ ├── page.d.ts │ │ │ ├── test │ │ │ │ ├── Loading.d.ts │ │ │ │ └── Loading.js │ │ │ ├── CustomRenderers.d.ts │ │ │ ├── CustomRenderers.js │ │ │ └── page.js │ │ ├── websocket │ │ │ ├── page.d.ts │ │ │ └── page.js │ │ ├── layout.d.ts │ │ ├── layout.js │ │ └── page.js │ ├── types │ │ ├── styles.js │ │ ├── chatbot.js │ │ ├── component.js │ │ ├── message.js │ │ ├── message.d.ts │ │ ├── component.d.ts │ │ ├── styles.d.ts │ │ └── chatbot.d.ts │ ├── components │ │ ├── chat │ │ │ ├── LinearBuffer.d.ts │ │ │ ├── ChatbotDefaultTheme.d.ts │ │ │ ├── GptstonksChatbotTheme.d.ts │ │ │ ├── ChatbotInput.d.ts │ │ │ ├── ChatbotCore.d.ts │ │ │ ├── LinearBuffer.js │ │ │ ├── ChatbotInput.js │ │ │ ├── GptstonksChatbotTheme.js │ │ │ └── ChatbotDefaultTheme.js │ │ └── renderers │ │ │ ├── DefaultRenderers.d.ts │ │ │ ├── RenderFunctions.d.ts │ │ │ ├── DefaultRenderers.js │ │ │ └── RenderFunctions.js │ ├── layouts │ │ ├── ChatbotHttp.d.ts │ │ ├── ChatbotWebsocket.d.ts │ │ └── ChatbotWebsocketStreaming.d.ts │ ├── hooks │ │ ├── useChatSocket.d.ts │ │ └── useChatSocket.js │ ├── index.d.ts │ └── index.js ├── tailwind.config.d.ts └── tailwind.config.js ├── api ├── models │ └── query.py ├── routers │ ├── ws.py │ └── http.py ├── main.py ├── dependencies.py └── utils │ └── phrases.py ├── next.config.mjs ├── postcss.config.js ├── .eslintrc.json ├── docs ├── assets │ ├── fonts │ │ ├── EOT │ │ │ ├── SourceCodePro-Bold.eot │ │ │ └── SourceCodePro-Regular.eot │ │ ├── OTF │ │ │ ├── SourceCodePro-Bold.otf │ │ │ └── SourceCodePro-Regular.otf │ │ ├── TTF │ │ │ ├── SourceCodePro-Bold.ttf │ │ │ └── SourceCodePro-Regular.ttf │ │ ├── WOFF │ │ │ ├── OTF │ │ │ │ ├── SourceCodePro-Bold.otf.woff │ │ │ │ └── SourceCodePro-Regular.otf.woff │ │ │ └── TTF │ │ │ │ ├── SourceCodePro-Bold.ttf.woff │ │ │ │ └── SourceCodePro-Regular.ttf.woff │ │ ├── WOFF2 │ │ │ ├── OTF │ │ │ │ ├── SourceCodePro-Bold.otf.woff2 │ │ │ │ └── SourceCodePro-Regular.otf.woff2 │ │ │ └── TTF │ │ │ │ ├── SourceCodePro-Bold.ttf.woff2 │ │ │ │ └── SourceCodePro-Regular.ttf.woff2 │ │ ├── source-code-pro.css │ │ └── LICENSE.txt │ ├── bass-addons.css │ ├── split.css │ ├── github.css │ ├── style.css │ └── site.js └── index.html ├── precompiler.sh ├── .husky └── pre-commit ├── .npmignore ├── src ├── types │ ├── message.ts │ ├── component.ts │ ├── styles.ts │ └── chatbot.ts ├── tests │ └── Test.js ├── app │ ├── layout.tsx │ ├── streaming │ │ ├── test │ │ │ ├── styles.css │ │ │ └── Loading.jsx │ │ ├── CustomRenderers.tsx │ │ └── page.tsx │ ├── globals.css │ ├── page.tsx │ └── websocket │ │ └── page.tsx ├── index.ts ├── components │ ├── chat │ │ ├── LinearBuffer.tsx │ │ ├── ChatbotInput.tsx │ │ ├── GptstonksChatbotTheme.ts │ │ ├── ChatbotDefaultTheme.ts │ │ └── ChatbotCore.tsx │ └── renderers │ │ ├── DefaultRenderers.tsx │ │ └── RenderFunctions.tsx ├── hooks │ └── useChatSocket.ts └── layouts │ ├── ChatbotHttp.tsx │ └── ChatbotWebsocket.tsx ├── .prettierrc ├── Dockerfile.local ├── .github ├── workflows │ ├── npm-lint.yml │ ├── npm-audit.yml │ ├── release.yml │ └── node-test.yml ├── dependabot.yml └── PULL_REQUEST_TEMPLATE.md ├── Dockerfile ├── tailwind.config.ts ├── .gitignore ├── tsconfig.json ├── LICENSE └── package.json /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/logo.png -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | .git 5 | .gitignore 6 | -------------------------------------------------------------------------------- /public/bytebard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/bytebard.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/openbb_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/openbb_logo.jpg -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/gptstonks_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/gptstonks_logo.png -------------------------------------------------------------------------------- /out/src/app/page.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export default function Home(): React.JSX.Element; 3 | -------------------------------------------------------------------------------- /out/src/types/styles.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /public/gptstonks_tview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/gptstonks_tview.png -------------------------------------------------------------------------------- /api/models/query.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class QueryParams(BaseModel): 4 | query: str 5 | -------------------------------------------------------------------------------- /out/src/types/chatbot.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /out/src/types/component.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /out/src/types/message.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /public/logo_oblongo_light.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/logo_oblongo_light.jpg -------------------------------------------------------------------------------- /public/openbb_x_gptstonks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/openbb_x_gptstonks.png -------------------------------------------------------------------------------- /out/src/app/streaming/page.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export default function Home(): React.JSX.Element; 3 | -------------------------------------------------------------------------------- /out/src/app/websocket/page.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export default function Home(): React.JSX.Element; 3 | -------------------------------------------------------------------------------- /public/gptstonks_logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/gptstonks_logo_small.png -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /out/tailwind.config.d.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | declare const config: Config; 3 | export default config; 4 | -------------------------------------------------------------------------------- /public/gptstonks_chatbot_open_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/public/gptstonks_chatbot_open_source.png -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "react-hooks/exhaustive-deps": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /out/src/app/streaming/test/Loading.d.ts: -------------------------------------------------------------------------------- 1 | export default function SubqueryComponent(): React.JSX.Element; 2 | import React from "react"; 3 | -------------------------------------------------------------------------------- /docs/assets/fonts/EOT/SourceCodePro-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/EOT/SourceCodePro-Bold.eot -------------------------------------------------------------------------------- /docs/assets/fonts/OTF/SourceCodePro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/OTF/SourceCodePro-Bold.otf -------------------------------------------------------------------------------- /docs/assets/fonts/TTF/SourceCodePro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf -------------------------------------------------------------------------------- /out/src/components/chat/LinearBuffer.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | export default function LinearBuffer(): React.JSX.Element; 3 | -------------------------------------------------------------------------------- /docs/assets/fonts/EOT/SourceCodePro-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/EOT/SourceCodePro-Regular.eot -------------------------------------------------------------------------------- /docs/assets/fonts/OTF/SourceCodePro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/OTF/SourceCodePro-Regular.otf -------------------------------------------------------------------------------- /docs/assets/fonts/TTF/SourceCodePro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf -------------------------------------------------------------------------------- /precompiler.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is used to precompile the source code of the project into out/ folder. 4 | 5 | rm -rf out/ 6 | tsc -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | npx prettier --write "src/**/*.{js,jsx,ts,tsx,json,css,scss,md} -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPTStonks/chatbot/HEAD/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 -------------------------------------------------------------------------------- /out/src/components/chat/ChatbotDefaultTheme.d.ts: -------------------------------------------------------------------------------- 1 | import { ThemeConfig } from '@/types/chatbot'; 2 | declare const useChatbotDefaultTheme: ThemeConfig; 3 | export default useChatbotDefaultTheme; 4 | -------------------------------------------------------------------------------- /out/src/components/chat/GptstonksChatbotTheme.d.ts: -------------------------------------------------------------------------------- 1 | import { ThemeConfig } from '@/types/chatbot'; 2 | declare const useGptstonksChatbotTheme: ThemeConfig; 3 | export default useGptstonksChatbotTheme; 4 | -------------------------------------------------------------------------------- /out/src/layouts/ChatbotHttp.d.ts: -------------------------------------------------------------------------------- 1 | import { ChatbotProps } from '@/types/chatbot'; 2 | import React from 'react'; 3 | declare const ChatbotHttp: React.FC; 4 | export default ChatbotHttp; 5 | -------------------------------------------------------------------------------- /out/src/layouts/ChatbotWebsocket.d.ts: -------------------------------------------------------------------------------- 1 | import { ChatbotProps } from '@/types/chatbot'; 2 | import React from 'react'; 3 | declare const ChatbotWebsocket: React.FC; 4 | export default ChatbotWebsocket; 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | tests 3 | .env 4 | .dockerignore 5 | .husky/ 6 | docs/ 7 | public/ 8 | Dockerfile* 9 | api_example.py 10 | .github/ 11 | gptstonks-test-package/ 12 | npm_package_test/ 13 | __pycache__/ 14 | .next/ 15 | -------------------------------------------------------------------------------- /out/src/hooks/useChatSocket.d.ts: -------------------------------------------------------------------------------- 1 | declare const useChatSocket: (url: string) => { 2 | sendMessage: (newMessage: string) => void; 3 | lastMessage: any; 4 | connectionStatus: string; 5 | eventReason: string | null; 6 | }; 7 | export default useChatSocket; 8 | -------------------------------------------------------------------------------- /out/src/app/layout.d.ts: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next'; 2 | import './globals.css'; 3 | import React from 'react'; 4 | export declare const metadata: Metadata; 5 | export default function RootLayout({ children, }: Readonly<{ 6 | children: React.ReactNode; 7 | }>): React.JSX.Element; 8 | -------------------------------------------------------------------------------- /docs/assets/bass-addons.css: -------------------------------------------------------------------------------- 1 | .input { 2 | font-family: inherit; 3 | display: block; 4 | width: 100%; 5 | height: 2rem; 6 | padding: 0.5rem; 7 | margin-bottom: 1rem; 8 | border: 1px solid #ccc; 9 | font-size: 0.875rem; 10 | border-radius: 3px; 11 | box-sizing: border-box; 12 | } 13 | -------------------------------------------------------------------------------- /src/types/message.ts: -------------------------------------------------------------------------------- 1 | export interface Message { 2 | text: string; 3 | user: string; 4 | loading?: boolean; 5 | graphData?: any; 6 | related?: string[]; 7 | reference?: string[]; 8 | providers?: string[]; 9 | subqueryQuestion?: string[]; 10 | subqueryResponse?: string[]; 11 | stream?: boolean; 12 | streamCompleted?: boolean; 13 | } 14 | -------------------------------------------------------------------------------- /out/src/types/message.d.ts: -------------------------------------------------------------------------------- 1 | export interface Message { 2 | text: string; 3 | user: string; 4 | loading?: boolean; 5 | graphData?: any; 6 | related?: string[]; 7 | reference?: string[]; 8 | providers?: string[]; 9 | subqueryQuestion?: string[]; 10 | subqueryResponse?: string[]; 11 | stream?: boolean; 12 | streamCompleted?: boolean; 13 | } 14 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "trailingComma": "all", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": false, 10 | "arrowParens": "always", 11 | "proseWrap": "always", 12 | "htmlWhitespaceSensitivity": "strict", 13 | "endOfLine": "lf" 14 | } 15 | -------------------------------------------------------------------------------- /out/src/layouts/ChatbotWebsocketStreaming.d.ts: -------------------------------------------------------------------------------- 1 | import { ChatbotProps } from '@/types/chatbot'; 2 | import React from 'react'; 3 | declare const ChatbotWebsocketStreaming: React.ForwardRefExoticComponent< 4 | ChatbotProps & 5 | React.RefAttributes<{ 6 | handleSendCustomMessage: (message: string) => void; 7 | }> 8 | >; 9 | export default ChatbotWebsocketStreaming; 10 | -------------------------------------------------------------------------------- /Dockerfile.local: -------------------------------------------------------------------------------- 1 | # Image made not by cloning the repository, but by local files 2 | FROM node:latest AS build-stage 3 | WORKDIR /app 4 | COPY . /app/front-end 5 | WORKDIR /app/front-end 6 | RUN npm install --force && \ 7 | npm run build 8 | 9 | FROM nginx:alpine 10 | COPY --from=build-stage /app/front-end/build /usr/share/nginx/html 11 | EXPOSE 80 12 | CMD ["nginx", "-g", "daemon off;"] 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/npm-lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint Code 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: '21.0.0' 17 | - run: npm install 18 | - run: npm run lint 19 | -------------------------------------------------------------------------------- /.github/workflows/npm-audit.yml: -------------------------------------------------------------------------------- 1 | name: Check for Vulnerable Dependencies 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | security: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: '21.0.0' 17 | - run: npm ci 18 | - run: npm audit 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Image for Github Actions workflows to build and deploy the front-end image 2 | FROM node:latest AS build-stage 3 | WORKDIR /app 4 | RUN git clone https://github.com/GPTStonks/front-end.git front-end 5 | WORKDIR /app/front-end 6 | RUN npm install --force && \ 7 | npm run build 8 | 9 | FROM nginx:alpine 10 | COPY --from=build-stage /app/front-end/build /usr/share/nginx/html 11 | EXPOSE 80 12 | CMD ["nginx", "-g", "daemon off;"] 13 | 14 | -------------------------------------------------------------------------------- /src/tests/Test.js: -------------------------------------------------------------------------------- 1 | import Chatbot from '@/components/chat/Chatbot'; 2 | import { useChatbotDefaultTheme } from './chatbot'; 3 | 4 | export const Test = () => { 5 | return ( 6 | 15 | ); 16 | }; 17 | export default Test; 18 | -------------------------------------------------------------------------------- /api/routers/ws.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, WebSocket, WebSocketDisconnect 2 | from ..dependencies import manager 3 | 4 | router = APIRouter() 5 | 6 | @router.websocket("/chatws") 7 | async def chat_websocket(websocket: WebSocket): 8 | await manager.connect(websocket) 9 | try: 10 | while True: 11 | await websocket.receive_text() 12 | await manager.send_random_messages(websocket) 13 | except WebSocketDisconnect: 14 | manager.disconnect(websocket) 15 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npmjs 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: actions/setup-node@v4 11 | with: 12 | node-version: lts/* 13 | registry-url: 'https://registry.npmjs.org' 14 | - run: npm clean-install 15 | - run: npm publish 16 | env: 17 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 18 | -------------------------------------------------------------------------------- /api/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.middleware.cors import CORSMiddleware 3 | from .routers import http as http_router 4 | from .routers import ws as ws_router 5 | 6 | app = FastAPI() 7 | 8 | app.add_middleware( 9 | CORSMiddleware, 10 | allow_origins=["http://localhost:3000", "http://localhost:3001"], 11 | allow_credentials=True, 12 | allow_methods=["*"], 13 | allow_headers=["*"], 14 | ) 15 | 16 | app.include_router(http_router.router) 17 | app.include_router(ws_router.router) 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/node-test.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [21.0.0] 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: npm ci 24 | - run: npm run build 25 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next'; 2 | import { Inter } from 'next/font/google'; 3 | import './globals.css'; 4 | import React from 'react'; 5 | 6 | const inter = Inter({ subsets: ['latin'] }); 7 | 8 | export const metadata: Metadata = { 9 | title: 'GPTStonks Chatbot', 10 | description: 'A fully customizable chatbot for your website.', 11 | }; 12 | 13 | export default function RootLayout({ 14 | children, 15 | }: Readonly<{ 16 | children: React.ReactNode; 17 | }>) { 18 | return ( 19 | 20 | {children} 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /docs/assets/split.css: -------------------------------------------------------------------------------- 1 | .gutter { 2 | background-color: #f5f5f5; 3 | background-repeat: no-repeat; 4 | background-position: 50%; 5 | } 6 | 7 | .gutter.gutter-vertical { 8 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII='); 9 | cursor: ns-resize; 10 | } 11 | 12 | .gutter.gutter-horizontal { 13 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=='); 14 | cursor: ew-resize; 15 | } 16 | -------------------------------------------------------------------------------- /out/tailwind.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | }; 19 | exports.default = config; 20 | -------------------------------------------------------------------------------- /out/src/components/chat/ChatbotInput.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | declare const ChatbotInput: ({ isMobile, themeConfig, newMessage, setNewMessage, handleKeyDown, handleSendMessage, isAnyMessageLoading, multimodeChat, multimodeRenderFunction, }: { 3 | isMobile: boolean; 4 | themeConfig: any; 5 | newMessage: string; 6 | setNewMessage: (message: string) => void; 7 | handleKeyDown: (event: React.KeyboardEvent) => void; 8 | handleSendMessage: () => void; 9 | isAnyMessageLoading: boolean; 10 | multimodeChat: any; 11 | multimodeRenderFunction: (modes: string[]) => JSX.Element | null; 12 | }) => React.JSX.Element; 13 | export default ChatbotInput; 14 | -------------------------------------------------------------------------------- /api/routers/http.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | from ..models.query import QueryParams as QueryParams 3 | from ..utils.phrases import get_random_phrase, generate_related_questions, generate_reference 4 | 5 | router = APIRouter() 6 | 7 | @router.post("/ask") 8 | async def ask(query_params: QueryParams): 9 | response_type = "result_data" 10 | result_data = get_random_phrase() 11 | related_questions = generate_related_questions() 12 | reference = generate_reference() 13 | 14 | return { 15 | "type": response_type, 16 | "result_data": result_data, 17 | "body": get_random_phrase(), 18 | "reference": reference, 19 | "related": related_questions, 20 | } 21 | -------------------------------------------------------------------------------- /out/src/components/renderers/DefaultRenderers.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | declare const DefaultRenderFunctions: { 3 | defaultWelcomeMessageRenderFunction: ( 4 | sendCustomMessage: (message: string) => void, 5 | ) => React.JSX.Element; 6 | defaultBotMessageRenderFunction: (message: any, input: string) => React.JSX.Element; 7 | defaultUserMessageRenderFunction: (text: string) => React.JSX.Element; 8 | defaultSubqueryRenderFunction: ( 9 | subqueryQuestion: string[], 10 | subqueryResponse: string[], 11 | ) => React.JSX.Element; 12 | defaultLoadingRenderFunction: ( 13 | text: string, 14 | themeConfig: any, 15 | subquery_arrays: any, 16 | type?: number, 17 | ) => React.JSX.Element; 18 | }; 19 | export default DefaultRenderFunctions; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # misc 2 | .DS_Store 3 | .env.local 4 | .env.development.local 5 | .env.test.local 6 | .env.production.local 7 | env.* 8 | 9 | # Other packages 10 | npm_package_test/ 11 | gptstonks-test-package/ 12 | 13 | # dependencies 14 | /node_modules 15 | /.pnp 16 | .pnp.js 17 | .yarn/install-state.gz 18 | 19 | # testing 20 | /coverage 21 | 22 | # next.js 23 | /.next/ 24 | .next 25 | 26 | # production 27 | /build 28 | /out/src/app/ 29 | 30 | # misc 31 | .DS_Store 32 | *.pem 33 | 34 | # debug 35 | npm-debug.log* 36 | yarn-debug.log* 37 | yarn-error.log* 38 | 39 | # local env files 40 | .env*.local 41 | 42 | # vercel 43 | .vercel 44 | 45 | # typescript 46 | *.tsbuildinfo 47 | next-env.d.ts 48 | 49 | # Python cache 50 | __pycache__/ 51 | 52 | # Owner of the project 53 | gptstonks/ -------------------------------------------------------------------------------- /src/app/streaming/test/styles.css: -------------------------------------------------------------------------------- 1 | .dialogue-container { 2 | background: linear-gradient(145deg, #f0f0f0, #e0e0e0); 3 | border: 2px solid #d0d0d0; 4 | padding: 20px; 5 | border-radius: 10px; 6 | box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); 7 | position: relative; 8 | overflow: hidden; 9 | } 10 | 11 | .dialogue-container::before { 12 | content: ''; 13 | position: absolute; 14 | top: 0; 15 | left: -100%; 16 | width: 200%; 17 | height: 100%; 18 | background: linear-gradient( 19 | to right, 20 | rgba(255, 255, 255, 0) 0%, 21 | rgba(255, 255, 255, 0.5) 50%, 22 | rgba(255, 255, 255, 0) 100% 23 | ); 24 | animation: reflect 3s infinite linear; 25 | } 26 | 27 | @keyframes reflect { 28 | 0% { 29 | left: -100%; 30 | } 31 | 100% { 32 | left: 100%; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/types/component.ts: -------------------------------------------------------------------------------- 1 | import { ComponentStyle, LoaderConfig } from './styles'; 2 | 3 | export interface ComponentConfig { 4 | style?: ComponentStyle; 5 | label?: string; 6 | fullWidth?: boolean; 7 | hoverBackgroundColor?: string; 8 | appears?: boolean; 9 | text?: string; 10 | showSideUserAvatar?: boolean; 11 | showSideBotAvatar?: boolean; 12 | botAvatarUrl?: string; 13 | userAvatarUrl?: string; 14 | loader?: LoaderConfig; 15 | } 16 | 17 | export interface Components { 18 | ChatBox?: ComponentConfig; 19 | LowPartBox?: ComponentConfig; 20 | TextField?: ComponentConfig; 21 | Button?: ComponentConfig; 22 | Disclaimer?: ComponentConfig; 23 | MessageBubbleBot?: ComponentConfig; 24 | LoaderBot?: ComponentConfig; 25 | MessageBubbleUser?: ComponentConfig; 26 | Avatar?: ComponentConfig; 27 | Divider?: ComponentConfig; 28 | } 29 | -------------------------------------------------------------------------------- /out/src/app/layout.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.metadata = void 0; 7 | const google_1 = require("next/font/google"); 8 | require("./globals.css"); 9 | const react_1 = __importDefault(require("react")); 10 | const inter = (0, google_1.Inter)({ subsets: ['latin'] }); 11 | exports.metadata = { 12 | title: 'GPTStonks Chatbot', 13 | description: 'A fully customizable chatbot for your website.', 14 | }; 15 | function RootLayout({ children, }) { 16 | return (react_1.default.createElement("html", { lang: "en" }, 17 | react_1.default.createElement("body", { className: inter.className }, children))); 18 | } 19 | exports.default = RootLayout; 20 | -------------------------------------------------------------------------------- /out/src/app/streaming/CustomRenderers.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | declare const WelcomeMessageRender: (sendCustomMessage: (message: string) => void) => React.JSX.Element; 3 | declare const BotMessageRender: (message: any, input?: string) => React.JSX.Element; 4 | declare const UserMessageRender: (text: string) => React.JSX.Element; 5 | declare const SubqueryRender: (subqueryQuestion: string[], subqueryResponse: string[]) => React.JSX.Element; 6 | declare const ProviderRender: (providers: string[]) => React.JSX.Element; 7 | declare const ErrorRenderFunction: (error: any) => React.JSX.Element; 8 | declare const LoadingMessageRender: (text: string, themeConfig: any, subquery_arrays: any, type?: number) => React.JSX.Element; 9 | export { WelcomeMessageRender, BotMessageRender, UserMessageRender, SubqueryRender, ProviderRender, ErrorRenderFunction, LoadingMessageRender, }; 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## What does this PR do? 2 | 3 | 9 | 10 | ## Before submitting 11 | 12 | - [ ] Did you make sure **title is self-explanatory** and **the description concisely explains the PR**? 13 | - [ ] Did you make sure your **PR does only one thing**, instead of bundling different changes together? 14 | - [ ] Did you list all the **breaking changes** introduced by this pull request? 15 | - [ ] Did you **test your PR locally** with `npm run build` and `npm test` commands? 16 | - [ ] Did you **run pre-commit hooks** with `npx prettier --write "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"` command? 17 | -------------------------------------------------------------------------------- /out/src/types/component.d.ts: -------------------------------------------------------------------------------- 1 | import { ComponentStyle, LoaderConfig } from './styles'; 2 | export interface ComponentConfig { 3 | style?: ComponentStyle; 4 | label?: string; 5 | fullWidth?: boolean; 6 | hoverBackgroundColor?: string; 7 | appears?: boolean; 8 | text?: string; 9 | showSideUserAvatar?: boolean; 10 | showSideBotAvatar?: boolean; 11 | botAvatarUrl?: string; 12 | userAvatarUrl?: string; 13 | loader?: LoaderConfig; 14 | } 15 | export interface Components { 16 | ChatBox?: ComponentConfig; 17 | LowPartBox?: ComponentConfig; 18 | TextField?: ComponentConfig; 19 | Button?: ComponentConfig; 20 | Disclaimer?: ComponentConfig; 21 | MessageBubbleBot?: ComponentConfig; 22 | LoaderBot?: ComponentConfig; 23 | MessageBubbleUser?: ComponentConfig; 24 | Avatar?: ComponentConfig; 25 | Divider?: ComponentConfig; 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": [ 4 | "dom", 5 | "dom.iterable", 6 | "esnext" 7 | ], 8 | "allowJs": true, 9 | "skipLibCheck": true, 10 | "strict": true, 11 | "esModuleInterop": true, 12 | "module": "CommonJS", 13 | "target": "ES6", 14 | "declaration": true, 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "incremental": true, 19 | "jsx": "react", 20 | "outDir": "out", 21 | "plugins": [ 22 | { 23 | "name": "next" 24 | } 25 | ], 26 | "paths": { 27 | "@/*": [ 28 | "./src/*" 29 | ] 30 | }, 31 | "noEmit": false 32 | }, 33 | "include": [ 34 | "next-env.d.ts", 35 | "**/*.ts", 36 | "**/*.tsx", 37 | ".next/types/**/*.ts", 38 | "**/*.jsx" 39 | ], 40 | "exclude": [ 41 | "node_modules" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /out/src/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as ChatbotWebsocket } from './layouts/ChatbotWebsocket'; 2 | export { default as ChatbotWebsocketStreaming } from './layouts/ChatbotWebsocketStreaming'; 3 | export { default as ChatbotHttp } from './layouts/ChatbotHttp'; 4 | export { default as useChatbotDefaultTheme } from './components/chat/ChatbotDefaultTheme'; 5 | export { default as useGptstonksChatbotTheme } from './components/chat/GptstonksChatbotTheme'; 6 | export { default as ChatbotCore } from './components/chat/ChatbotCore'; 7 | export { default as ChatbotInput } from './components/chat/ChatbotInput'; 8 | export { default as useChatSocket } from './hooks/useChatSocket'; 9 | export { default as RenderFunctions } from './components/renderers/RenderFunctions'; 10 | export { default as DefaulRenderFunctions } from './components/renderers/DefaultRenderers'; 11 | export * from './types/chatbot'; 12 | export * from './types/message'; 13 | export * from './types/component'; 14 | export * from './types/styles'; 15 | -------------------------------------------------------------------------------- /docs/assets/fonts/source-code-pro.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Source Code Pro'; 3 | font-weight: 400; 4 | font-style: normal; 5 | font-stretch: normal; 6 | src: 7 | url('EOT/SourceCodePro-Regular.eot') format('embedded-opentype'), 8 | url('WOFF2/TTF/SourceCodePro-Regular.ttf.woff2') format('woff2'), 9 | url('WOFF/OTF/SourceCodePro-Regular.otf.woff') format('woff'), 10 | url('OTF/SourceCodePro-Regular.otf') format('opentype'), 11 | url('TTF/SourceCodePro-Regular.ttf') format('truetype'); 12 | } 13 | 14 | @font-face { 15 | font-family: 'Source Code Pro'; 16 | font-weight: 700; 17 | font-style: normal; 18 | font-stretch: normal; 19 | src: 20 | url('EOT/SourceCodePro-Bold.eot') format('embedded-opentype'), 21 | url('WOFF2/TTF/SourceCodePro-Bold.ttf.woff2') format('woff2'), 22 | url('WOFF/OTF/SourceCodePro-Bold.otf.woff') format('woff'), 23 | url('OTF/SourceCodePro-Bold.otf') format('opentype'), 24 | url('TTF/SourceCodePro-Bold.ttf') format('truetype'); 25 | } 26 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ChatbotWebsocket } from './layouts/ChatbotWebsocket'; 2 | export { default as ChatbotWebsocketStreaming } from './layouts/ChatbotWebsocketStreaming'; 3 | export { default as ChatbotHttp } from './layouts/ChatbotHttp'; 4 | export { default as useChatbotDefaultTheme } from './components/chat/ChatbotDefaultTheme'; 5 | export { default as useGptstonksChatbotTheme } from './components/chat/GptstonksChatbotTheme'; 6 | export { default as ChatbotCore } from './components/chat/ChatbotCore'; 7 | export { default as ChatbotInput } from './components/chat/ChatbotInput'; 8 | export { default as useChatSocket } from './hooks/useChatSocket'; 9 | export { default as RenderFunctions } from './components/renderers/RenderFunctions'; 10 | export { default as DefaulRenderFunctions } from './components/renderers/DefaultRenderers'; 11 | 12 | // Type definitions 13 | export * from './types/chatbot'; 14 | export * from './types/message'; 15 | export * from './types/component'; 16 | export * from './types/styles'; 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 GPTStonks 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/types/styles.ts: -------------------------------------------------------------------------------- 1 | export interface PaletteColor { 2 | main: string; 3 | } 4 | 5 | export interface Palette { 6 | primary: PaletteColor; 7 | secondary: PaletteColor; 8 | error: PaletteColor; 9 | warning: PaletteColor; 10 | info: PaletteColor; 11 | success: PaletteColor; 12 | background: { default: string; paper: string }; 13 | text: { primary: string; secondary: string }; 14 | } 15 | 16 | export interface Typography { 17 | fontFamily: string; 18 | } 19 | 20 | export interface ComponentStyle extends React.CSSProperties { 21 | '& img'?: React.CSSProperties; 22 | '& label'?: React.CSSProperties; 23 | '& label.MuiFocused'?: React.CSSProperties; 24 | '& .MuiInputUnderline:after'?: React.CSSProperties; 25 | '& .MuiOutlinedInputRoot'?: { 26 | '& fieldset'?: React.CSSProperties; 27 | '&:hover fieldset'?: React.CSSProperties; 28 | '&.MuiFocused fieldset'?: React.CSSProperties; 29 | }; 30 | '&::-webkit-scrollbar'?: React.CSSProperties; 31 | '&::-webkit-scrollbar-track'?: React.CSSProperties; 32 | '&::-webkit-scrollbar-thumb'?: React.CSSProperties; 33 | } 34 | 35 | export interface LoaderConfig { 36 | color: string; 37 | backgroundColor: string; 38 | } 39 | -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) 22 | rgb(var(--background-start-rgb)); 23 | } 24 | 25 | @layer utilities { 26 | .text-balance { 27 | text-wrap: balance; 28 | } 29 | } 30 | 31 | ::-webkit-scrollbar { 32 | width: 8px; 33 | height: 8px; 34 | } 35 | 36 | ::-webkit-scrollbar-thumb { 37 | background-color: rgba(var(--foreground-rgb), 0.5); 38 | border-radius: 6px; 39 | transition: background-color 0.3s; 40 | } 41 | 42 | ::-webkit-scrollbar-track { 43 | background: rgba(var(--foreground-rgb), 0.1); 44 | border-radius: 6px; 45 | } 46 | 47 | ::-webkit-scrollbar-thumb:hover { 48 | background-color: rgba(var(--foreground-rgb), 0.7); 49 | } 50 | -------------------------------------------------------------------------------- /src/components/chat/LinearBuffer.tsx: -------------------------------------------------------------------------------- 1 | import Box from '@mui/material/Box'; 2 | import LinearProgress from '@mui/material/LinearProgress'; 3 | import * as React from 'react'; 4 | 5 | export default function LinearBuffer() { 6 | const [progress, setProgress] = React.useState(0); 7 | const [buffer, setBuffer] = React.useState(10); 8 | 9 | const progressRef = React.useRef(() => {}); 10 | React.useEffect(() => { 11 | progressRef.current = () => { 12 | if (progress > 200) { 13 | setProgress(0); 14 | setBuffer(10); 15 | } else { 16 | const diff = Math.random() * 10; 17 | const diff2 = Math.random() * 10; 18 | setProgress(progress + diff); 19 | setBuffer(progress + diff + diff2); 20 | } 21 | }; 22 | }); 23 | 24 | React.useEffect(() => { 25 | const timer = setInterval(() => { 26 | progressRef.current(); 27 | }, 120); 28 | 29 | return () => { 30 | clearInterval(timer); 31 | }; 32 | }, []); 33 | 34 | return ( 35 | 36 | 45 | 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /out/src/types/styles.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export interface PaletteColor { 3 | main: string; 4 | } 5 | export interface Palette { 6 | primary: PaletteColor; 7 | secondary: PaletteColor; 8 | error: PaletteColor; 9 | warning: PaletteColor; 10 | info: PaletteColor; 11 | success: PaletteColor; 12 | background: { 13 | default: string; 14 | paper: string; 15 | }; 16 | text: { 17 | primary: string; 18 | secondary: string; 19 | }; 20 | } 21 | export interface Typography { 22 | fontFamily: string; 23 | } 24 | export interface ComponentStyle extends React.CSSProperties { 25 | '& img'?: React.CSSProperties; 26 | '& label'?: React.CSSProperties; 27 | '& label.MuiFocused'?: React.CSSProperties; 28 | '& .MuiInputUnderline:after'?: React.CSSProperties; 29 | '& .MuiOutlinedInputRoot'?: { 30 | '& fieldset'?: React.CSSProperties; 31 | '&:hover fieldset'?: React.CSSProperties; 32 | '&.MuiFocused fieldset'?: React.CSSProperties; 33 | }; 34 | '&::-webkit-scrollbar'?: React.CSSProperties; 35 | '&::-webkit-scrollbar-track'?: React.CSSProperties; 36 | '&::-webkit-scrollbar-thumb'?: React.CSSProperties; 37 | } 38 | export interface LoaderConfig { 39 | color: string; 40 | backgroundColor: string; 41 | } 42 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-chatbot 0.1.0 | Documentation 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

react-chatbot

17 |
0.1.0
18 | 26 |
27 |
    28 | 29 |
30 |
31 | 34 |
35 |
36 |
37 | 38 |
39 |
40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /out/src/components/renderers/RenderFunctions.d.ts: -------------------------------------------------------------------------------- 1 | import { Message } from '@/types/message'; 2 | declare const RenderFunctions: ({ 3 | welcomeMessageRenderFunction, 4 | botMessageRenderFunction, 5 | userMessageRenderFunction, 6 | dataRenderFunction, 7 | providerRenderFunction, 8 | referenceRenderFunction, 9 | relatedQuestionsRenderFunction, 10 | subqueryRenderFunction, 11 | loadingRenderFunction, 12 | }: { 13 | welcomeMessageRenderFunction?: Function | undefined; 14 | botMessageRenderFunction?: Function | undefined; 15 | userMessageRenderFunction?: Function | undefined; 16 | dataRenderFunction?: Function | undefined; 17 | providerRenderFunction?: Function | undefined; 18 | referenceRenderFunction?: Function | undefined; 19 | relatedQuestionsRenderFunction?: Function | undefined; 20 | subqueryRenderFunction?: Function | undefined; 21 | loadingRenderFunction?: Function | undefined; 22 | }) => { 23 | WelcomeMessageRender: (sendCustomMessage: (message: string) => void) => any; 24 | BotMessageRender: (message: Message, input: string) => any; 25 | UserMessageRender: (text: string) => any; 26 | DataRender: (data: any) => any; 27 | ProviderRender: (providers: any) => any; 28 | ReferenceRender: (reference: any) => any; 29 | RelatedQuestionsRender: ( 30 | relatedQuestions: any, 31 | sendCustomMessage: (message: string) => void, 32 | ) => any; 33 | SubqueryRender: (subqueryQuestion: any, subqueryResponse: any) => any; 34 | LoadingMessageRender: ( 35 | text: string, 36 | themeConfig: any, 37 | subquery_arrays: any, 38 | type?: number, 39 | ) => any; 40 | }; 41 | export default RenderFunctions; 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gptstonks/chatbot", 3 | "version": "0.1.3", 4 | "author": { 5 | "name": "GPTStonks", 6 | "email": "gptstonks@gmail.com" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/GPTStonks/chatbot.git" 11 | }, 12 | "homepage": "https://gptstonks.net", 13 | "license": "MIT", 14 | "keywords": [ 15 | "chatbot", 16 | "websocket", 17 | "react", 18 | "nextjs", 19 | "AI" 20 | ], 21 | "description": "GPTStonks Open-source Chatbot", 22 | "main": "out/src/index.js", 23 | "private": false, 24 | "files": [ 25 | "out/src/components/**/*", 26 | "out/src/layouts/**/*", 27 | "out/src/types/**/*", 28 | "out/src/hooks/**/*", 29 | "out/src/index.d.ts", 30 | "out/src/index.js" 31 | ], 32 | "scripts": { 33 | "dev": "next dev", 34 | "build": "next build", 35 | "start": "next start", 36 | "lint": "next lint", 37 | "test": "echo \"Error: no test specified\"" 38 | }, 39 | "dependencies": { 40 | "@emotion/react": "^11.11.4", 41 | "@emotion/styled": "^11.11.0", 42 | "@mui/icons-material": "^5.15.13", 43 | "@mui/material": "^5.15.12", 44 | "framer-motion": "^11.5.4", 45 | "lint-staged": "^15.2.2", 46 | "next": "14.1.3", 47 | "react": "^18", 48 | "react-dom": "^18", 49 | "react-loader-spinner": "^6.1.6", 50 | "react-use-websocket": "^3.0.0" 51 | }, 52 | "devDependencies": { 53 | "@types/node": "^20", 54 | "@types/react": "^18", 55 | "@types/react-dom": "^18", 56 | "autoprefixer": "^10.0.1", 57 | "eslint": "^8", 58 | "eslint-config-next": "14.1.3", 59 | "postcss": "^8", 60 | "tailwindcss": "^3.3.0", 61 | "typescript": "^5" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /api/dependencies.py: -------------------------------------------------------------------------------- 1 | import time 2 | from fastapi import WebSocket 3 | from .utils.phrases import get_random_phrase, generate_related_questions, generate_reference 4 | import asyncio 5 | import json 6 | 7 | class ConnectionManager: 8 | active_connections: list[WebSocket] = [] 9 | 10 | async def connect(self, websocket: WebSocket): 11 | await websocket.accept() 12 | self.active_connections.append(websocket) 13 | 14 | def disconnect(self, websocket: WebSocket): 15 | self.active_connections.remove(websocket) 16 | 17 | async def send_personal_message(self, message: dict, websocket: WebSocket): 18 | message_json = json.dumps(message) 19 | await websocket.send_text(message_json) 20 | 21 | async def broadcast(self, message: str): 22 | for connection in self.active_connections: 23 | await connection.send_text(message) 24 | 25 | async def send_random_messages(self, websocket: WebSocket): 26 | result_data = get_random_phrase() 27 | related_questions = generate_related_questions() 28 | reference = generate_reference() 29 | 30 | message_1 = { 31 | "type": "model_step", 32 | "result_data": result_data, 33 | "body": get_random_phrase(), 34 | "reference": reference, 35 | "related": related_questions, 36 | } 37 | await self.send_personal_message(message_1, websocket) 38 | 39 | message_2 = { 40 | "type": "data", 41 | "result_data": get_random_phrase(), 42 | "body": get_random_phrase(), 43 | "reference": reference, 44 | "related": related_questions, 45 | } 46 | time.sleep(2) 47 | 48 | await self.send_personal_message(message_2, websocket) 49 | 50 | manager = ConnectionManager() 51 | -------------------------------------------------------------------------------- /src/app/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import useChatbotDefaultTheme from '@/components/chat/ChatbotDefaultTheme'; 3 | import ChatbotHttp from '@/layouts/ChatbotHttp'; 4 | import { Message } from '@/types/message'; 5 | import { Box, Typography } from '@mui/material'; 6 | import React from 'react'; 7 | 8 | export default function Home() { 9 | const [initializedChat, setInitializedChat] = React.useState(false); 10 | const [chatData, setChatData] = React.useState(null); 11 | 12 | const themeConfig = useChatbotDefaultTheme; 13 | 14 | return ( 15 |
24 |
25 |
26 | { 39 | setChatData(data); 40 | }} 41 | onApiResponseCode={(bool: boolean) => { 42 | setInitializedChat(bool); 43 | }} 44 | userMessageRenderFunction={(text: string) => ( 45 | 46 | {text} 47 | 48 | )} 49 | botMessageRenderFunction={(message: Message) => ( 50 | 51 | {message.text} 52 | 53 | )} 54 | //dataRenderFunction={(data: any) =>
{data}
} 55 | errorRenderFunction={(error: string) =>
{error}
} 56 | /> 57 |
58 |
59 |
60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /docs/assets/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .diff .hljs-header, 18 | .hljs-javadoc { 19 | color: #998; 20 | font-style: italic; 21 | } 22 | 23 | .hljs-keyword, 24 | .css .rule .hljs-keyword, 25 | .hljs-winutils, 26 | .nginx .hljs-title, 27 | .hljs-subst, 28 | .hljs-request, 29 | .hljs-status { 30 | color: #1184ce; 31 | } 32 | 33 | .hljs-number, 34 | .hljs-hexcolor, 35 | .ruby .hljs-constant { 36 | color: #ed225d; 37 | } 38 | 39 | .hljs-string, 40 | .hljs-tag .hljs-value, 41 | .hljs-phpdoc, 42 | .hljs-dartdoc, 43 | .tex .hljs-formula { 44 | color: #ed225d; 45 | } 46 | 47 | .hljs-title, 48 | .hljs-id, 49 | .scss .hljs-preprocessor { 50 | color: #900; 51 | font-weight: bold; 52 | } 53 | 54 | .hljs-list .hljs-keyword, 55 | .hljs-subst { 56 | font-weight: normal; 57 | } 58 | 59 | .hljs-class .hljs-title, 60 | .hljs-type, 61 | .vhdl .hljs-literal, 62 | .tex .hljs-command { 63 | color: #458; 64 | font-weight: bold; 65 | } 66 | 67 | .hljs-tag, 68 | .hljs-tag .hljs-title, 69 | .hljs-rules .hljs-property, 70 | .django .hljs-tag .hljs-keyword { 71 | color: #000080; 72 | font-weight: normal; 73 | } 74 | 75 | .hljs-attribute, 76 | .hljs-variable, 77 | .lisp .hljs-body { 78 | color: #008080; 79 | } 80 | 81 | .hljs-regexp { 82 | color: #009926; 83 | } 84 | 85 | .hljs-symbol, 86 | .ruby .hljs-symbol .hljs-string, 87 | .lisp .hljs-keyword, 88 | .clojure .hljs-keyword, 89 | .scheme .hljs-keyword, 90 | .tex .hljs-special, 91 | .hljs-prompt { 92 | color: #990073; 93 | } 94 | 95 | .hljs-built_in { 96 | color: #0086b3; 97 | } 98 | 99 | .hljs-preprocessor, 100 | .hljs-pragma, 101 | .hljs-pi, 102 | .hljs-doctype, 103 | .hljs-shebang, 104 | .hljs-cdata { 105 | color: #999; 106 | font-weight: bold; 107 | } 108 | 109 | .hljs-deletion { 110 | background: #fdd; 111 | } 112 | 113 | .hljs-addition { 114 | background: #dfd; 115 | } 116 | 117 | .diff .hljs-change { 118 | background: #0086b3; 119 | } 120 | 121 | .hljs-chunk { 122 | color: #aaa; 123 | } 124 | -------------------------------------------------------------------------------- /src/app/websocket/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import useChatbotDefaultTheme from '@/components/chat/ChatbotDefaultTheme'; 3 | import ChatbotWebsocket from '@/layouts/ChatbotWebsocket'; 4 | import { Message } from '@/types/message'; 5 | import { Box, Typography } from '@mui/material'; 6 | import React from 'react'; 7 | 8 | export default function Home() { 9 | const [initializedChat, setInitializedChat] = React.useState(false); 10 | const [chatData, setChatData] = React.useState(null); 11 | 12 | const themeConfig = useChatbotDefaultTheme; 13 | 14 | return ( 15 |
25 |
26 |
27 | { 41 | setChatData(data); 42 | }} 43 | onApiResponseCode={(bool: boolean) => { 44 | setInitializedChat(bool); 45 | }} 46 | userMessageRenderFunction={(text: string) => ( 47 | 48 | {text} 49 | 50 | )} 51 | botMessageRenderFunction={(message: Message) => ( 52 | 58 | 63 | {message.text} 64 | 65 | 66 | )} 67 | /> 68 |
69 |
70 |
71 | ); 72 | } 73 | -------------------------------------------------------------------------------- /out/src/types/chatbot.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { Palette, Typography } from './styles'; 3 | import { Components } from './component'; 4 | import { Message } from './message'; 5 | export interface APIConfig { 6 | queryEndpoint: string; 7 | queryParams?: Record; 8 | modelStepTypes?: Record; 9 | needsJWT?: boolean; 10 | token?: string; 11 | } 12 | export interface MultimodeChat { 13 | [key: string]: { 14 | url_param: string; 15 | value: string; 16 | isActivated?: boolean; 17 | }; 18 | } 19 | export interface ChatLayoutConfig { 20 | chatOrientation?: 'horizontal' | 'vertical'; 21 | avatarPosition?: 'left' | 'right' | 'top' | 'bottom'; 22 | mobileLayout?: { 23 | hideAvatar?: boolean; 24 | messageMaxWidth?: string; 25 | }; 26 | infiniteScroll?: boolean; 27 | botMessageStackDirection?: 'row' | 'column'; 28 | responseHeader?: boolean; 29 | } 30 | export interface ThemeConfig { 31 | style?: React.CSSProperties; 32 | palette?: Palette; 33 | typography?: Typography; 34 | components?: Components; 35 | chatLayoutConfig?: ChatLayoutConfig; 36 | } 37 | export interface ChatbotProps { 38 | className?: string; 39 | style?: React.CSSProperties; 40 | apiConfig: APIConfig; 41 | loaderType?: number; 42 | themeConfig: ThemeConfig; 43 | preloadedMessages?: Message[]; 44 | multimodeChat?: MultimodeChat; 45 | sendCustomMessage?: (text: string) => void; 46 | welcomeMessageRenderFunction?: (sendCustomMessage: any) => JSX.Element; 47 | setDataForParent?: (data: any) => void; 48 | onApiResponseCode?: (bool: boolean) => void; 49 | multimodeRenderFunction?: (modes: string[]) => JSX.Element; 50 | userMessageRenderFunction?: (text: string) => JSX.Element; 51 | botMessageRenderFunction?: (message: Message, input?: string) => JSX.Element; 52 | dataRenderFunction?: (data: any) => JSX.Element; 53 | providerRenderFunction?: (providers: string[]) => JSX.Element; 54 | referenceRenderFunction?: (reference: string[]) => JSX.Element; 55 | subqueryRenderFunction?: (subqueryQuestion: string[], subqueryResponse: string[]) => JSX.Element; 56 | relatedQuestionsRenderFunction?: ( 57 | relatedQuestions: string[], 58 | sendCustomMessage: any, 59 | ) => JSX.Element; 60 | errorRenderFunction?: (error: any) => JSX.Element; 61 | loadingRenderFunction?: ( 62 | text: string, 63 | themeConfig: ThemeConfig, 64 | subquery_arrays: any, 65 | type?: number, 66 | ) => JSX.Element; 67 | } 68 | -------------------------------------------------------------------------------- /src/components/renderers/DefaultRenderers.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, Box, Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import { DNA } from 'react-loader-spinner'; 4 | 5 | const defaultWelcomeMessageRenderFunction = (sendCustomMessage: (message: string) => void) => ( 6 | 16 | 17 | Welcome! How can I help you today? 18 | 19 | 20 | ); 21 | 22 | const defaultBotMessageRenderFunction = (message: any, input: string) => ( 23 | 29 | {message.text} 30 | 31 | ); 32 | 33 | const defaultUserMessageRenderFunction = (text: string) => ( 34 | 35 | {text} 36 | 37 | ); 38 | 39 | const defaultSubqueryRenderFunction = (subqueryQuestion: string[], subqueryResponse: string[]) => ( 40 | 41 | {subqueryQuestion.join(', ')} 42 | {subqueryResponse.join(', ')} 43 | 44 | ); 45 | 46 | const defaultLoadingRenderFunction = ( 47 | text: string, 48 | themeConfig: any, 49 | subquery_arrays: any, 50 | type: number = 1, 51 | ) => { 52 | return ( 53 | 54 | 61 | 62 | 70 | {text} 71 | 72 | 73 | ); 74 | }; 75 | 76 | const DefaultRenderFunctions = { 77 | defaultWelcomeMessageRenderFunction, 78 | defaultBotMessageRenderFunction, 79 | defaultUserMessageRenderFunction, 80 | defaultSubqueryRenderFunction, 81 | defaultLoadingRenderFunction, 82 | }; 83 | 84 | export default DefaultRenderFunctions; 85 | -------------------------------------------------------------------------------- /out/src/components/chat/ChatbotCore.d.ts: -------------------------------------------------------------------------------- 1 | import { APIConfig, ThemeConfig } from '@/types/chatbot'; 2 | import { Message } from '@/types/message'; 3 | import React from 'react'; 4 | declare const ChatbotCore: ({ 5 | messages, 6 | themeConfig, 7 | loaderType, 8 | apiConfig, 9 | isMobile, 10 | botUser, 11 | humanUser, 12 | botMessage, 13 | messagesEndRef, 14 | isAnyMessageLoading, 15 | showLinearLoader, 16 | sendCustomMessage, 17 | welcomeMessageRenderFunction, 18 | botMessageRenderFunction, 19 | userMessageRenderFunction, 20 | dataRenderFunction, 21 | providerRenderFunction, 22 | referenceRenderFunction, 23 | relatedQuestionsRenderFunction, 24 | subqueryRenderFunction, 25 | loadingRenderFunction, 26 | }: { 27 | messages: Message[]; 28 | themeConfig: ThemeConfig; 29 | loaderType?: number | undefined; 30 | isMobile: boolean; 31 | apiConfig: APIConfig; 32 | botUser: string; 33 | humanUser: string; 34 | botMessage: Message | null; 35 | messagesEndRef: any; 36 | isAnyMessageLoading: boolean; 37 | showLinearLoader: boolean; 38 | setDataForParent?: ((data: any) => void) | undefined; 39 | onApiResponseCode?: ((bool: boolean) => void) | undefined; 40 | multimodeRenderFunction?: ((modes: string[]) => JSX.Element) | undefined; 41 | errorRenderFunction?: ((error: any) => JSX.Element) | undefined; 42 | sendCustomMessage: (message: string) => void; 43 | welcomeMessageRenderFunction?: 44 | | ((sendCustomMessage: (message: string) => void) => JSX.Element | null) 45 | | undefined; 46 | botMessageRenderFunction?: ((message: any, input: string) => JSX.Element | null) | undefined; 47 | userMessageRenderFunction?: ((text: string) => JSX.Element | null) | undefined; 48 | dataRenderFunction?: ((data: any) => JSX.Element | null) | undefined; 49 | providerRenderFunction?: ((providers: string[]) => JSX.Element | null) | undefined; 50 | referenceRenderFunction?: ((reference: any) => JSX.Element | null) | undefined; 51 | relatedQuestionsRenderFunction?: 52 | | ((relatedQuestions: any, sendCustomMessage: (message: string) => void) => JSX.Element | null) 53 | | undefined; 54 | subqueryRenderFunction?: 55 | | ((subqueryQuestion: string[], subqueryResponse: string[]) => JSX.Element | null) 56 | | undefined; 57 | loadingRenderFunction?: 58 | | (( 59 | text: string, 60 | themeConfig: ThemeConfig, 61 | subquery_arrays: any, 62 | type: number, 63 | ) => JSX.Element | null) 64 | | undefined; 65 | }) => React.JSX.Element; 66 | export default ChatbotCore; 67 | -------------------------------------------------------------------------------- /src/types/chatbot.ts: -------------------------------------------------------------------------------- 1 | import { Palette, Typography } from './styles'; 2 | import { Components } from './component'; 3 | import { Message } from './message'; 4 | 5 | export interface APIConfig { 6 | queryEndpoint: string; 7 | queryParams?: Record; 8 | modelStepTypes?: Record; 9 | needsJWT?: boolean; // If the API needs a JWT token for HTTP requests 10 | token?: string; // JWT token name (only if needsJWT is true) 11 | } 12 | 13 | export interface MultimodeChat { 14 | [key: string]: { 15 | url_param: string; 16 | value: string; 17 | isActivated?: boolean; 18 | }; 19 | } 20 | 21 | export interface ChatLayoutConfig { 22 | chatOrientation?: 'horizontal' | 'vertical'; 23 | avatarPosition?: 'left' | 'right' | 'top' | 'bottom'; 24 | mobileLayout?: { 25 | hideAvatar?: boolean; 26 | messageMaxWidth?: string; 27 | }; 28 | infiniteScroll?: boolean; 29 | botMessageStackDirection?: 'row' | 'column'; 30 | responseHeader?: boolean; 31 | } 32 | 33 | export interface ThemeConfig { 34 | style?: React.CSSProperties; 35 | palette?: Palette; 36 | typography?: Typography; 37 | components?: Components; 38 | chatLayoutConfig?: ChatLayoutConfig; 39 | } 40 | 41 | export interface ChatbotProps { 42 | className?: string; 43 | style?: React.CSSProperties; 44 | apiConfig: APIConfig; 45 | loaderType?: number; 46 | themeConfig: ThemeConfig; 47 | preloadedMessages?: Message[]; 48 | multimodeChat?: MultimodeChat; 49 | sendCustomMessage?: (text: string) => void; 50 | welcomeMessageRenderFunction?: (sendCustomMessage: any) => JSX.Element; 51 | setDataForParent?: (data: any) => void; 52 | onApiResponseCode?: (bool: boolean) => void; 53 | multimodeRenderFunction?: (modes: string[]) => JSX.Element; 54 | userMessageRenderFunction?: (text: string) => JSX.Element; 55 | botMessageRenderFunction?: (message: Message, input?: string) => JSX.Element; 56 | dataRenderFunction?: (data: any) => JSX.Element; 57 | providerRenderFunction?: (providers: string[]) => JSX.Element; 58 | referenceRenderFunction?: (reference: string[]) => JSX.Element; 59 | subqueryRenderFunction?: (subqueryQuestion: string[], subqueryResponse: string[]) => JSX.Element; 60 | relatedQuestionsRenderFunction?: ( 61 | relatedQuestions: string[], 62 | sendCustomMessage: any, 63 | ) => JSX.Element; 64 | errorRenderFunction?: (error: any) => JSX.Element; 65 | loadingRenderFunction?: ( 66 | text: string, 67 | themeConfig: ThemeConfig, 68 | subquery_arrays: any, 69 | type?: number, 70 | ) => JSX.Element; 71 | } 72 | -------------------------------------------------------------------------------- /out/src/app/page.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 'use client'; 3 | var __importDefault = (this && this.__importDefault) || function (mod) { 4 | return (mod && mod.__esModule) ? mod : { "default": mod }; 5 | }; 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | const ChatbotDefaultTheme_1 = __importDefault(require("@/components/chat/ChatbotDefaultTheme")); 8 | const ChatbotHttp_1 = __importDefault(require("@/layouts/ChatbotHttp")); 9 | const material_1 = require("@mui/material"); 10 | const react_1 = __importDefault(require("react")); 11 | function Home() { 12 | const [initializedChat, setInitializedChat] = react_1.default.useState(false); 13 | const [chatData, setChatData] = react_1.default.useState(null); 14 | const themeConfig = ChatbotDefaultTheme_1.default; 15 | return (react_1.default.createElement("main", { style: { 16 | display: 'flex', 17 | justifyContent: 'center', 18 | alignItems: 'center', 19 | height: '100vh', 20 | backgroundColor: '#080808', 21 | } }, 22 | react_1.default.createElement("div", { style: { width: '20vw', height: '100%' } }), 23 | react_1.default.createElement("div", { style: { width: '60vw', height: '100%' } }, 24 | react_1.default.createElement(ChatbotHttp_1.default, { apiConfig: { 25 | queryEndpoint: 'http://localhost:5000/ask', 26 | queryParams: { 27 | type: 'type', 28 | data: 'result_data', 29 | text: 'body', 30 | reference: 'reference', 31 | related: 'related', 32 | }, 33 | }, themeConfig: themeConfig, setDataForParent: (data) => { 34 | setChatData(data); 35 | }, onApiResponseCode: (bool) => { 36 | setInitializedChat(bool); 37 | }, userMessageRenderFunction: (text) => (react_1.default.createElement(material_1.Box, null, 38 | react_1.default.createElement(material_1.Typography, null, text))), botMessageRenderFunction: (message) => (react_1.default.createElement(material_1.Box, null, 39 | react_1.default.createElement(material_1.Typography, null, message.text))), 40 | //dataRenderFunction={(data: any) =>
{data}
} 41 | errorRenderFunction: (error) => react_1.default.createElement("div", null, error) })), 42 | react_1.default.createElement("div", { style: { width: '20vw', height: '100%' } }))); 43 | } 44 | exports.default = Home; 45 | -------------------------------------------------------------------------------- /docs/assets/style.css: -------------------------------------------------------------------------------- 1 | .documentation { 2 | font-family: Helvetica, sans-serif; 3 | color: #666; 4 | line-height: 1.5; 5 | background: #f5f5f5; 6 | } 7 | 8 | .black { 9 | color: #666; 10 | } 11 | 12 | .bg-white { 13 | background-color: #fff; 14 | } 15 | 16 | h4 { 17 | margin: 20px 0 10px 0; 18 | } 19 | 20 | .documentation h3 { 21 | color: #000; 22 | } 23 | 24 | .border-bottom { 25 | border-color: #ddd; 26 | } 27 | 28 | a { 29 | color: #1184ce; 30 | text-decoration: none; 31 | } 32 | 33 | .documentation a[href]:hover { 34 | text-decoration: underline; 35 | } 36 | 37 | a:hover { 38 | cursor: pointer; 39 | } 40 | 41 | .py1-ul li { 42 | padding: 5px 0; 43 | } 44 | 45 | .max-height-100 { 46 | max-height: 100%; 47 | } 48 | 49 | .height-viewport-100 { 50 | height: 100vh; 51 | } 52 | 53 | section:target h3 { 54 | font-weight: 700; 55 | } 56 | 57 | .documentation td, 58 | .documentation th { 59 | padding: 0.25rem 0.25rem; 60 | } 61 | 62 | h1:hover .anchorjs-link, 63 | h2:hover .anchorjs-link, 64 | h3:hover .anchorjs-link, 65 | h4:hover .anchorjs-link { 66 | opacity: 1; 67 | } 68 | 69 | .fix-3 { 70 | width: 25%; 71 | max-width: 244px; 72 | } 73 | 74 | .fix-3 { 75 | width: 25%; 76 | max-width: 244px; 77 | } 78 | 79 | @media (min-width: 52em) { 80 | .fix-margin-3 { 81 | margin-left: 25%; 82 | } 83 | } 84 | 85 | .pre, 86 | pre, 87 | code, 88 | .code { 89 | font-family: 90 | Source Code Pro, 91 | Menlo, 92 | Consolas, 93 | Liberation Mono, 94 | monospace; 95 | font-size: 14px; 96 | } 97 | 98 | .fill-light { 99 | background: #f9f9f9; 100 | } 101 | 102 | .width2 { 103 | width: 1rem; 104 | } 105 | 106 | .input { 107 | font-family: inherit; 108 | display: block; 109 | width: 100%; 110 | height: 2rem; 111 | padding: 0.5rem; 112 | margin-bottom: 1rem; 113 | border: 1px solid #ccc; 114 | font-size: 0.875rem; 115 | border-radius: 3px; 116 | box-sizing: border-box; 117 | } 118 | 119 | table { 120 | border-collapse: collapse; 121 | } 122 | 123 | .prose table th, 124 | .prose table td { 125 | text-align: left; 126 | padding: 8px; 127 | border: 1px solid #ddd; 128 | } 129 | 130 | .prose table th:nth-child(1) { 131 | border-right: none; 132 | } 133 | .prose table th:nth-child(2) { 134 | border-left: none; 135 | } 136 | 137 | .prose table { 138 | border: 1px solid #ddd; 139 | } 140 | 141 | .prose-big { 142 | font-size: 18px; 143 | line-height: 30px; 144 | } 145 | 146 | .quiet { 147 | opacity: 0.7; 148 | } 149 | 150 | .minishadow { 151 | box-shadow: 2px 2px 10px #f3f3f3; 152 | } 153 | -------------------------------------------------------------------------------- /out/src/app/websocket/page.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 'use client'; 3 | var __importDefault = (this && this.__importDefault) || function (mod) { 4 | return (mod && mod.__esModule) ? mod : { "default": mod }; 5 | }; 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | const ChatbotDefaultTheme_1 = __importDefault(require("@/components/chat/ChatbotDefaultTheme")); 8 | const ChatbotWebsocket_1 = __importDefault(require("@/layouts/ChatbotWebsocket")); 9 | const material_1 = require("@mui/material"); 10 | const react_1 = __importDefault(require("react")); 11 | function Home() { 12 | const [initializedChat, setInitializedChat] = react_1.default.useState(false); 13 | const [chatData, setChatData] = react_1.default.useState(null); 14 | const themeConfig = ChatbotDefaultTheme_1.default; 15 | return (react_1.default.createElement("main", { style: { 16 | display: 'flex', 17 | justifyContent: 'center', 18 | alignItems: 'center', 19 | height: '100vh', 20 | width: '100vw', 21 | backgroundColor: '#080808', 22 | } }, 23 | react_1.default.createElement("div", { style: { width: '20vw', height: '100%' } }), 24 | react_1.default.createElement("div", { style: { width: '100%', height: '100%' } }, 25 | react_1.default.createElement(ChatbotWebsocket_1.default, { apiConfig: { 26 | queryEndpoint: 'ws://localhost:8000/chatws', 27 | queryParams: { 28 | type: 'type', 29 | data: 'result_data', 30 | text: 'body', 31 | reference: 'reference', 32 | related: 'related', 33 | stream: 'stream_step', 34 | }, 35 | }, themeConfig: themeConfig, setDataForParent: (data) => { 36 | setChatData(data); 37 | }, onApiResponseCode: (bool) => { 38 | setInitializedChat(bool); 39 | }, userMessageRenderFunction: (text) => (react_1.default.createElement(material_1.Box, null, 40 | react_1.default.createElement(material_1.Typography, null, text))), botMessageRenderFunction: (message) => (react_1.default.createElement(material_1.Box, { sx: { 41 | maxWidth: '100%', 42 | overflowWrap: 'break-word', 43 | } }, 44 | react_1.default.createElement(material_1.Typography, { sx: { 45 | wordWrap: 'break-word', 46 | } }, message.text))) })), 47 | react_1.default.createElement("div", { style: { width: '20vw', height: '100%' } }))); 48 | } 49 | exports.default = Home; 50 | -------------------------------------------------------------------------------- /out/src/components/chat/LinearBuffer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | const Box_1 = __importDefault(require("@mui/material/Box")); 30 | const LinearProgress_1 = __importDefault(require("@mui/material/LinearProgress")); 31 | const React = __importStar(require("react")); 32 | function LinearBuffer() { 33 | const [progress, setProgress] = React.useState(0); 34 | const [buffer, setBuffer] = React.useState(10); 35 | const progressRef = React.useRef(() => { }); 36 | React.useEffect(() => { 37 | progressRef.current = () => { 38 | if (progress > 200) { 39 | setProgress(0); 40 | setBuffer(10); 41 | } 42 | else { 43 | const diff = Math.random() * 10; 44 | const diff2 = Math.random() * 10; 45 | setProgress(progress + diff); 46 | setBuffer(progress + diff + diff2); 47 | } 48 | }; 49 | }); 50 | React.useEffect(() => { 51 | const timer = setInterval(() => { 52 | progressRef.current(); 53 | }, 120); 54 | return () => { 55 | clearInterval(timer); 56 | }; 57 | }, []); 58 | return (React.createElement(Box_1.default, { sx: { width: '100%' } }, 59 | React.createElement(LinearProgress_1.default, { variant: "buffer", value: progress, valueBuffer: buffer, sx: { 60 | height: '5px', 61 | borderRadius: 5, 62 | } }))); 63 | } 64 | exports.default = LinearBuffer; 65 | -------------------------------------------------------------------------------- /src/hooks/useChatSocket.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { useState, useEffect, useCallback } from 'react'; 3 | 4 | const useChatSocket = (url: string) => { 5 | const [socket, setSocket] = useState(null); 6 | const [connectionStatus, setConnectionStatus] = useState('disconnected'); 7 | const [lastMessage, setLastMessage] = useState(null); 8 | const [eventReason, setEventReason] = useState(null); 9 | 10 | useEffect(() => { 11 | if (!url) { 12 | console.error('WebSocket connection failed: URL is required'); 13 | return; 14 | } 15 | 16 | let newSocket: WebSocket | null = null; 17 | 18 | try { 19 | newSocket = new WebSocket(url); 20 | } catch (error) { 21 | console.error('WebSocket connection failed:', error); 22 | return; 23 | } 24 | 25 | const handleOpen = () => { 26 | setConnectionStatus('connected'); 27 | setEventReason(null); 28 | console.log('Socket connection opened'); 29 | }; 30 | 31 | const handleClose = (event: CloseEvent) => { 32 | setConnectionStatus('disconnected'); 33 | setEventReason(event.reason); 34 | console.log(`Socket connection closed: ${event.reason}`); 35 | }; 36 | 37 | const handleMessage = (event: MessageEvent) => { 38 | const messageData = JSON.parse(event.data); 39 | setLastMessage(messageData); 40 | }; 41 | 42 | const handleError = (event: Event) => { 43 | setConnectionStatus('error'); 44 | setEventReason('An error occurred'); 45 | console.log('WebSocket error:', event); 46 | }; 47 | 48 | newSocket.addEventListener('open', handleOpen); 49 | newSocket.addEventListener('close', handleClose); 50 | newSocket.addEventListener('message', handleMessage); 51 | newSocket.addEventListener('error', handleError); 52 | 53 | setSocket(newSocket); 54 | 55 | return () => { 56 | if (newSocket) { 57 | newSocket.removeEventListener('open', handleOpen); 58 | newSocket.removeEventListener('close', handleClose); 59 | newSocket.removeEventListener('message', handleMessage); 60 | newSocket.removeEventListener('error', handleError); 61 | if (newSocket.readyState === WebSocket.OPEN) { 62 | newSocket.close(); 63 | } 64 | } 65 | }; 66 | }, [url]); 67 | 68 | useEffect(() => { 69 | const closeSocket = () => { 70 | if (socket && socket.readyState === WebSocket.OPEN) { 71 | socket.close(); 72 | } 73 | }; 74 | 75 | window.addEventListener('beforeunload', closeSocket); 76 | return () => { 77 | window.removeEventListener('beforeunload', closeSocket); 78 | }; 79 | }, [socket]); 80 | 81 | const sendMessage = useCallback( 82 | (newMessage: string) => { 83 | if (!newMessage.trim()) return; 84 | if (socket && socket.readyState === WebSocket.OPEN) { 85 | socket.send(newMessage); 86 | setLastMessage({ text: newMessage, user: 'humanUser' }); 87 | } else { 88 | console.error('WebSocket is not open. Cannot send message.'); 89 | } 90 | }, 91 | [socket], 92 | ); 93 | 94 | return { sendMessage, lastMessage, connectionStatus, eventReason }; 95 | }; 96 | 97 | export default useChatSocket; 98 | -------------------------------------------------------------------------------- /src/app/streaming/test/Loading.jsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import React from 'react'; 3 | import { motion } from 'framer-motion'; 4 | import './styles.css'; // Asegúrate de tener un archivo CSS para los estilos 5 | 6 | const data = { 7 | type: 'model_step', 8 | body: 'agent', 9 | subqueries_answered: [ 10 | 'Provide a list of memecoins that seem to be less correlated with BTC price action', 11 | ], 12 | subqueries_responses: [ 13 | "Based on the information gathered, the latest big crypto movements involve the top 10 cryptocurrencies, with Bitcoin (BTC) leading the pack in terms of market capitalization and growth. Here are some key points regarding Bitcoin and the general trend of BTC:\n\n1. **Bitcoin (BTC)**:\n - Bitcoin is the original and most well-known cryptocurrency, with a market capitalization of $1.3 trillion.\n - The price of one Bitcoin has seen significant growth over the years. For example, in May 2016, the price was around $500, while as of July 16, 2024, it was approximately $63,808.\n - This price increase represents a substantial growth of 12,662% over the specified period.\n\n2. **General Trend of BTC**:\n - Bitcoin's performance and price movements have a significant impact on the overall cryptocurrency market.\n - As the leading cryptocurrency, Bitcoin's trends often influence the direction of other cryptocurrencies in the market.\n - Bitcoin's market capitalization and year-over-year return of 111% indicate its dominance and continued relevance in the crypto space.\n\n3. **Market Caps and Pricing**:\n - The market capitalization and pricing data for Bitcoin and other cryptocurrencies can be sourced from platforms like CoinMarketCap, providing real-time information on their performance.\n\nIn summary, Bitcoin remains a key player in the cryptocurrency market, with its price movements and market capitalization influencing the broader trends in the industry. The growth and stability of Bitcoin serve as important indicators for investors and traders looking to understand the general trend of cryptocurrencies. [Sources: [Forbes Advisor](https://www.forbes.com/advisor/investing/cryptocurrency/top-10-cryptocurrencies/), [CoinTelegraph](https://cointelegraph.com/news/what-happened-in-crypto-today), [CNBC](https://www.cnbc.com/bitcoin/)]", 14 | ], 15 | }; 16 | 17 | const AnimatedText = ({ text }) => { 18 | const words = text.split(' '); 19 | 20 | return ( 21 |
22 | {words.map((word, index) => ( 23 | 30 | {word} 31 | 32 | ))} 33 |
34 | ); 35 | }; 36 | 37 | export default function SubqueryComponent() { 38 | return ( 39 |
47 | {data.subqueries_answered.map((query, index) => ( 48 |
49 |

50 | 51 |

52 |

53 | 54 |

55 |
56 | ))} 57 |
58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /out/src/hooks/useChatSocket.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 'use client'; 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const react_1 = require("react"); 5 | const useChatSocket = (url) => { 6 | const [socket, setSocket] = (0, react_1.useState)(null); 7 | const [connectionStatus, setConnectionStatus] = (0, react_1.useState)('disconnected'); 8 | const [lastMessage, setLastMessage] = (0, react_1.useState)(null); 9 | const [eventReason, setEventReason] = (0, react_1.useState)(null); 10 | (0, react_1.useEffect)(() => { 11 | if (!url) { 12 | console.error('WebSocket connection failed: URL is required'); 13 | return; 14 | } 15 | let newSocket = null; 16 | try { 17 | newSocket = new WebSocket(url); 18 | } 19 | catch (error) { 20 | console.error('WebSocket connection failed:', error); 21 | return; 22 | } 23 | const handleOpen = () => { 24 | setConnectionStatus('connected'); 25 | setEventReason(null); 26 | console.log('Socket connection opened'); 27 | }; 28 | const handleClose = (event) => { 29 | setConnectionStatus('disconnected'); 30 | setEventReason(event.reason); 31 | console.log(`Socket connection closed: ${event.reason}`); 32 | }; 33 | const handleMessage = (event) => { 34 | const messageData = JSON.parse(event.data); 35 | setLastMessage(messageData); 36 | }; 37 | const handleError = (event) => { 38 | setConnectionStatus('error'); 39 | setEventReason('An error occurred'); 40 | console.log('WebSocket error:', event); 41 | }; 42 | newSocket.addEventListener('open', handleOpen); 43 | newSocket.addEventListener('close', handleClose); 44 | newSocket.addEventListener('message', handleMessage); 45 | newSocket.addEventListener('error', handleError); 46 | setSocket(newSocket); 47 | return () => { 48 | if (newSocket) { 49 | newSocket.removeEventListener('open', handleOpen); 50 | newSocket.removeEventListener('close', handleClose); 51 | newSocket.removeEventListener('message', handleMessage); 52 | newSocket.removeEventListener('error', handleError); 53 | if (newSocket.readyState === WebSocket.OPEN) { 54 | newSocket.close(); 55 | } 56 | } 57 | }; 58 | }, [url]); 59 | (0, react_1.useEffect)(() => { 60 | const closeSocket = () => { 61 | if (socket && socket.readyState === WebSocket.OPEN) { 62 | socket.close(); 63 | } 64 | }; 65 | window.addEventListener('beforeunload', closeSocket); 66 | return () => { 67 | window.removeEventListener('beforeunload', closeSocket); 68 | }; 69 | }, [socket]); 70 | const sendMessage = (0, react_1.useCallback)((newMessage) => { 71 | if (!newMessage.trim()) 72 | return; 73 | if (socket && socket.readyState === WebSocket.OPEN) { 74 | socket.send(newMessage); 75 | setLastMessage({ text: newMessage, user: 'humanUser' }); 76 | } 77 | else { 78 | console.error('WebSocket is not open. Cannot send message.'); 79 | } 80 | }, [socket]); 81 | return { sendMessage, lastMessage, connectionStatus, eventReason }; 82 | }; 83 | exports.default = useChatSocket; 84 | -------------------------------------------------------------------------------- /api/utils/phrases.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | phrases = [ "The global economy is absolutely thriving, and there's an electrifying opportunity to dive into the stock market like never before! Let's ride the wave of prosperity together!", 4 | "Today's the day I'm supercharging my portfolio with some incredibly promising stocks! The future's bright, and the potential for growth is sky-high!", 5 | "I'm strategically enhancing my portfolio by capitalizing on the gains and pivoting towards even more exciting investment avenues. The journey to wealth continues!", 6 | "The cryptocurrency world is a treasure trove of innovation and untapped potential. I'm on a thrilling adventure to discover the next big crypto gem!", 7 | "Investing in real estate is not just smart; it's a game-changer. I'm on the hunt for properties in burgeoning markets, ready to turn dreams into reality!", 8 | "Bonds are the cornerstone of a savvy investor's portfolio. I'm bolstering my investments with some of the most stable and secure bonds out there. Safety first, but profit assured!", 9 | "Commodities are my secret weapon against inflation. Gold, oil, you name it—I'm diving into commodities to safeguard and enrich my portfolio!", 10 | "ETFs are my ticket to a world of diversified, balanced investment. With just one bold move, I'm getting exposure to an entire universe of assets. Exciting times ahead!", 11 | "Handing over the reins to the pros with mutual funds and watching my investments soar! Top-performing funds are the name of the game, and I'm playing to win.", 12 | "Options trading is my playground for financial creativity. It's all about strategic moves and flexibility. Ready to boost my portfolio with some high-potential options!", 13 | "Futures trading is where I predict and profit from the future. Armed with insight and daring, I'm diving into futures for the ultimate financial thrill!", 14 | "Forex trading is my passport to the dynamic world of currency exchange. I'm navigating the forex waves, ready to make a splash with smart, calculated moves!", 15 | "CFDs are the cutting-edge of modern investing. Without owning the underlying assets, I'm set to profit from their price movements. The future of finance is here, and I'm in!", 16 | "Cryptocurrencies are the vanguard of the digital finance revolution. I'm not just participating; I'm eagerly investing in the cryptocurrencies that are shaping our future!", 17 | "NFTs are transforming the digital landscape, and I'm all in! Investing in unique NFTs is not just exciting; it's a way to support and be part of the digital art revolution!" 18 | ] 19 | 20 | related_questions = [ 21 | "How does BTC halving affect the market and what are the implications for investors?", 22 | "What are the key factors to consider when investing in real estate?", 23 | "How do I choose the right ETFs for my investment portfolio and what are the benefits of diversification?", 24 | "What are the risks and rewards of options trading, and how can I mitigate potential losses?", 25 | ] 26 | 27 | references = [ 28 | "https://gptstonks.net/", 29 | "https://wikipedia.org/wiki/Stock_market", 30 | "https://www.investopedia.com/terms/s/stockmarket.asp", 31 | "https://tradingview.com/", 32 | "https://www.bloomberg.com/markets", 33 | "https://www.cnbc.com/markets", 34 | "https://www.reuters.com/finance/markets", 35 | ] 36 | 37 | def get_random_phrase() -> str: 38 | return random.choice(phrases) 39 | 40 | def generate_related_questions() -> list: 41 | return related_questions 42 | 43 | def generate_reference() -> list: 44 | return references 45 | -------------------------------------------------------------------------------- /out/src/app/streaming/test/Loading.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 'use client'; 3 | var __importDefault = (this && this.__importDefault) || function (mod) { 4 | return (mod && mod.__esModule) ? mod : { "default": mod }; 5 | }; 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | const react_1 = __importDefault(require("react")); 8 | const framer_motion_1 = require("framer-motion"); 9 | require("./styles.css"); // Asegúrate de tener un archivo CSS para los estilos 10 | const data = { 11 | type: 'model_step', 12 | body: 'agent', 13 | subqueries_answered: [ 14 | 'Provide a list of memecoins that seem to be less correlated with BTC price action', 15 | ], 16 | subqueries_responses: [ 17 | "Based on the information gathered, the latest big crypto movements involve the top 10 cryptocurrencies, with Bitcoin (BTC) leading the pack in terms of market capitalization and growth. Here are some key points regarding Bitcoin and the general trend of BTC:\n\n1. **Bitcoin (BTC)**:\n - Bitcoin is the original and most well-known cryptocurrency, with a market capitalization of $1.3 trillion.\n - The price of one Bitcoin has seen significant growth over the years. For example, in May 2016, the price was around $500, while as of July 16, 2024, it was approximately $63,808.\n - This price increase represents a substantial growth of 12,662% over the specified period.\n\n2. **General Trend of BTC**:\n - Bitcoin's performance and price movements have a significant impact on the overall cryptocurrency market.\n - As the leading cryptocurrency, Bitcoin's trends often influence the direction of other cryptocurrencies in the market.\n - Bitcoin's market capitalization and year-over-year return of 111% indicate its dominance and continued relevance in the crypto space.\n\n3. **Market Caps and Pricing**:\n - The market capitalization and pricing data for Bitcoin and other cryptocurrencies can be sourced from platforms like CoinMarketCap, providing real-time information on their performance.\n\nIn summary, Bitcoin remains a key player in the cryptocurrency market, with its price movements and market capitalization influencing the broader trends in the industry. The growth and stability of Bitcoin serve as important indicators for investors and traders looking to understand the general trend of cryptocurrencies. [Sources: [Forbes Advisor](https://www.forbes.com/advisor/investing/cryptocurrency/top-10-cryptocurrencies/), [CoinTelegraph](https://cointelegraph.com/news/what-happened-in-crypto-today), [CNBC](https://www.cnbc.com/bitcoin/)]", 18 | ], 19 | }; 20 | const AnimatedText = ({ text }) => { 21 | const words = text.split(' '); 22 | return (react_1.default.createElement("div", { style: { display: 'inline-block' } }, words.map((word, index) => (react_1.default.createElement(framer_motion_1.motion.span, { key: index, initial: { opacity: 0, y: 50 }, animate: { opacity: 1, y: 0 }, transition: { delay: index * 0.1 }, style: { display: 'inline-block', marginRight: '5px' } }, word))))); 23 | }; 24 | function SubqueryComponent() { 25 | return (react_1.default.createElement("div", { style: { 26 | display: 'flex', 27 | justifyContent: 'center', 28 | alignItems: 'center', 29 | color: 'black', 30 | } }, data.subqueries_answered.map((query, index) => (react_1.default.createElement("div", { key: index, className: "dialogue-container" }, 31 | react_1.default.createElement("h2", null, 32 | react_1.default.createElement(AnimatedText, { text: query })), 33 | react_1.default.createElement("p", null, 34 | react_1.default.createElement(AnimatedText, { text: data.subqueries_responses[index] }))))))); 35 | } 36 | exports.default = SubqueryComponent; 37 | -------------------------------------------------------------------------------- /src/components/chat/ChatbotInput.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { 3 | Box, 4 | TextField, 5 | InputAdornment, 6 | IconButton, 7 | CircularProgress, 8 | Typography, 9 | } from '@mui/material'; 10 | import ArrowUpward from '@mui/icons-material/ArrowUpward'; 11 | import React from 'react'; 12 | 13 | const ChatbotInput = ({ 14 | isMobile, 15 | themeConfig, 16 | newMessage, 17 | setNewMessage, 18 | handleKeyDown, 19 | handleSendMessage, 20 | isAnyMessageLoading, 21 | multimodeChat, 22 | multimodeRenderFunction, 23 | }: { 24 | isMobile: boolean; 25 | themeConfig: any; 26 | newMessage: string; 27 | setNewMessage: (message: string) => void; 28 | handleKeyDown: (event: React.KeyboardEvent) => void; 29 | handleSendMessage: () => void; 30 | isAnyMessageLoading: boolean; 31 | multimodeChat: any; 32 | multimodeRenderFunction: (modes: string[]) => JSX.Element | null; 33 | }) => { 34 | const MultiModeRender = useCallback( 35 | (modes: string[]) => { 36 | return multimodeRenderFunction ? multimodeRenderFunction(modes) : null; 37 | }, 38 | [multimodeRenderFunction], 39 | ); 40 | 41 | return ( 42 | 48 | 55 | setNewMessage(e.target.value)} 62 | onKeyDown={handleKeyDown} 63 | size="small" 64 | label={ 65 | isAnyMessageLoading 66 | ? '' 67 | : themeConfig?.components?.TextField?.label || 'Ask our chatbot!' 68 | } 69 | InputProps={{ 70 | style: { 71 | ...themeConfig?.components?.TextField?.style, 72 | opacity: isAnyMessageLoading ? 0.2 : 1, 73 | }, 74 | endAdornment: ( 75 | 76 | {isAnyMessageLoading ? ( 77 | 78 | ) : ( 79 | 92 | 93 | 94 | )} 95 | 96 | ), 97 | }} 98 | /> 99 | {multimodeChat && 100 | MultiModeRender(Object.values(multimodeChat).map((item: any) => item.value))} 101 | 102 | 103 | {themeConfig?.components?.Disclaimer?.appears && ( 104 | 105 | {themeConfig?.components?.Disclaimer?.text || 106 | 'This is an open-source chatbot. Have some fun and enjoy! 🚀'} 107 | 108 | )} 109 | 110 | ); 111 | }; 112 | 113 | export default ChatbotInput; 114 | -------------------------------------------------------------------------------- /out/src/components/renderers/DefaultRenderers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var __importDefault = 3 | (this && this.__importDefault) || 4 | function (mod) { 5 | return mod && mod.__esModule ? mod : { default: mod }; 6 | }; 7 | Object.defineProperty(exports, '__esModule', { value: true }); 8 | const material_1 = require('@mui/material'); 9 | const react_1 = __importDefault(require('react')); 10 | const react_loader_spinner_1 = require('react-loader-spinner'); 11 | const defaultWelcomeMessageRenderFunction = (sendCustomMessage) => 12 | react_1.default.createElement( 13 | material_1.Box, 14 | { 15 | sx: { 16 | position: 'fixed', 17 | width: '100vw', 18 | top: '50%', 19 | left: '50%', 20 | transform: 'translate(-50%, -50%)', 21 | textAlign: 'center', 22 | }, 23 | }, 24 | react_1.default.createElement( 25 | material_1.Typography, 26 | { variant: 'h4', sx: { color: 'white' } }, 27 | 'Welcome! How can I help you today?', 28 | ), 29 | ); 30 | const defaultBotMessageRenderFunction = (message, input) => 31 | react_1.default.createElement( 32 | material_1.Box, 33 | { 34 | sx: { 35 | maxWidth: '100%', 36 | overflowWrap: 'break-word', 37 | }, 38 | }, 39 | react_1.default.createElement(material_1.Typography, null, message.text), 40 | ); 41 | const defaultUserMessageRenderFunction = (text) => 42 | react_1.default.createElement( 43 | material_1.Box, 44 | null, 45 | react_1.default.createElement(material_1.Typography, null, text), 46 | ); 47 | const defaultSubqueryRenderFunction = (subqueryQuestion, subqueryResponse) => 48 | react_1.default.createElement( 49 | material_1.Box, 50 | null, 51 | react_1.default.createElement( 52 | material_1.Typography, 53 | { variant: 'h5' }, 54 | subqueryQuestion.join(', '), 55 | ), 56 | react_1.default.createElement( 57 | material_1.Typography, 58 | { variant: 'h6' }, 59 | subqueryResponse.join(', '), 60 | ), 61 | ); 62 | const defaultLoadingRenderFunction = (text, themeConfig, subquery_arrays, type = 1) => { 63 | var _a, _b, _c, _d, _e, _f; 64 | return react_1.default.createElement( 65 | material_1.Box, 66 | { display: 'flex', flexDirection: 'row', alignItems: 'center' }, 67 | react_1.default.createElement(material_1.Avatar, { 68 | sx: Object.assign( 69 | { marginRight: '1rem' }, 70 | (_b = 71 | (_a = 72 | themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === 73 | null || _a === void 0 74 | ? void 0 75 | : _a.Avatar) === null || _b === void 0 76 | ? void 0 77 | : _b.style, 78 | ), 79 | src: 80 | (_d = 81 | (_c = 82 | themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === 83 | null || _c === void 0 84 | ? void 0 85 | : _c.Avatar) === null || _d === void 0 86 | ? void 0 87 | : _d.botAvatarUrl, 88 | }), 89 | react_1.default.createElement( 90 | material_1.Box, 91 | { 92 | sx: Object.assign( 93 | {}, 94 | (_f = 95 | (_e = 96 | themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === 97 | null || _e === void 0 98 | ? void 0 99 | : _e.LoaderBot) === null || _f === void 0 100 | ? void 0 101 | : _f.style, 102 | ), 103 | }, 104 | react_1.default.createElement(react_loader_spinner_1.DNA, { 105 | visible: true, 106 | height: '60', 107 | width: '60', 108 | ariaLabel: 'dna-loading', 109 | wrapperStyle: {}, 110 | wrapperClass: 'dna-wrapper', 111 | }), 112 | react_1.default.createElement(material_1.Typography, { sx: { marginLeft: '1rem' } }, text), 113 | ), 114 | ); 115 | }; 116 | const DefaultRenderFunctions = { 117 | defaultWelcomeMessageRenderFunction, 118 | defaultBotMessageRenderFunction, 119 | defaultUserMessageRenderFunction, 120 | defaultSubqueryRenderFunction, 121 | defaultLoadingRenderFunction, 122 | }; 123 | exports.default = DefaultRenderFunctions; 124 | -------------------------------------------------------------------------------- /out/src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var __createBinding = 3 | (this && this.__createBinding) || 4 | (Object.create 5 | ? function (o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | var desc = Object.getOwnPropertyDescriptor(m, k); 8 | if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) { 9 | desc = { 10 | enumerable: true, 11 | get: function () { 12 | return m[k]; 13 | }, 14 | }; 15 | } 16 | Object.defineProperty(o, k2, desc); 17 | } 18 | : function (o, m, k, k2) { 19 | if (k2 === undefined) k2 = k; 20 | o[k2] = m[k]; 21 | }); 22 | var __exportStar = 23 | (this && this.__exportStar) || 24 | function (m, exports) { 25 | for (var p in m) 26 | if (p !== 'default' && !Object.prototype.hasOwnProperty.call(exports, p)) 27 | __createBinding(exports, m, p); 28 | }; 29 | var __importDefault = 30 | (this && this.__importDefault) || 31 | function (mod) { 32 | return mod && mod.__esModule ? mod : { default: mod }; 33 | }; 34 | Object.defineProperty(exports, '__esModule', { value: true }); 35 | exports.DefaulRenderFunctions = 36 | exports.RenderFunctions = 37 | exports.useChatSocket = 38 | exports.ChatbotInput = 39 | exports.ChatbotCore = 40 | exports.useGptstonksChatbotTheme = 41 | exports.useChatbotDefaultTheme = 42 | exports.ChatbotHttp = 43 | exports.ChatbotWebsocketStreaming = 44 | exports.ChatbotWebsocket = 45 | void 0; 46 | var ChatbotWebsocket_1 = require('./layouts/ChatbotWebsocket'); 47 | Object.defineProperty(exports, 'ChatbotWebsocket', { 48 | enumerable: true, 49 | get: function () { 50 | return __importDefault(ChatbotWebsocket_1).default; 51 | }, 52 | }); 53 | var ChatbotWebsocketStreaming_1 = require('./layouts/ChatbotWebsocketStreaming'); 54 | Object.defineProperty(exports, 'ChatbotWebsocketStreaming', { 55 | enumerable: true, 56 | get: function () { 57 | return __importDefault(ChatbotWebsocketStreaming_1).default; 58 | }, 59 | }); 60 | var ChatbotHttp_1 = require('./layouts/ChatbotHttp'); 61 | Object.defineProperty(exports, 'ChatbotHttp', { 62 | enumerable: true, 63 | get: function () { 64 | return __importDefault(ChatbotHttp_1).default; 65 | }, 66 | }); 67 | var ChatbotDefaultTheme_1 = require('./components/chat/ChatbotDefaultTheme'); 68 | Object.defineProperty(exports, 'useChatbotDefaultTheme', { 69 | enumerable: true, 70 | get: function () { 71 | return __importDefault(ChatbotDefaultTheme_1).default; 72 | }, 73 | }); 74 | var GptstonksChatbotTheme_1 = require('./components/chat/GptstonksChatbotTheme'); 75 | Object.defineProperty(exports, 'useGptstonksChatbotTheme', { 76 | enumerable: true, 77 | get: function () { 78 | return __importDefault(GptstonksChatbotTheme_1).default; 79 | }, 80 | }); 81 | var ChatbotCore_1 = require('./components/chat/ChatbotCore'); 82 | Object.defineProperty(exports, 'ChatbotCore', { 83 | enumerable: true, 84 | get: function () { 85 | return __importDefault(ChatbotCore_1).default; 86 | }, 87 | }); 88 | var ChatbotInput_1 = require('./components/chat/ChatbotInput'); 89 | Object.defineProperty(exports, 'ChatbotInput', { 90 | enumerable: true, 91 | get: function () { 92 | return __importDefault(ChatbotInput_1).default; 93 | }, 94 | }); 95 | var useChatSocket_1 = require('./hooks/useChatSocket'); 96 | Object.defineProperty(exports, 'useChatSocket', { 97 | enumerable: true, 98 | get: function () { 99 | return __importDefault(useChatSocket_1).default; 100 | }, 101 | }); 102 | var RenderFunctions_1 = require('./components/renderers/RenderFunctions'); 103 | Object.defineProperty(exports, 'RenderFunctions', { 104 | enumerable: true, 105 | get: function () { 106 | return __importDefault(RenderFunctions_1).default; 107 | }, 108 | }); 109 | var DefaultRenderers_1 = require('./components/renderers/DefaultRenderers'); 110 | Object.defineProperty(exports, 'DefaulRenderFunctions', { 111 | enumerable: true, 112 | get: function () { 113 | return __importDefault(DefaultRenderers_1).default; 114 | }, 115 | }); 116 | // Type definitions 117 | __exportStar(require('./types/chatbot'), exports); 118 | __exportStar(require('./types/message'), exports); 119 | __exportStar(require('./types/component'), exports); 120 | __exportStar(require('./types/styles'), exports); 121 | -------------------------------------------------------------------------------- /src/app/streaming/CustomRenderers.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Avatar, Box, Typography, Button } from '@mui/material'; 3 | import { DNA, MutatingDots } from 'react-loader-spinner'; 4 | import SubqueryComponent from './test/Loading'; 5 | 6 | const WelcomeMessageRender = (sendCustomMessage: (message: string) => void) => ( 7 | 17 | 18 | Welcome! How can I help you today? 19 | 20 | 21 | ); 22 | 23 | const BotMessageRender = (message: any, input?: string) => ( 24 | 30 | {message.text} 31 | 32 | ); 33 | 34 | const UserMessageRender = (text: string) => ( 35 | 36 | {text} 37 | 38 | ); 39 | 40 | const SubqueryRender = (subqueryQuestion: string[], subqueryResponse: string[]) => ( 41 | 42 | {subqueryQuestion.join(', ')} 43 | {subqueryResponse.join(', ')} 44 | 45 | ); 46 | 47 | const ProviderRender = (providers: string[]) => ( 48 | 49 | {providers.join(', ')} 50 | 51 | ); 52 | 53 | const ErrorRenderFunction = (error: any) => ( 54 | 65 | {error} 66 | 67 | ); 68 | 69 | const LoadingMessageRender = ( 70 | text: string, 71 | themeConfig: any, 72 | subquery_arrays: any, 73 | type: number = 1, 74 | ) => { 75 | if (type === 1) { 76 | return ( 77 | 78 | 85 | 86 | 94 | {text} 95 | 96 | 97 | ); 98 | } else if (type === 2) { 99 | return ( 100 | 101 | 108 | 109 | 120 | {text} 121 | 122 | 123 | ); 124 | } else { 125 | return ( 126 | 127 | 134 | 135 | 136 | 137 | 138 | ); 139 | } 140 | }; 141 | 142 | export { 143 | WelcomeMessageRender, 144 | BotMessageRender, 145 | UserMessageRender, 146 | SubqueryRender, 147 | ProviderRender, 148 | ErrorRenderFunction, 149 | LoadingMessageRender, 150 | }; 151 | -------------------------------------------------------------------------------- /out/src/components/chat/ChatbotInput.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const react_1 = require("react"); 7 | const material_1 = require("@mui/material"); 8 | const ArrowUpward_1 = __importDefault(require("@mui/icons-material/ArrowUpward")); 9 | const react_2 = __importDefault(require("react")); 10 | const ChatbotInput = ({ isMobile, themeConfig, newMessage, setNewMessage, handleKeyDown, handleSendMessage, isAnyMessageLoading, multimodeChat, multimodeRenderFunction, }) => { 11 | var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x; 12 | const MultiModeRender = (0, react_1.useCallback)((modes) => { 13 | return multimodeRenderFunction ? multimodeRenderFunction(modes) : null; 14 | }, [multimodeRenderFunction]); 15 | return (react_2.default.createElement(material_1.Box, { sx: Object.assign(Object.assign({}, (_b = (_a = themeConfig.components) === null || _a === void 0 ? void 0 : _a.LowPartBox) === null || _b === void 0 ? void 0 : _b.style), { width: isMobile ? '90vw' : ((_e = (_d = (_c = themeConfig.components) === null || _c === void 0 ? void 0 : _c.LowPartBox) === null || _d === void 0 ? void 0 : _d.style) === null || _e === void 0 ? void 0 : _e.width) || '60%' }) }, 16 | react_2.default.createElement(material_1.Box, { sx: { 17 | display: 'flex', 18 | flexDirection: 'column', 19 | width: isMobile ? '90vw' : ((_h = (_g = (_f = themeConfig.components) === null || _f === void 0 ? void 0 : _f.LowPartBox) === null || _g === void 0 ? void 0 : _g.style) === null || _h === void 0 ? void 0 : _h.width) || '60%', 20 | } }, 21 | react_2.default.createElement(material_1.TextField, { fullWidth: ((_k = (_j = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _j === void 0 ? void 0 : _j.TextField) === null || _k === void 0 ? void 0 : _k.fullWidth) || true, multiline: true, minRows: 1, maxRows: 2, value: newMessage, onChange: (e) => setNewMessage(e.target.value), onKeyDown: handleKeyDown, size: "small", label: isAnyMessageLoading 22 | ? '' 23 | : ((_m = (_l = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _l === void 0 ? void 0 : _l.TextField) === null || _m === void 0 ? void 0 : _m.label) || 'Ask our chatbot!', InputProps: { 24 | style: Object.assign(Object.assign({}, (_p = (_o = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _o === void 0 ? void 0 : _o.TextField) === null || _p === void 0 ? void 0 : _p.style), { opacity: isAnyMessageLoading ? 0.2 : 1 }), 25 | endAdornment: (react_2.default.createElement(material_1.InputAdornment, { position: "end" }, isAnyMessageLoading ? (react_2.default.createElement(material_1.CircularProgress, { size: 24 })) : (react_2.default.createElement(material_1.IconButton, { onClick: handleSendMessage, disabled: isAnyMessageLoading, size: isMobile ? 'small' : 'medium', sx: Object.assign(Object.assign({}, (_r = (_q = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _q === void 0 ? void 0 : _q.Button) === null || _r === void 0 ? void 0 : _r.style), { '&:hover': { 26 | backgroundColor: ((_t = (_s = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _s === void 0 ? void 0 : _s.Button) === null || _t === void 0 ? void 0 : _t.hoverBackgroundColor) || '#b8bb26', 27 | }, minWidth: 'auto' }) }, 28 | react_2.default.createElement(ArrowUpward_1.default, { fontSize: isMobile ? 'small' : 'medium' }))))), 29 | } }), 30 | multimodeChat && 31 | MultiModeRender(Object.values(multimodeChat).map((item) => item.value))), 32 | ((_v = (_u = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _u === void 0 ? void 0 : _u.Disclaimer) === null || _v === void 0 ? void 0 : _v.appears) && (react_2.default.createElement(material_1.Typography, { sx: themeConfig.components.Disclaimer.style }, ((_x = (_w = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _w === void 0 ? void 0 : _w.Disclaimer) === null || _x === void 0 ? void 0 : _x.text) || 33 | 'This is an open-source chatbot. Have some fun and enjoy! 🚀')))); 34 | }; 35 | exports.default = ChatbotInput; 36 | -------------------------------------------------------------------------------- /docs/assets/fonts/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /docs/assets/site.js: -------------------------------------------------------------------------------- 1 | /* global anchors */ 2 | 3 | // add anchor links to headers 4 | anchors.options.placement = 'left'; 5 | anchors.add('h3'); 6 | 7 | // Filter UI 8 | var tocElements = document.getElementById('toc').getElementsByTagName('li'); 9 | 10 | document.getElementById('filter-input').addEventListener('keyup', function (e) { 11 | var i, element, children; 12 | 13 | // enter key 14 | if (e.keyCode === 13) { 15 | // go to the first displayed item in the toc 16 | for (i = 0; i < tocElements.length; i++) { 17 | element = tocElements[i]; 18 | if (!element.classList.contains('display-none')) { 19 | location.replace(element.firstChild.href); 20 | return e.preventDefault(); 21 | } 22 | } 23 | } 24 | 25 | var match = function () { 26 | return true; 27 | }; 28 | 29 | var value = this.value.toLowerCase(); 30 | 31 | if (!value.match(/^\s*$/)) { 32 | match = function (element) { 33 | var html = element.firstChild.innerHTML; 34 | return html && html.toLowerCase().indexOf(value) !== -1; 35 | }; 36 | } 37 | 38 | for (i = 0; i < tocElements.length; i++) { 39 | element = tocElements[i]; 40 | children = Array.from(element.getElementsByTagName('li')); 41 | if (match(element) || children.some(match)) { 42 | element.classList.remove('display-none'); 43 | } else { 44 | element.classList.add('display-none'); 45 | } 46 | } 47 | }); 48 | 49 | var items = document.getElementsByClassName('toggle-sibling'); 50 | for (var j = 0; j < items.length; j++) { 51 | items[j].addEventListener('click', toggleSibling); 52 | } 53 | 54 | function toggleSibling() { 55 | var stepSibling = this.parentNode.getElementsByClassName('toggle-target')[0]; 56 | var icon = this.getElementsByClassName('icon')[0]; 57 | var klass = 'display-none'; 58 | if (stepSibling.classList.contains(klass)) { 59 | stepSibling.classList.remove(klass); 60 | icon.innerHTML = '▾'; 61 | } else { 62 | stepSibling.classList.add(klass); 63 | icon.innerHTML = '▸'; 64 | } 65 | } 66 | 67 | function showHashTarget(targetId) { 68 | if (targetId) { 69 | var hashTarget = document.getElementById(targetId); 70 | // new target is hidden 71 | if ( 72 | hashTarget && 73 | hashTarget.offsetHeight === 0 && 74 | hashTarget.parentNode.parentNode.classList.contains('display-none') 75 | ) { 76 | hashTarget.parentNode.parentNode.classList.remove('display-none'); 77 | } 78 | } 79 | } 80 | 81 | function scrollIntoView(targetId) { 82 | // Only scroll to element if we don't have a stored scroll position. 83 | if (targetId && !history.state) { 84 | var hashTarget = document.getElementById(targetId); 85 | if (hashTarget) { 86 | hashTarget.scrollIntoView(); 87 | } 88 | } 89 | } 90 | 91 | function gotoCurrentTarget() { 92 | showHashTarget(location.hash.substring(1)); 93 | scrollIntoView(location.hash.substring(1)); 94 | } 95 | 96 | window.addEventListener('hashchange', gotoCurrentTarget); 97 | gotoCurrentTarget(); 98 | 99 | var toclinks = document.getElementsByClassName('pre-open'); 100 | for (var k = 0; k < toclinks.length; k++) { 101 | toclinks[k].addEventListener('mousedown', preOpen, false); 102 | } 103 | 104 | function preOpen() { 105 | showHashTarget(this.hash.substring(1)); 106 | } 107 | 108 | var split_left = document.querySelector('#split-left'); 109 | var split_right = document.querySelector('#split-right'); 110 | var split_parent = split_left.parentNode; 111 | var cw_with_sb = split_left.clientWidth; 112 | split_left.style.overflow = 'hidden'; 113 | var cw_without_sb = split_left.clientWidth; 114 | split_left.style.overflow = ''; 115 | 116 | Split(['#split-left', '#split-right'], { 117 | elementStyle: function (dimension, size, gutterSize) { 118 | return { 119 | 'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)', 120 | }; 121 | }, 122 | gutterStyle: function (dimension, gutterSize) { 123 | return { 124 | 'flex-basis': gutterSize + 'px', 125 | }; 126 | }, 127 | gutterSize: 20, 128 | sizes: [33, 67], 129 | }); 130 | 131 | // Chrome doesn't remember scroll position properly so do it ourselves. 132 | // Also works on Firefox and Edge. 133 | 134 | function updateState() { 135 | history.replaceState( 136 | { 137 | left_top: split_left.scrollTop, 138 | right_top: split_right.scrollTop, 139 | }, 140 | document.title, 141 | ); 142 | } 143 | 144 | function loadState(ev) { 145 | if (ev) { 146 | // Edge doesn't replace change history.state on popstate. 147 | history.replaceState(ev.state, document.title); 148 | } 149 | if (history.state) { 150 | split_left.scrollTop = history.state.left_top; 151 | split_right.scrollTop = history.state.right_top; 152 | } 153 | } 154 | 155 | window.addEventListener('load', function () { 156 | // Restore after Firefox scrolls to hash. 157 | setTimeout(function () { 158 | loadState(); 159 | // Update with initial scroll position. 160 | updateState(); 161 | // Update scroll positions only after we've loaded because Firefox 162 | // emits an initial scroll event with 0. 163 | split_left.addEventListener('scroll', updateState); 164 | split_right.addEventListener('scroll', updateState); 165 | }, 1); 166 | }); 167 | 168 | window.addEventListener('popstate', loadState); 169 | -------------------------------------------------------------------------------- /src/components/chat/GptstonksChatbotTheme.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ThemeConfig } from '@/types/chatbot'; 3 | 4 | const useGptstonksChatbotTheme: ThemeConfig = { 5 | chatLayoutConfig: { 6 | chatOrientation: 'vertical', 7 | avatarPosition: 'left', 8 | mobileLayout: { 9 | hideAvatar: false, 10 | messageMaxWidth: '100%', 11 | }, 12 | infiniteScroll: true, 13 | botMessageStackDirection: 'column', 14 | responseHeader: true, 15 | }, 16 | style: { 17 | justifyContent: 'center', 18 | height: '100%', 19 | alignItems: 'center', 20 | background: '#080808', 21 | scrollbarWidth: 'thin', 22 | scrollbarColor: 'yellow', 23 | }, 24 | palette: { 25 | primary: { main: '#fac670' }, 26 | secondary: { main: '#83a598' }, 27 | error: { main: '#fb4934' }, 28 | warning: { main: '#fe8019' }, 29 | info: { main: '#83a598' }, 30 | success: { main: '#b8bb26' }, 31 | background: { default: '#080808', paper: '#16181c' }, 32 | text: { primary: '#ebdbb2', secondary: '#d5c4a1' }, 33 | }, 34 | typography: { fontFamily: 'Poppins, sans-serif' }, 35 | components: { 36 | ChatBox: { 37 | style: { 38 | height: '100%', 39 | width: '100%', 40 | backgroundColor: 'transparent', 41 | fontFamily: 'Poppins, sans-serif', 42 | textAlign: 'left', 43 | alignItems: 'center', 44 | justifyContent: 'left', 45 | overflowY: 'auto', 46 | paddingTop: '2rem', 47 | '&::-webkit-scrollbar': { 48 | display: 'none', 49 | }, 50 | }, 51 | }, 52 | LowPartBox: { 53 | style: { 54 | display: 'flex', 55 | flexDirection: 'column', 56 | position: 'fixed', 57 | bottom: '30px', 58 | right: 0, 59 | left: 0, 60 | alignItems: 'center', 61 | justifyContent: 'space-between', 62 | margin: '0 auto', 63 | width: '70%', 64 | backgroundColor: 'transparent', 65 | }, 66 | }, 67 | TextField: { 68 | label: 'Type a message', 69 | fullWidth: false, 70 | style: { 71 | borderRadius: '30px', 72 | backgroundColor: '#1f1f1f', 73 | color: '#ebdbb2', 74 | '& label': { 75 | color: 'white', 76 | }, 77 | '& label.MuiFocused': { 78 | color: 'white', 79 | }, 80 | '& .MuiInputUnderline:after': { 81 | borderBottomColor: 'yellow', 82 | }, 83 | '& .MuiOutlinedInputRoot': { 84 | '& fieldset': { 85 | borderColor: 'white', 86 | opacity: '0.5', 87 | }, 88 | '&:hover fieldset': { 89 | borderColor: 'white', 90 | opacity: '0.8', 91 | }, 92 | '&.MuiFocused fieldset': { 93 | borderColor: '#ebdbb2', 94 | }, 95 | }, 96 | }, 97 | }, 98 | Button: { 99 | style: { 100 | padding: '6px 6px', 101 | color: '#ebdbb2', 102 | width: 'fit-content', 103 | }, 104 | hoverBackgroundColor: '#6b6b6b', 105 | }, 106 | Disclaimer: { 107 | appears: true, 108 | text: 'GPTStonks, your AI financial assistant.', 109 | style: { 110 | display: 'flex', 111 | justifyContent: 'center', 112 | alignItems: 'center', 113 | color: '#ebdbb2', 114 | fontSize: '0.75rem', 115 | marginTop: '0.5rem', 116 | }, 117 | }, 118 | MessageBubbleBot: { 119 | style: { 120 | alignItems: 'left', 121 | justifyContent: 'left', 122 | borderRadius: '10px', 123 | flexDirection: 'column', 124 | color: 'white', 125 | fontSize: '0.875rem', 126 | wordBreak: 'break-word', 127 | transition: 'opacity 0.5s ease-in-out', 128 | maxWidth: '100%', 129 | }, 130 | }, 131 | LoaderBot: { 132 | style: { 133 | backgroundColor: 'transparent', 134 | display: 'flex', 135 | color: 'white', 136 | alignItems: 'center', 137 | justifyContent: 'center', 138 | padding: '0.5rem 1rem', 139 | }, 140 | }, 141 | MessageBubbleUser: { 142 | style: { 143 | display: 'flex', 144 | flexDirection: 'row', 145 | justifyContent: 'left', 146 | textAlign: 'left', 147 | alignItems: 'center', 148 | color: 'white', 149 | fontSize: '1.5rem', 150 | transition: 'opacity 0.5s ease-in-out', 151 | wordBreak: 'break-word', 152 | }, 153 | loader: { 154 | color: '#b8bb26', 155 | backgroundColor: '#121214', 156 | }, 157 | }, 158 | Avatar: { 159 | botAvatarUrl: 'bytebard.png', 160 | userAvatarUrl: 'gptstonks_logo_small.png', 161 | showSideUserAvatar: false, 162 | showSideBotAvatar: false, 163 | style: { 164 | marginRight: '0.5em', 165 | width: 25, 166 | height: 25, 167 | backgroundColor: 'transparent', 168 | '& img': { 169 | width: '100%', 170 | height: '100%', 171 | objectFit: 'cover', 172 | }, 173 | }, 174 | }, 175 | Divider: { 176 | appears: false, 177 | style: { 178 | backgroundColor: '#b8bb26', 179 | width: '100%', 180 | display: 'flex', 181 | justifyContent: 'center', 182 | }, 183 | }, 184 | }, 185 | }; 186 | 187 | export default useGptstonksChatbotTheme; 188 | -------------------------------------------------------------------------------- /src/components/renderers/RenderFunctions.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react'; 2 | import { Box, Typography } from '@mui/material'; 3 | import { Message } from '@/types/message'; 4 | import { DNA, MutatingDots } from 'react-loader-spinner'; 5 | import { Avatar } from '@mui/material'; 6 | import { ThemeConfig } from '@/types/chatbot'; 7 | import SubqueryComponent from '@/app/streaming/test/Loading'; 8 | 9 | const RenderFunctions = ({ 10 | welcomeMessageRenderFunction, 11 | botMessageRenderFunction, 12 | userMessageRenderFunction, 13 | dataRenderFunction, 14 | providerRenderFunction, 15 | referenceRenderFunction, 16 | relatedQuestionsRenderFunction, 17 | subqueryRenderFunction, 18 | loadingRenderFunction, 19 | }: { 20 | welcomeMessageRenderFunction?: Function; 21 | botMessageRenderFunction?: Function; 22 | userMessageRenderFunction?: Function; 23 | dataRenderFunction?: Function; 24 | providerRenderFunction?: Function; 25 | referenceRenderFunction?: Function; 26 | relatedQuestionsRenderFunction?: Function; 27 | subqueryRenderFunction?: Function; 28 | loadingRenderFunction?: Function; 29 | }) => { 30 | const WelcomeMessageRender = useCallback( 31 | (sendCustomMessage: (message: string) => void) => { 32 | return welcomeMessageRenderFunction ? ( 33 | welcomeMessageRenderFunction(sendCustomMessage) 34 | ) : ( 35 | 45 | 46 | Welcome! How can I help you today? 47 | 48 | 49 | ); 50 | }, 51 | [welcomeMessageRenderFunction], 52 | ); 53 | 54 | const BotMessageRender = useCallback( 55 | (message: Message, input: string) => { 56 | return botMessageRenderFunction ? ( 57 | botMessageRenderFunction(message, input) 58 | ) : ( 59 | {message.text} 60 | ); 61 | }, 62 | [botMessageRenderFunction], 63 | ); 64 | 65 | const UserMessageRender = useCallback( 66 | (text: string) => { 67 | return userMessageRenderFunction ? ( 68 | userMessageRenderFunction(text) 69 | ) : ( 70 | 80 | {text} 81 | 82 | ); 83 | }, 84 | [userMessageRenderFunction], 85 | ); 86 | 87 | const DataRender = useCallback( 88 | (data: any) => { 89 | return dataRenderFunction ? dataRenderFunction(data) : null; 90 | }, 91 | [dataRenderFunction], 92 | ); 93 | 94 | const ProviderRender = useCallback( 95 | (providers: any) => { 96 | return providerRenderFunction ? providerRenderFunction(providers) : null; 97 | }, 98 | [providerRenderFunction], 99 | ); 100 | 101 | const ReferenceRender = useCallback( 102 | (reference: any) => { 103 | return referenceRenderFunction ? referenceRenderFunction(reference) : null; 104 | }, 105 | [referenceRenderFunction], 106 | ); 107 | 108 | const RelatedQuestionsRender = useCallback( 109 | (relatedQuestions: any, sendCustomMessage: (message: string) => void) => { 110 | return relatedQuestionsRenderFunction 111 | ? relatedQuestionsRenderFunction(relatedQuestions, sendCustomMessage) 112 | : null; 113 | }, 114 | [relatedQuestionsRenderFunction], 115 | ); 116 | 117 | const SubqueryRender = useCallback( 118 | (subqueryQuestion: any, subqueryResponse: any) => { 119 | return subqueryRenderFunction 120 | ? subqueryRenderFunction(subqueryQuestion, subqueryResponse) 121 | : null; 122 | }, 123 | [subqueryRenderFunction], 124 | ); 125 | 126 | const LoadingMessageRender = useCallback( 127 | (text: string, themeConfig: any, subquery_arrays: any, type: number = 1) => { 128 | return loadingRenderFunction ? ( 129 | loadingRenderFunction(text, themeConfig, subquery_arrays, type) 130 | ) : ( 131 | 132 | 139 | 140 | 148 | {text} 149 | 150 | 151 | ); 152 | }, 153 | [loadingRenderFunction], 154 | ); 155 | 156 | return { 157 | WelcomeMessageRender, 158 | BotMessageRender, 159 | UserMessageRender, 160 | DataRender, 161 | ProviderRender, 162 | ReferenceRender, 163 | RelatedQuestionsRender, 164 | SubqueryRender, 165 | LoadingMessageRender, 166 | }; 167 | }; 168 | 169 | export default RenderFunctions; 170 | -------------------------------------------------------------------------------- /src/app/streaming/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import useChatbotDefaultTheme from '@/components/chat/ChatbotDefaultTheme'; 3 | import ChatbotWebsocketStreaming from '@/layouts/ChatbotWebsocketStreaming'; 4 | import { MultimodeChat } from '@/types/chatbot'; 5 | import { Message } from '@/types/message'; 6 | import { Box, Button } from '@mui/material'; 7 | import React, { useEffect, useState, useRef } from 'react'; 8 | import { 9 | BotMessageRender, 10 | ErrorRenderFunction, 11 | LoadingMessageRender, 12 | ProviderRender, 13 | SubqueryRender, 14 | UserMessageRender, 15 | WelcomeMessageRender, 16 | } from './CustomRenderers'; 17 | import { useSearchParams } from 'next/navigation'; 18 | 19 | export default function Home() { 20 | // const params = useSearchParams(); 21 | 22 | const [initializedChat, setInitializedChat] = React.useState(false); 23 | const [chatData, setChatData] = React.useState(null); 24 | const [multimodeChat, setMultimodeChat] = useState({ 25 | mode1: { url_param: 'agent_mode', value: 'speed', isActivated: false }, 26 | mode2: { url_param: 'agent_mode', value: 'quality', isActivated: true }, 27 | }); 28 | 29 | const themeConfig = useChatbotDefaultTheme; 30 | 31 | const preloadedMessages: Message[] = [ 32 | { 33 | text: 'Hello! How can I help you today?', 34 | user: 'humanUser', 35 | }, 36 | { 37 | text: 'Hello!', 38 | user: 'botUser', 39 | }, 40 | ]; 41 | 42 | const [token, setToken] = useState(null); 43 | 44 | useEffect(() => { 45 | const storedToken = localStorage.getItem('userToken'); 46 | setToken(storedToken); 47 | }, []); 48 | 49 | const chatbotRef = useRef<{ 50 | handleSendCustomMessage: (message: string) => void; 51 | }>(null); 52 | 53 | // useEffect(() => { 54 | // if (params.has('query')) { 55 | // const encodedQuery = params.get('query'); 56 | // if (encodedQuery) { 57 | // const query = decodeURIComponent(encodedQuery); 58 | 59 | // console.log('Query:', query); 60 | 61 | // setTimeout(() => { 62 | // if (chatbotRef.current) { 63 | // chatbotRef.current.handleSendCustomMessage(query); 64 | // } 65 | // }, 1000); 66 | // } 67 | // } 68 | // }, []); 69 | 70 | const handleButtonClick = () => { 71 | if (chatbotRef.current) { 72 | chatbotRef.current.handleSendCustomMessage('Hello from parent!'); 73 | } 74 | }; 75 | 76 | return ( 77 |
87 |
88 | 89 |
90 | ( 94 | 101 | {modes.map((mode, index) => ( 102 | 116 | ))} 117 | 118 | )} 119 | preloadedMessages={preloadedMessages} 120 | apiConfig={{ 121 | queryEndpoint: 'ws://localhost:8000/chatws?token=' + token, 122 | queryParams: { 123 | type: 'type', 124 | data: 'result_data', 125 | text: 'body', 126 | reference: 'reference', 127 | related: 'related', 128 | stream: 'stream_step', 129 | subqueryQuestion: 'subqueries_answered', 130 | subqueryResponse: 'subqueries_responses', 131 | }, 132 | modelStepTypes: { 133 | world_knowledge: '📈 Navigating Economic Currents...', 134 | simple_reflection: 'Wrapping up...', 135 | other: 'Preparing content from...', 136 | }, 137 | }} 138 | themeConfig={themeConfig} 139 | setDataForParent={(data: any) => { 140 | setChatData(data); 141 | }} 142 | onApiResponseCode={(bool: boolean) => { 143 | setInitializedChat(bool); 144 | }} 145 | errorRenderFunction={ErrorRenderFunction} 146 | userMessageRenderFunction={UserMessageRender} 147 | botMessageRenderFunction={BotMessageRender} 148 | providerRenderFunction={ProviderRender} 149 | subqueryRenderFunction={SubqueryRender} 150 | welcomeMessageRenderFunction={WelcomeMessageRender} 151 | loaderType={3} 152 | loadingRenderFunction={LoadingMessageRender} 153 | /> 154 |
155 |
156 |
157 | ); 158 | } 159 | -------------------------------------------------------------------------------- /src/components/chat/ChatbotDefaultTheme.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ThemeConfig } from '@/types/chatbot'; 3 | 4 | const useChatbotDefaultTheme: ThemeConfig = { 5 | chatLayoutConfig: { 6 | chatOrientation: 'vertical', 7 | avatarPosition: 'left', 8 | mobileLayout: { 9 | hideAvatar: false, 10 | messageMaxWidth: '100%', 11 | }, 12 | infiniteScroll: true, 13 | botMessageStackDirection: 'column', 14 | responseHeader: false, 15 | }, 16 | style: { 17 | justifyContent: 'center', 18 | alignItems: 'center', 19 | background: '#080808', 20 | scrollbarWidth: 'thin', 21 | width: '100%', 22 | scrollbarColor: 'yellow', 23 | }, 24 | palette: { 25 | primary: { main: '#fac670' }, 26 | secondary: { main: '#83a598' }, 27 | error: { main: '#fb4934' }, 28 | warning: { main: '#fe8019' }, 29 | info: { main: '#83a598' }, 30 | success: { main: '#b8bb26' }, 31 | background: { default: '#080808', paper: '#16181c' }, 32 | text: { primary: '#ebdbb2', secondary: '#d5c4a1' }, 33 | }, 34 | //typography: { fontFamily: 'Saira Variable, sans-serif' }, 35 | components: { 36 | ChatBox: { 37 | style: { 38 | position: 'relative', 39 | background: 40 | 'radial-gradient(circle at top, #fffff0 0%, #e0e0d1 2.55%, #c1c1a3 7.5%, #a2a275 20%, #8b8b60 30%, #73734c 40%, #5b5b38 60%, #000000 100%);', 41 | //fontFamily: 'Saira Variable, sans-serif', 42 | minHeight: '80vh', 43 | maxHeight: '85vh', 44 | overflowY: 'auto', 45 | paddingTop: '2rem', 46 | paddingRight: '4rem', 47 | }, 48 | }, 49 | LowPartBox: { 50 | style: { 51 | display: 'flex', 52 | alignItems: 'center', 53 | flexDirection: 'column', 54 | justifyContent: 'space-between', 55 | padding: '1rem', 56 | margin: '0 auto', 57 | width: '80%', 58 | }, 59 | }, 60 | TextField: { 61 | label: 'Type a message', 62 | fullWidth: false, 63 | style: { 64 | //backgroundColor: '#070707', 65 | color: '#ebdbb2', 66 | '& label': { 67 | color: 'white', 68 | }, 69 | '& label.MuiFocused': { 70 | color: 'white', 71 | }, 72 | '& .MuiInputUnderline:after': { 73 | borderBottomColor: 'yellow', 74 | }, 75 | '& .MuiOutlinedInputRoot': { 76 | '& fieldset': { 77 | borderColor: 'white', 78 | opacity: '0.5', 79 | }, 80 | '&:hover fieldset': { 81 | borderColor: 'white', 82 | opacity: '0.8', 83 | }, 84 | '&.MuiFocused fieldset': { 85 | borderColor: '#ebdbb2', 86 | }, 87 | }, 88 | }, 89 | }, 90 | Button: { 91 | style: { 92 | minWidth: 'fit-content', 93 | padding: '6px 6px', 94 | color: '#fff', 95 | borderColor: '#b8bb26', 96 | width: 'fit-content', 97 | }, 98 | hoverBackgroundColor: '#fabd2f', 99 | }, 100 | Disclaimer: { 101 | appears: true, 102 | text: 'GPTStonks Chatbot - your open-source AI chatbot.', 103 | style: { 104 | display: 'flex', 105 | justifyContent: 'center', 106 | alignItems: 'center', 107 | color: '#ebdbb2', 108 | fontSize: '0.75rem', 109 | padding: '0.5rem', 110 | }, 111 | }, 112 | MessageBubbleBot: { 113 | style: { 114 | display: 'flex', 115 | alignItems: 'center', 116 | justifyContent: 'center', 117 | padding: '0.5rem 1rem', 118 | borderRadius: '10px', 119 | flexDirection: 'column', 120 | backgroundColor: '#121214', 121 | color: 'white', 122 | fontSize: '0.875rem', 123 | wordBreak: 'break-word', 124 | transition: 'opacity 0.5s ease-in-out', 125 | '&::-webkit-scrollbar': { 126 | width: '0.5em', 127 | }, 128 | '&::-webkit-scrollbar-track': { 129 | boxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)', 130 | }, 131 | '&::-webkit-scrollbar-thumb': { 132 | backgroundColor: '#ebdbb2', 133 | outline: '0.5px solid slategrey', 134 | }, 135 | }, 136 | }, 137 | LoaderBot: { 138 | style: { 139 | backgroundColor: 'transparent', 140 | display: 'flex', 141 | color: 'white', 142 | alignItems: 'center', 143 | justifyContent: 'center', 144 | padding: '0.5rem 1rem', 145 | }, 146 | }, 147 | MessageBubbleUser: { 148 | style: { 149 | display: 'flex', 150 | padding: '0.5rem 1rem', 151 | borderRadius: '10px', 152 | backgroundColor: '#121214', 153 | flexDirection: 'row-reverse', 154 | color: 'white', 155 | fontSize: '0.875rem', 156 | transition: 'opacity 0.5s ease-in-out', 157 | wordBreak: 'break-word', 158 | }, 159 | loader: { 160 | color: '#b8bb26', 161 | backgroundColor: '#121214', 162 | }, 163 | }, 164 | Avatar: { 165 | botAvatarUrl: 'bytebard.png', 166 | userAvatarUrl: 'gptstonks_logo_small.png', 167 | showSideUserAvatar: true, 168 | showSideBotAvatar: true, 169 | style: { 170 | width: 40, 171 | height: 40, 172 | marginRight: '0.5em', 173 | marginLeft: '0.5em', 174 | borderRadius: '50%', 175 | backgroundColor: 'transparent', 176 | '& img': { 177 | width: '100%', 178 | height: '100%', 179 | objectFit: 'cover', 180 | }, 181 | }, 182 | }, 183 | Divider: { 184 | appears: true, 185 | style: { 186 | backgroundColor: '#b8bb26', 187 | width: '100%', 188 | display: 'flex', 189 | justifyContent: 'center', 190 | }, 191 | }, 192 | }, 193 | }; 194 | 195 | export default useChatbotDefaultTheme; 196 | -------------------------------------------------------------------------------- /out/src/app/streaming/CustomRenderers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.LoadingMessageRender = exports.ErrorRenderFunction = exports.ProviderRender = exports.SubqueryRender = exports.UserMessageRender = exports.BotMessageRender = exports.WelcomeMessageRender = void 0; 7 | const react_1 = __importDefault(require("react")); 8 | const material_1 = require("@mui/material"); 9 | const react_loader_spinner_1 = require("react-loader-spinner"); 10 | const Loading_1 = __importDefault(require("./test/Loading")); 11 | const WelcomeMessageRender = (sendCustomMessage) => (react_1.default.createElement(material_1.Box, { sx: { 12 | position: 'fixed', 13 | width: '100vw', 14 | top: '50%', 15 | left: '50%', 16 | transform: 'translate(-50%, -50%)', 17 | textAlign: 'center', 18 | } }, 19 | react_1.default.createElement(material_1.Typography, { variant: "h4", sx: { color: 'white' } }, "Welcome! How can I help you today?"))); 20 | exports.WelcomeMessageRender = WelcomeMessageRender; 21 | const BotMessageRender = (message, input) => (react_1.default.createElement(material_1.Box, { sx: { 22 | maxWidth: '100%', 23 | overflowWrap: 'break-word', 24 | } }, 25 | react_1.default.createElement(material_1.Typography, null, message.text))); 26 | exports.BotMessageRender = BotMessageRender; 27 | const UserMessageRender = (text) => (react_1.default.createElement(material_1.Box, null, 28 | react_1.default.createElement(material_1.Typography, null, text))); 29 | exports.UserMessageRender = UserMessageRender; 30 | const SubqueryRender = (subqueryQuestion, subqueryResponse) => (react_1.default.createElement(material_1.Box, null, 31 | react_1.default.createElement(material_1.Typography, null, subqueryQuestion.join(', ')), 32 | react_1.default.createElement(material_1.Typography, null, subqueryResponse.join(', ')))); 33 | exports.SubqueryRender = SubqueryRender; 34 | const ProviderRender = (providers) => (react_1.default.createElement(material_1.Box, null, 35 | react_1.default.createElement(material_1.Typography, null, providers.join(', ')))); 36 | exports.ProviderRender = ProviderRender; 37 | const ErrorRenderFunction = (error) => (react_1.default.createElement(material_1.Box, { sx: { 38 | position: 'fixed', 39 | top: 0, 40 | left: '50%', 41 | transform: 'translateX(-50%)', 42 | padding: '3px 15px', 43 | zIndex: 1000, 44 | backgroundColor: 'rgba(255, 255, 255, 0.5)', 45 | } }, 46 | react_1.default.createElement(material_1.Typography, null, error))); 47 | exports.ErrorRenderFunction = ErrorRenderFunction; 48 | const LoadingMessageRender = (text, themeConfig, subquery_arrays, type = 1) => { 49 | var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; 50 | if (type === 1) { 51 | return (react_1.default.createElement(material_1.Box, { display: "flex", flexDirection: "row", alignItems: "center" }, 52 | react_1.default.createElement(material_1.Avatar, { sx: Object.assign({ marginRight: '1rem' }, (_b = (_a = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _a === void 0 ? void 0 : _a.Avatar) === null || _b === void 0 ? void 0 : _b.style), src: (_d = (_c = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _c === void 0 ? void 0 : _c.Avatar) === null || _d === void 0 ? void 0 : _d.botAvatarUrl }), 53 | react_1.default.createElement(material_1.Box, { sx: Object.assign({}, (_f = (_e = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _e === void 0 ? void 0 : _e.LoaderBot) === null || _f === void 0 ? void 0 : _f.style) }, 54 | react_1.default.createElement(react_loader_spinner_1.DNA, { visible: true, height: "60", width: "60", ariaLabel: "dna-loading", wrapperStyle: {}, wrapperClass: "dna-wrapper" }), 55 | react_1.default.createElement(material_1.Typography, { sx: { marginLeft: '1rem' } }, text)))); 56 | } 57 | else if (type === 2) { 58 | return (react_1.default.createElement(material_1.Box, { display: "flex", flexDirection: "row", alignItems: "center" }, 59 | react_1.default.createElement(material_1.Avatar, { sx: Object.assign({ marginRight: '1rem' }, (_h = (_g = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _g === void 0 ? void 0 : _g.Avatar) === null || _h === void 0 ? void 0 : _h.style), src: (_k = (_j = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _j === void 0 ? void 0 : _j.Avatar) === null || _k === void 0 ? void 0 : _k.botAvatarUrl }), 60 | react_1.default.createElement(material_1.Box, { sx: Object.assign({}, (_m = (_l = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _l === void 0 ? void 0 : _l.LoaderBot) === null || _m === void 0 ? void 0 : _m.style) }, 61 | react_1.default.createElement(react_loader_spinner_1.MutatingDots, { visible: true, height: "60", width: "60", color: "#4fa94d", secondaryColor: "#4fa94d", radius: "12.5", ariaLabel: "mutating-dots-loading", wrapperStyle: {}, wrapperClass: "" }), 62 | react_1.default.createElement(material_1.Typography, { sx: { marginLeft: '1rem' } }, text)))); 63 | } 64 | else { 65 | return (react_1.default.createElement(material_1.Box, { display: "flex", flexDirection: "row", alignItems: "center" }, 66 | react_1.default.createElement(material_1.Avatar, { sx: Object.assign({ marginRight: '1rem' }, (_p = (_o = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _o === void 0 ? void 0 : _o.Avatar) === null || _p === void 0 ? void 0 : _p.style), src: (_r = (_q = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _q === void 0 ? void 0 : _q.Avatar) === null || _r === void 0 ? void 0 : _r.botAvatarUrl }), 67 | react_1.default.createElement(material_1.Box, { sx: Object.assign({}, (_t = (_s = themeConfig === null || themeConfig === void 0 ? void 0 : themeConfig.components) === null || _s === void 0 ? void 0 : _s.LoaderBot) === null || _t === void 0 ? void 0 : _t.style) }, 68 | react_1.default.createElement(Loading_1.default, null)))); 69 | } 70 | }; 71 | exports.LoadingMessageRender = LoadingMessageRender; 72 | -------------------------------------------------------------------------------- /out/src/components/chat/GptstonksChatbotTheme.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const useGptstonksChatbotTheme = { 4 | chatLayoutConfig: { 5 | chatOrientation: 'vertical', 6 | avatarPosition: 'left', 7 | mobileLayout: { 8 | hideAvatar: false, 9 | messageMaxWidth: '100%', 10 | }, 11 | infiniteScroll: true, 12 | botMessageStackDirection: 'column', 13 | responseHeader: true, 14 | }, 15 | style: { 16 | justifyContent: 'center', 17 | height: '100%', 18 | alignItems: 'center', 19 | background: '#080808', 20 | scrollbarWidth: 'thin', 21 | scrollbarColor: 'yellow', 22 | }, 23 | palette: { 24 | primary: { main: '#fac670' }, 25 | secondary: { main: '#83a598' }, 26 | error: { main: '#fb4934' }, 27 | warning: { main: '#fe8019' }, 28 | info: { main: '#83a598' }, 29 | success: { main: '#b8bb26' }, 30 | background: { default: '#080808', paper: '#16181c' }, 31 | text: { primary: '#ebdbb2', secondary: '#d5c4a1' }, 32 | }, 33 | typography: { fontFamily: 'Poppins, sans-serif' }, 34 | components: { 35 | ChatBox: { 36 | style: { 37 | height: '100%', 38 | width: '100%', 39 | backgroundColor: 'transparent', 40 | fontFamily: 'Poppins, sans-serif', 41 | textAlign: 'left', 42 | alignItems: 'center', 43 | justifyContent: 'left', 44 | overflowY: 'auto', 45 | paddingTop: '2rem', 46 | '&::-webkit-scrollbar': { 47 | display: 'none', 48 | }, 49 | }, 50 | }, 51 | LowPartBox: { 52 | style: { 53 | display: 'flex', 54 | flexDirection: 'column', 55 | position: 'fixed', 56 | bottom: '30px', 57 | right: 0, 58 | left: 0, 59 | alignItems: 'center', 60 | justifyContent: 'space-between', 61 | margin: '0 auto', 62 | width: '70%', 63 | backgroundColor: 'transparent', 64 | }, 65 | }, 66 | TextField: { 67 | label: 'Type a message', 68 | fullWidth: false, 69 | style: { 70 | borderRadius: '30px', 71 | backgroundColor: '#1f1f1f', 72 | color: '#ebdbb2', 73 | '& label': { 74 | color: 'white', 75 | }, 76 | '& label.MuiFocused': { 77 | color: 'white', 78 | }, 79 | '& .MuiInputUnderline:after': { 80 | borderBottomColor: 'yellow', 81 | }, 82 | '& .MuiOutlinedInputRoot': { 83 | '& fieldset': { 84 | borderColor: 'white', 85 | opacity: '0.5', 86 | }, 87 | '&:hover fieldset': { 88 | borderColor: 'white', 89 | opacity: '0.8', 90 | }, 91 | '&.MuiFocused fieldset': { 92 | borderColor: '#ebdbb2', 93 | }, 94 | }, 95 | }, 96 | }, 97 | Button: { 98 | style: { 99 | padding: '6px 6px', 100 | color: '#ebdbb2', 101 | width: 'fit-content', 102 | }, 103 | hoverBackgroundColor: '#6b6b6b', 104 | }, 105 | Disclaimer: { 106 | appears: true, 107 | text: 'GPTStonks, your AI financial assistant.', 108 | style: { 109 | display: 'flex', 110 | justifyContent: 'center', 111 | alignItems: 'center', 112 | color: '#ebdbb2', 113 | fontSize: '0.75rem', 114 | marginTop: '0.5rem', 115 | }, 116 | }, 117 | MessageBubbleBot: { 118 | style: { 119 | alignItems: 'left', 120 | justifyContent: 'left', 121 | borderRadius: '10px', 122 | flexDirection: 'column', 123 | color: 'white', 124 | fontSize: '0.875rem', 125 | wordBreak: 'break-word', 126 | transition: 'opacity 0.5s ease-in-out', 127 | maxWidth: '100%', 128 | }, 129 | }, 130 | LoaderBot: { 131 | style: { 132 | backgroundColor: 'transparent', 133 | display: 'flex', 134 | color: 'white', 135 | alignItems: 'center', 136 | justifyContent: 'center', 137 | padding: '0.5rem 1rem', 138 | }, 139 | }, 140 | MessageBubbleUser: { 141 | style: { 142 | display: 'flex', 143 | flexDirection: 'row', 144 | justifyContent: 'left', 145 | textAlign: 'left', 146 | alignItems: 'center', 147 | color: 'white', 148 | fontSize: '1.5rem', 149 | transition: 'opacity 0.5s ease-in-out', 150 | wordBreak: 'break-word', 151 | }, 152 | loader: { 153 | color: '#b8bb26', 154 | backgroundColor: '#121214', 155 | }, 156 | }, 157 | Avatar: { 158 | botAvatarUrl: 'bytebard.png', 159 | userAvatarUrl: 'gptstonks_logo_small.png', 160 | showSideUserAvatar: false, 161 | showSideBotAvatar: false, 162 | style: { 163 | marginRight: '0.5em', 164 | width: 25, 165 | height: 25, 166 | backgroundColor: 'transparent', 167 | '& img': { 168 | width: '100%', 169 | height: '100%', 170 | objectFit: 'cover', 171 | }, 172 | }, 173 | }, 174 | Divider: { 175 | appears: false, 176 | style: { 177 | backgroundColor: '#b8bb26', 178 | width: '100%', 179 | display: 'flex', 180 | justifyContent: 'center', 181 | }, 182 | }, 183 | }, 184 | }; 185 | exports.default = useGptstonksChatbotTheme; 186 | -------------------------------------------------------------------------------- /out/src/app/streaming/page.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 'use client'; 3 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 4 | if (k2 === undefined) k2 = k; 5 | var desc = Object.getOwnPropertyDescriptor(m, k); 6 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 7 | desc = { enumerable: true, get: function() { return m[k]; } }; 8 | } 9 | Object.defineProperty(o, k2, desc); 10 | }) : (function(o, m, k, k2) { 11 | if (k2 === undefined) k2 = k; 12 | o[k2] = m[k]; 13 | })); 14 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 15 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 16 | }) : function(o, v) { 17 | o["default"] = v; 18 | }); 19 | var __importStar = (this && this.__importStar) || function (mod) { 20 | if (mod && mod.__esModule) return mod; 21 | var result = {}; 22 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 23 | __setModuleDefault(result, mod); 24 | return result; 25 | }; 26 | var __importDefault = (this && this.__importDefault) || function (mod) { 27 | return (mod && mod.__esModule) ? mod : { "default": mod }; 28 | }; 29 | Object.defineProperty(exports, "__esModule", { value: true }); 30 | const ChatbotDefaultTheme_1 = __importDefault(require("@/components/chat/ChatbotDefaultTheme")); 31 | const ChatbotWebsocketStreaming_1 = __importDefault(require("@/layouts/ChatbotWebsocketStreaming")); 32 | const material_1 = require("@mui/material"); 33 | const react_1 = __importStar(require("react")); 34 | const CustomRenderers_1 = require("./CustomRenderers"); 35 | function Home() { 36 | // const params = useSearchParams(); 37 | const [initializedChat, setInitializedChat] = react_1.default.useState(false); 38 | const [chatData, setChatData] = react_1.default.useState(null); 39 | const [multimodeChat, setMultimodeChat] = (0, react_1.useState)({ 40 | mode1: { url_param: 'agent_mode', value: 'speed', isActivated: false }, 41 | mode2: { url_param: 'agent_mode', value: 'quality', isActivated: true }, 42 | }); 43 | const themeConfig = ChatbotDefaultTheme_1.default; 44 | const preloadedMessages = [ 45 | { 46 | text: 'Hello! How can I help you today?', 47 | user: 'humanUser', 48 | }, 49 | { 50 | text: 'Hello!', 51 | user: 'botUser', 52 | }, 53 | ]; 54 | const [token, setToken] = (0, react_1.useState)(null); 55 | (0, react_1.useEffect)(() => { 56 | const storedToken = localStorage.getItem('userToken'); 57 | setToken(storedToken); 58 | }, []); 59 | const chatbotRef = (0, react_1.useRef)(null); 60 | // useEffect(() => { 61 | // if (params.has('query')) { 62 | // const encodedQuery = params.get('query'); 63 | // if (encodedQuery) { 64 | // const query = decodeURIComponent(encodedQuery); 65 | // console.log('Query:', query); 66 | // setTimeout(() => { 67 | // if (chatbotRef.current) { 68 | // chatbotRef.current.handleSendCustomMessage(query); 69 | // } 70 | // }, 1000); 71 | // } 72 | // } 73 | // }, []); 74 | const handleButtonClick = () => { 75 | if (chatbotRef.current) { 76 | chatbotRef.current.handleSendCustomMessage('Hello from parent!'); 77 | } 78 | }; 79 | return (react_1.default.createElement("main", { style: { 80 | display: 'flex', 81 | justifyContent: 'center', 82 | alignItems: 'center', 83 | height: '100vh', 84 | width: '100vw', 85 | backgroundColor: '#080808', 86 | } }, 87 | react_1.default.createElement("div", { style: { width: '20vw', height: '100%' } }), 88 | react_1.default.createElement(material_1.Button, { onClick: handleButtonClick }, "Send Message to Chatbot"), 89 | react_1.default.createElement("div", { style: { width: '100%', height: '100%' } }, 90 | react_1.default.createElement(ChatbotWebsocketStreaming_1.default, { ref: chatbotRef, multimodeChat: multimodeChat, multimodeRenderFunction: (modes) => (react_1.default.createElement(material_1.Box, { sx: { 91 | display: 'flex', 92 | justifyContent: 'center', 93 | gap: '10px', 94 | } }, modes.map((mode, index) => (react_1.default.createElement(material_1.Button, { key: index, onClick: () => { 95 | const newMultimodeChat = Object.assign({}, multimodeChat); 96 | Object.keys(newMultimodeChat).forEach((key) => { 97 | newMultimodeChat[key].isActivated = false; 98 | }); 99 | newMultimodeChat[`mode${index + 1}`].isActivated = true; 100 | setMultimodeChat(newMultimodeChat); 101 | console.log('Multimode chat:', newMultimodeChat); 102 | } }, mode))))), preloadedMessages: preloadedMessages, apiConfig: { 103 | queryEndpoint: 'ws://localhost:8000/chatws?token=' + token, 104 | queryParams: { 105 | type: 'type', 106 | data: 'result_data', 107 | text: 'body', 108 | reference: 'reference', 109 | related: 'related', 110 | stream: 'stream_step', 111 | subqueryQuestion: 'subqueries_answered', 112 | subqueryResponse: 'subqueries_responses', 113 | }, 114 | modelStepTypes: { 115 | world_knowledge: '📈 Navigating Economic Currents...', 116 | simple_reflection: 'Wrapping up...', 117 | other: 'Preparing content from...', 118 | }, 119 | }, themeConfig: themeConfig, setDataForParent: (data) => { 120 | setChatData(data); 121 | }, onApiResponseCode: (bool) => { 122 | setInitializedChat(bool); 123 | }, errorRenderFunction: CustomRenderers_1.ErrorRenderFunction, userMessageRenderFunction: CustomRenderers_1.UserMessageRender, botMessageRenderFunction: CustomRenderers_1.BotMessageRender, providerRenderFunction: CustomRenderers_1.ProviderRender, subqueryRenderFunction: CustomRenderers_1.SubqueryRender, welcomeMessageRenderFunction: CustomRenderers_1.WelcomeMessageRender, loaderType: 3, loadingRenderFunction: CustomRenderers_1.LoadingMessageRender })), 124 | react_1.default.createElement("div", { style: { width: '20vw', height: '100%' } }))); 125 | } 126 | exports.default = Home; 127 | -------------------------------------------------------------------------------- /out/src/components/chat/ChatbotDefaultTheme.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const useChatbotDefaultTheme = { 4 | chatLayoutConfig: { 5 | chatOrientation: 'vertical', 6 | avatarPosition: 'left', 7 | mobileLayout: { 8 | hideAvatar: false, 9 | messageMaxWidth: '100%', 10 | }, 11 | infiniteScroll: true, 12 | botMessageStackDirection: 'column', 13 | responseHeader: false, 14 | }, 15 | style: { 16 | justifyContent: 'center', 17 | alignItems: 'center', 18 | background: '#080808', 19 | scrollbarWidth: 'thin', 20 | width: '100%', 21 | scrollbarColor: 'yellow', 22 | }, 23 | palette: { 24 | primary: { main: '#fac670' }, 25 | secondary: { main: '#83a598' }, 26 | error: { main: '#fb4934' }, 27 | warning: { main: '#fe8019' }, 28 | info: { main: '#83a598' }, 29 | success: { main: '#b8bb26' }, 30 | background: { default: '#080808', paper: '#16181c' }, 31 | text: { primary: '#ebdbb2', secondary: '#d5c4a1' }, 32 | }, 33 | //typography: { fontFamily: 'Saira Variable, sans-serif' }, 34 | components: { 35 | ChatBox: { 36 | style: { 37 | position: 'relative', 38 | background: 'radial-gradient(circle at top, #fffff0 0%, #e0e0d1 2.55%, #c1c1a3 7.5%, #a2a275 20%, #8b8b60 30%, #73734c 40%, #5b5b38 60%, #000000 100%);', 39 | //fontFamily: 'Saira Variable, sans-serif', 40 | minHeight: '80vh', 41 | maxHeight: '85vh', 42 | overflowY: 'auto', 43 | paddingTop: '2rem', 44 | paddingRight: '4rem', 45 | }, 46 | }, 47 | LowPartBox: { 48 | style: { 49 | display: 'flex', 50 | alignItems: 'center', 51 | flexDirection: 'column', 52 | justifyContent: 'space-between', 53 | padding: '1rem', 54 | margin: '0 auto', 55 | width: '80%', 56 | }, 57 | }, 58 | TextField: { 59 | label: 'Type a message', 60 | fullWidth: false, 61 | style: { 62 | //backgroundColor: '#070707', 63 | color: '#ebdbb2', 64 | '& label': { 65 | color: 'white', 66 | }, 67 | '& label.MuiFocused': { 68 | color: 'white', 69 | }, 70 | '& .MuiInputUnderline:after': { 71 | borderBottomColor: 'yellow', 72 | }, 73 | '& .MuiOutlinedInputRoot': { 74 | '& fieldset': { 75 | borderColor: 'white', 76 | opacity: '0.5', 77 | }, 78 | '&:hover fieldset': { 79 | borderColor: 'white', 80 | opacity: '0.8', 81 | }, 82 | '&.MuiFocused fieldset': { 83 | borderColor: '#ebdbb2', 84 | }, 85 | }, 86 | }, 87 | }, 88 | Button: { 89 | style: { 90 | minWidth: 'fit-content', 91 | padding: '6px 6px', 92 | color: '#fff', 93 | borderColor: '#b8bb26', 94 | width: 'fit-content', 95 | }, 96 | hoverBackgroundColor: '#fabd2f', 97 | }, 98 | Disclaimer: { 99 | appears: true, 100 | text: 'GPTStonks Chatbot - your open-source AI chatbot.', 101 | style: { 102 | display: 'flex', 103 | justifyContent: 'center', 104 | alignItems: 'center', 105 | color: '#ebdbb2', 106 | fontSize: '0.75rem', 107 | padding: '0.5rem', 108 | }, 109 | }, 110 | MessageBubbleBot: { 111 | style: { 112 | display: 'flex', 113 | alignItems: 'center', 114 | justifyContent: 'center', 115 | padding: '0.5rem 1rem', 116 | borderRadius: '10px', 117 | flexDirection: 'column', 118 | backgroundColor: '#121214', 119 | color: 'white', 120 | fontSize: '0.875rem', 121 | wordBreak: 'break-word', 122 | transition: 'opacity 0.5s ease-in-out', 123 | '&::-webkit-scrollbar': { 124 | width: '0.5em', 125 | }, 126 | '&::-webkit-scrollbar-track': { 127 | boxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)', 128 | }, 129 | '&::-webkit-scrollbar-thumb': { 130 | backgroundColor: '#ebdbb2', 131 | outline: '0.5px solid slategrey', 132 | }, 133 | }, 134 | }, 135 | LoaderBot: { 136 | style: { 137 | backgroundColor: 'transparent', 138 | display: 'flex', 139 | color: 'white', 140 | alignItems: 'center', 141 | justifyContent: 'center', 142 | padding: '0.5rem 1rem', 143 | }, 144 | }, 145 | MessageBubbleUser: { 146 | style: { 147 | display: 'flex', 148 | padding: '0.5rem 1rem', 149 | borderRadius: '10px', 150 | backgroundColor: '#121214', 151 | flexDirection: 'row-reverse', 152 | color: 'white', 153 | fontSize: '0.875rem', 154 | transition: 'opacity 0.5s ease-in-out', 155 | wordBreak: 'break-word', 156 | }, 157 | loader: { 158 | color: '#b8bb26', 159 | backgroundColor: '#121214', 160 | }, 161 | }, 162 | Avatar: { 163 | botAvatarUrl: 'bytebard.png', 164 | userAvatarUrl: 'gptstonks_logo_small.png', 165 | showSideUserAvatar: true, 166 | showSideBotAvatar: true, 167 | style: { 168 | width: 40, 169 | height: 40, 170 | marginRight: '0.5em', 171 | marginLeft: '0.5em', 172 | borderRadius: '50%', 173 | backgroundColor: 'transparent', 174 | '& img': { 175 | width: '100%', 176 | height: '100%', 177 | objectFit: 'cover', 178 | }, 179 | }, 180 | }, 181 | Divider: { 182 | appears: true, 183 | style: { 184 | backgroundColor: '#b8bb26', 185 | width: '100%', 186 | display: 'flex', 187 | justifyContent: 'center', 188 | }, 189 | }, 190 | }, 191 | }; 192 | exports.default = useChatbotDefaultTheme; 193 | -------------------------------------------------------------------------------- /out/src/components/renderers/RenderFunctions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var __createBinding = 3 | (this && this.__createBinding) || 4 | (Object.create 5 | ? function (o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | var desc = Object.getOwnPropertyDescriptor(m, k); 8 | if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) { 9 | desc = { 10 | enumerable: true, 11 | get: function () { 12 | return m[k]; 13 | }, 14 | }; 15 | } 16 | Object.defineProperty(o, k2, desc); 17 | } 18 | : function (o, m, k, k2) { 19 | if (k2 === undefined) k2 = k; 20 | o[k2] = m[k]; 21 | }); 22 | var __setModuleDefault = 23 | (this && this.__setModuleDefault) || 24 | (Object.create 25 | ? function (o, v) { 26 | Object.defineProperty(o, 'default', { enumerable: true, value: v }); 27 | } 28 | : function (o, v) { 29 | o['default'] = v; 30 | }); 31 | var __importStar = 32 | (this && this.__importStar) || 33 | function (mod) { 34 | if (mod && mod.__esModule) return mod; 35 | var result = {}; 36 | if (mod != null) 37 | for (var k in mod) 38 | if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) 39 | __createBinding(result, mod, k); 40 | __setModuleDefault(result, mod); 41 | return result; 42 | }; 43 | Object.defineProperty(exports, '__esModule', { value: true }); 44 | const react_1 = __importStar(require('react')); 45 | const material_1 = require('@mui/material'); 46 | const react_loader_spinner_1 = require('react-loader-spinner'); 47 | const material_2 = require('@mui/material'); 48 | const RenderFunctions = ({ 49 | welcomeMessageRenderFunction, 50 | botMessageRenderFunction, 51 | userMessageRenderFunction, 52 | dataRenderFunction, 53 | providerRenderFunction, 54 | referenceRenderFunction, 55 | relatedQuestionsRenderFunction, 56 | subqueryRenderFunction, 57 | loadingRenderFunction, 58 | }) => { 59 | const WelcomeMessageRender = (0, react_1.useCallback)( 60 | (sendCustomMessage) => { 61 | return welcomeMessageRenderFunction 62 | ? welcomeMessageRenderFunction(sendCustomMessage) 63 | : react_1.default.createElement( 64 | material_1.Box, 65 | { 66 | sx: { 67 | position: 'fixed', 68 | width: '100vw', 69 | top: '50%', 70 | left: '50%', 71 | transform: 'translate(-50%, -50%)', 72 | textAlign: 'center', 73 | }, 74 | }, 75 | react_1.default.createElement( 76 | material_1.Typography, 77 | { variant: 'h4', sx: { color: 'white' } }, 78 | 'Welcome! How can I help you today?', 79 | ), 80 | ); 81 | }, 82 | [welcomeMessageRenderFunction], 83 | ); 84 | const BotMessageRender = (0, react_1.useCallback)( 85 | (message, input) => { 86 | return botMessageRenderFunction 87 | ? botMessageRenderFunction(message, input) 88 | : react_1.default.createElement(material_1.Typography, null, message.text); 89 | }, 90 | [botMessageRenderFunction], 91 | ); 92 | const UserMessageRender = (0, react_1.useCallback)( 93 | (text) => { 94 | return userMessageRenderFunction 95 | ? userMessageRenderFunction(text) 96 | : react_1.default.createElement( 97 | material_1.Typography, 98 | { 99 | variant: 'h4', 100 | sx: { 101 | overflow: 'hidden', 102 | display: '-webkit-box', 103 | WebkitLineClamp: 3, 104 | WebkitBoxOrient: 'vertical', 105 | textOverflow: 'ellipsis', 106 | }, 107 | }, 108 | text, 109 | ); 110 | }, 111 | [userMessageRenderFunction], 112 | ); 113 | const DataRender = (0, react_1.useCallback)( 114 | (data) => { 115 | return dataRenderFunction ? dataRenderFunction(data) : null; 116 | }, 117 | [dataRenderFunction], 118 | ); 119 | const ProviderRender = (0, react_1.useCallback)( 120 | (providers) => { 121 | return providerRenderFunction ? providerRenderFunction(providers) : null; 122 | }, 123 | [providerRenderFunction], 124 | ); 125 | const ReferenceRender = (0, react_1.useCallback)( 126 | (reference) => { 127 | return referenceRenderFunction ? referenceRenderFunction(reference) : null; 128 | }, 129 | [referenceRenderFunction], 130 | ); 131 | const RelatedQuestionsRender = (0, react_1.useCallback)( 132 | (relatedQuestions, sendCustomMessage) => { 133 | return relatedQuestionsRenderFunction 134 | ? relatedQuestionsRenderFunction(relatedQuestions, sendCustomMessage) 135 | : null; 136 | }, 137 | [relatedQuestionsRenderFunction], 138 | ); 139 | const SubqueryRender = (0, react_1.useCallback)( 140 | (subqueryQuestion, subqueryResponse) => { 141 | return subqueryRenderFunction 142 | ? subqueryRenderFunction(subqueryQuestion, subqueryResponse) 143 | : null; 144 | }, 145 | [subqueryRenderFunction], 146 | ); 147 | const LoadingMessageRender = (0, react_1.useCallback)( 148 | (text, themeConfig, subquery_arrays, type = 1) => { 149 | var _a, _b, _c, _d, _e, _f; 150 | return loadingRenderFunction 151 | ? loadingRenderFunction(text, themeConfig, subquery_arrays, type) 152 | : react_1.default.createElement( 153 | material_1.Box, 154 | { display: 'flex', flexDirection: 'row', alignItems: 'center' }, 155 | react_1.default.createElement(material_2.Avatar, { 156 | sx: Object.assign( 157 | { marginRight: '1rem' }, 158 | (_b = 159 | (_a = 160 | themeConfig === null || themeConfig === void 0 161 | ? void 0 162 | : themeConfig.components) === null || _a === void 0 163 | ? void 0 164 | : _a.Avatar) === null || _b === void 0 165 | ? void 0 166 | : _b.style, 167 | ), 168 | src: 169 | (_d = 170 | (_c = 171 | themeConfig === null || themeConfig === void 0 172 | ? void 0 173 | : themeConfig.components) === null || _c === void 0 174 | ? void 0 175 | : _c.Avatar) === null || _d === void 0 176 | ? void 0 177 | : _d.botAvatarUrl, 178 | }), 179 | react_1.default.createElement( 180 | material_1.Box, 181 | { 182 | sx: Object.assign( 183 | {}, 184 | (_f = 185 | (_e = 186 | themeConfig === null || themeConfig === void 0 187 | ? void 0 188 | : themeConfig.components) === null || _e === void 0 189 | ? void 0 190 | : _e.LoaderBot) === null || _f === void 0 191 | ? void 0 192 | : _f.style, 193 | ), 194 | }, 195 | react_1.default.createElement(react_loader_spinner_1.DNA, { 196 | visible: true, 197 | height: '60', 198 | width: '60', 199 | ariaLabel: 'dna-loading', 200 | wrapperStyle: {}, 201 | wrapperClass: 'dna-wrapper', 202 | }), 203 | react_1.default.createElement( 204 | material_1.Typography, 205 | { sx: { marginLeft: '1rem' } }, 206 | text, 207 | ), 208 | ), 209 | ); 210 | }, 211 | [loadingRenderFunction], 212 | ); 213 | return { 214 | WelcomeMessageRender, 215 | BotMessageRender, 216 | UserMessageRender, 217 | DataRender, 218 | ProviderRender, 219 | ReferenceRender, 220 | RelatedQuestionsRender, 221 | SubqueryRender, 222 | LoadingMessageRender, 223 | }; 224 | }; 225 | exports.default = RenderFunctions; 226 | -------------------------------------------------------------------------------- /src/layouts/ChatbotHttp.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { ChatbotProps } from '@/types/chatbot'; 3 | import { Message } from '@/types/message'; 4 | import { Divider, useMediaQuery } from '@mui/material'; 5 | import { ThemeProvider, createTheme } from '@mui/material/styles'; 6 | import React, { useEffect, useRef, useState } from 'react'; 7 | import ChatbotCore from '../components/chat/ChatbotCore'; 8 | import ChatbotInput from '../components/chat/ChatbotInput'; 9 | 10 | const ChatbotHttp: React.FC = ({ 11 | className, 12 | apiConfig, 13 | themeConfig, 14 | loaderType, 15 | setDataForParent, 16 | welcomeMessageRenderFunction, 17 | botMessageRenderFunction, 18 | userMessageRenderFunction, 19 | dataRenderFunction, 20 | providerRenderFunction, 21 | referenceRenderFunction, 22 | relatedQuestionsRenderFunction, 23 | multimodeChat, 24 | multimodeRenderFunction, 25 | loadingRenderFunction, 26 | subqueryRenderFunction, 27 | }: ChatbotProps) => { 28 | const humanUser = 'humanUser'; 29 | const botUser = 'botUser'; 30 | const isMobile = useMediaQuery('(max-width:750px)'); 31 | const customTheme = createTheme( 32 | themeConfig ? { palette: themeConfig.palette, typography: themeConfig.typography } : {}, 33 | ); 34 | const [messages, setMessages] = useState([]); 35 | const [newMessage, setNewMessage] = useState(''); 36 | const [botMessage, setBotMessage] = useState(null); 37 | const messagesEndRef = useRef(null); 38 | const [isAnyMessageLoading, setIsAnyMessageLoading] = useState(false); 39 | const [showLinearLoader, setShowLinearLoader] = useState(false); 40 | const [token, setToken] = useState(null); 41 | 42 | if (!apiConfig.queryEndpoint.startsWith('http')) { 43 | throw new Error('queryEndpoint should start with http:// or https:// for fetch'); 44 | } 45 | 46 | if (apiConfig.needsJWT && !apiConfig.token) { 47 | throw new Error('token is required for JWT authentication'); 48 | } else if (!apiConfig.needsJWT && apiConfig.token) { 49 | console.warn('token is not required for non-JWT authentication'); 50 | } else if (apiConfig.needsJWT && apiConfig.token) { 51 | setToken(localStorage.getItem(apiConfig.token)); 52 | } 53 | 54 | const handleFetchMessage = async () => { 55 | if (apiConfig.needsJWT && apiConfig.token && token) { 56 | const response = await fetch(apiConfig.queryEndpoint, { 57 | method: 'POST', 58 | headers: { 59 | 'Content-Type': 'application/json', 60 | Authorization: `Bearer ${token}`, 61 | }, 62 | body: JSON.stringify({ query: newMessage }), 63 | } as RequestInit); 64 | 65 | let messageData = await response.json(); 66 | let mappedData: { [key: string]: any } = {}; 67 | 68 | if (apiConfig.queryParams) { 69 | Object.entries(apiConfig.queryParams).forEach(([key, value]) => { 70 | mappedData[key] = messageData[value]; 71 | }); 72 | } 73 | 74 | let body = mappedData.text; 75 | let type = mappedData.type; 76 | let data = mappedData.data; 77 | let related = mappedData.related; 78 | let reference = mappedData.reference; 79 | /* console.log('body:', body); 80 | console.log('type:', type); 81 | console.log('data:', data); 82 | console.log('related:', related); 83 | console.log('reference:', reference); */ 84 | 85 | if (setDataForParent) { 86 | setDataForParent(mappedData); 87 | } 88 | 89 | const botMessage = { 90 | text: body, 91 | user: botUser, 92 | data: data, 93 | reference: reference, 94 | related: related, 95 | loading: false, 96 | }; 97 | setMessages((prevMessages) => [...prevMessages, botMessage]); 98 | } else { 99 | const response = await fetch(apiConfig.queryEndpoint, { 100 | method: 'POST', 101 | headers: { 102 | 'Content-Type': 'application/json', 103 | }, 104 | body: JSON.stringify({ query: newMessage }), 105 | } as RequestInit); 106 | 107 | let messageData = await response.json(); 108 | let mappedData: { [key: string]: any } = {}; 109 | 110 | if (apiConfig.queryParams) { 111 | Object.entries(apiConfig.queryParams).forEach(([key, value]) => { 112 | mappedData[key] = messageData[value]; 113 | }); 114 | } 115 | 116 | let body = mappedData.text; 117 | let type = mappedData.type; 118 | let data = mappedData.data; 119 | let related = mappedData.related; 120 | let reference = mappedData.reference; 121 | /* console.log('body:', body); 122 | console.log('type:', type); 123 | console.log('data:', data); 124 | console.log('related:', related); 125 | console.log('reference:', reference); */ 126 | 127 | if (setDataForParent) { 128 | setDataForParent(mappedData); 129 | } 130 | 131 | const botMessage = { 132 | text: body, 133 | user: botUser, 134 | data: data, 135 | reference: reference, 136 | related: related, 137 | loading: false, 138 | }; 139 | setMessages((prevMessages) => [...prevMessages, botMessage]); 140 | } 141 | }; 142 | 143 | const handleSendMessage = () => { 144 | handleFetchMessage(); 145 | 146 | const userMessage = { text: newMessage, user: humanUser, loading: false }; 147 | setMessages((prevMessages) => [...prevMessages, userMessage]); 148 | setNewMessage(''); 149 | }; 150 | 151 | const handleSendCustomMessage = (message: string) => { 152 | setNewMessage(message); 153 | handleFetchMessage(); 154 | 155 | const userMessage = { text: message, user: humanUser, loading: false }; 156 | setMessages((prevMessages) => [...prevMessages, userMessage]); 157 | setNewMessage(''); 158 | }; 159 | 160 | useEffect(() => { 161 | scrollToBottom(); 162 | }, [messages, isAnyMessageLoading]); 163 | 164 | const scrollToBottom = () => { 165 | messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); 166 | }; 167 | 168 | const handleKeyDown = (event: React.KeyboardEvent) => { 169 | if (event.key === 'Enter') { 170 | handleSendMessage(); 171 | event.preventDefault(); 172 | } 173 | }; 174 | 175 | return ( 176 |
182 | 183 | 206 | {themeConfig?.components?.Divider?.appears && ( 207 | 208 | )} 209 | 210 | multimodeRenderFunction?.(modes) ?? null} 220 | /> 221 | 222 |
223 | ); 224 | }; 225 | 226 | export default ChatbotHttp; 227 | -------------------------------------------------------------------------------- /src/layouts/ChatbotWebsocket.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { ChatbotProps } from '@/types/chatbot'; 3 | import { Message } from '@/types/message'; 4 | import { Dialog, Divider, useMediaQuery } from '@mui/material'; 5 | import { ThemeProvider, createTheme } from '@mui/material/styles'; 6 | import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; 7 | import { ReadyState } from 'react-use-websocket'; 8 | import ChatbotCore from '../components/chat/ChatbotCore'; 9 | import ChatbotInput from '../components/chat/ChatbotInput'; 10 | import useChatSocket from '../hooks/useChatSocket'; 11 | 12 | const ChatbotWebsocket: React.FC = ({ 13 | className, 14 | apiConfig, 15 | loaderType, 16 | themeConfig, 17 | setDataForParent, 18 | onApiResponseCode, 19 | sendCustomMessage, 20 | welcomeMessageRenderFunction, 21 | botMessageRenderFunction, 22 | userMessageRenderFunction, 23 | dataRenderFunction, 24 | providerRenderFunction, 25 | referenceRenderFunction, 26 | relatedQuestionsRenderFunction, 27 | subqueryRenderFunction, 28 | errorRenderFunction, 29 | multimodeChat, 30 | multimodeRenderFunction, 31 | loadingRenderFunction, 32 | }: ChatbotProps) => { 33 | const ErrorRender = useCallback( 34 | (error: any) => { 35 | return errorRenderFunction ? ( 36 | errorRenderFunction(error) 37 | ) : ( 38 | 39 |
46 | ⚠️ {error} 47 |
48 |
49 | ); 50 | }, 51 | [errorRenderFunction], 52 | ); 53 | 54 | const humanUser = 'humanUser'; 55 | const botUser = 'botUser'; 56 | const isMobile = useMediaQuery('(max-width:750px)'); 57 | const customTheme = createTheme( 58 | themeConfig ? { palette: themeConfig.palette, typography: themeConfig.typography } : {}, 59 | ); 60 | const [messages, setMessages] = useState([]); 61 | const [newMessage, setNewMessage] = useState(''); 62 | const [botMessage, setBotMessage] = useState(null); 63 | const messagesEndRef = useRef(null); 64 | const [isAnyMessageLoading, setIsAnyMessageLoading] = useState(false); 65 | const [showLinearLoader, setShowLinearLoader] = useState(false); 66 | const [token, setToken] = useState(null); 67 | const [graphData, setGraphData] = useState(null); 68 | 69 | if (!apiConfig?.queryEndpoint?.startsWith('ws')) { 70 | throw new Error('queryEndpoint should start with ws:// or wss:// for websocket'); 71 | } 72 | 73 | const wsUrl = useMemo(() => { 74 | return apiConfig.queryEndpoint || ''; 75 | }, [apiConfig.queryEndpoint]); 76 | 77 | const { sendMessage, lastMessage, connectionStatus, eventReason } = useChatSocket(wsUrl ?? ''); 78 | 79 | const handleSendMessage = () => { 80 | if (!newMessage.trim()) return; 81 | sendMessage(JSON.stringify({ query: newMessage })); 82 | 83 | const userMessage = { text: newMessage, user: humanUser, loading: false }; 84 | setMessages((prevMessages) => [...prevMessages, userMessage]); 85 | setNewMessage(''); 86 | }; 87 | 88 | const handleSendCustomMessage = (message: string) => { 89 | if (!message.trim()) return; 90 | sendMessage(JSON.stringify({ query: message })); 91 | 92 | const userMessage = { text: message, user: humanUser, loading: false }; 93 | setMessages((prevMessages) => [...prevMessages, userMessage]); 94 | }; 95 | 96 | useEffect(() => { 97 | if (onApiResponseCode && messages.length > 0) { 98 | onApiResponseCode(true); 99 | } 100 | }, [messages]); 101 | 102 | useEffect(() => { 103 | if (lastMessage !== null) { 104 | let messageData = JSON.parse(lastMessage.data); 105 | let mappedData: { [key: string]: any } = {}; 106 | 107 | if (apiConfig.queryParams) { 108 | Object.entries(apiConfig.queryParams).forEach(([key, value]) => { 109 | mappedData[key] = messageData[value]; 110 | }); 111 | } 112 | 113 | let body = mappedData.text; 114 | let type = mappedData.type; 115 | let data = mappedData.data; 116 | let related = mappedData.related; 117 | let reference = mappedData.reference; 118 | /* console.log('body:', body); 119 | console.log('type:', type); 120 | console.log('data:', data); 121 | console.log('related:', related); 122 | console.log('reference:', reference); */ 123 | 124 | if (setDataForParent) { 125 | setDataForParent(mappedData); 126 | } 127 | 128 | if (type === 'data' && data) { 129 | setGraphData(data); 130 | } 131 | 132 | let queryLoading = type !== 'data'; 133 | setIsAnyMessageLoading(queryLoading); 134 | 135 | if (queryLoading && type === 'model_step') { 136 | setBotMessage((prevBotMessage) => ({ 137 | text: body, 138 | user: botUser, 139 | loading: true, 140 | })); 141 | } else if (type === 'data') { 142 | setShowLinearLoader(true); 143 | 144 | setTimeout(() => { 145 | setMessages((prevMessages) => [ 146 | ...prevMessages, 147 | { 148 | text: body, 149 | user: botUser, 150 | graphData: data, 151 | related: related, 152 | reference: reference, 153 | loading: false, 154 | }, 155 | ]); 156 | setShowLinearLoader(false); 157 | setBotMessage(null); 158 | }, 3000); 159 | } 160 | } 161 | }, [lastMessage]); 162 | 163 | useEffect(() => { 164 | scrollToBottom(); 165 | }, [messages, lastMessage, isAnyMessageLoading]); 166 | 167 | const scrollToBottom = () => { 168 | messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); 169 | }; 170 | 171 | const handleKeyDown = (event: React.KeyboardEvent) => { 172 | if (event.key === 'Enter') { 173 | handleSendMessage(); 174 | event.preventDefault(); 175 | } 176 | }; 177 | 178 | return ( 179 |
185 | 186 | 187 | {connectionStatus === 'Closed' && 188 | ErrorRender(eventReason ? eventReason : 'Connection closed unexpectedly')} 189 | 212 | 213 | 214 | {themeConfig?.components?.Divider?.appears && ( 215 | 216 | )} 217 | 218 | multimodeRenderFunction?.(modes) ?? null} 228 | /> 229 | 230 |
231 | ); 232 | }; 233 | 234 | export default ChatbotWebsocket; 235 | -------------------------------------------------------------------------------- /public/bytebard.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 122 | 126 | 128 | 129 | 130 | 131 | 132 | 133 | 135 | 136 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /src/components/chat/ChatbotCore.tsx: -------------------------------------------------------------------------------- 1 | import { APIConfig, ThemeConfig } from '@/types/chatbot'; 2 | import { Message } from '@/types/message'; 3 | import { Avatar, Box, List, ListItem, Typography } from '@mui/material'; 4 | import DefaultRenderFunctions from '../renderers/DefaultRenderers'; 5 | import LinearBuffer from './LinearBuffer'; 6 | import React from 'react'; 7 | 8 | const { 9 | defaultWelcomeMessageRenderFunction, 10 | defaultBotMessageRenderFunction, 11 | defaultUserMessageRenderFunction, 12 | defaultSubqueryRenderFunction, 13 | defaultLoadingRenderFunction, 14 | } = DefaultRenderFunctions; 15 | 16 | const ChatbotCore = ({ 17 | messages, 18 | themeConfig, 19 | loaderType = 1, 20 | apiConfig, 21 | isMobile, 22 | botUser, 23 | humanUser, 24 | botMessage, 25 | messagesEndRef, 26 | isAnyMessageLoading, 27 | showLinearLoader, 28 | sendCustomMessage, 29 | welcomeMessageRenderFunction = defaultWelcomeMessageRenderFunction, 30 | botMessageRenderFunction = defaultBotMessageRenderFunction, 31 | userMessageRenderFunction = defaultUserMessageRenderFunction, 32 | dataRenderFunction = (data: any) => null, 33 | providerRenderFunction = (providers: string[]) => null, 34 | referenceRenderFunction = (reference: any) => null, 35 | relatedQuestionsRenderFunction = ( 36 | relatedQuestions: any, 37 | sendCustomMessage: (message: string) => void, 38 | ) => null, 39 | subqueryRenderFunction = defaultSubqueryRenderFunction, 40 | loadingRenderFunction = defaultLoadingRenderFunction, 41 | }: { 42 | messages: Message[]; 43 | themeConfig: ThemeConfig; 44 | loaderType?: number; 45 | isMobile: boolean; 46 | apiConfig: APIConfig; 47 | botUser: string; 48 | humanUser: string; 49 | botMessage: Message | null; 50 | messagesEndRef: any; 51 | isAnyMessageLoading: boolean; 52 | showLinearLoader: boolean; 53 | setDataForParent?: (data: any) => void; 54 | onApiResponseCode?: (bool: boolean) => void; 55 | multimodeRenderFunction?: (modes: string[]) => JSX.Element; 56 | errorRenderFunction?: (error: any) => JSX.Element; 57 | sendCustomMessage: (message: string) => void; 58 | welcomeMessageRenderFunction?: ( 59 | sendCustomMessage: (message: string) => void, 60 | ) => JSX.Element | null; 61 | botMessageRenderFunction?: (message: any, input: string) => JSX.Element | null; 62 | userMessageRenderFunction?: (text: string) => JSX.Element | null; 63 | dataRenderFunction?: (data: any) => JSX.Element | null; 64 | providerRenderFunction?: (providers: string[]) => JSX.Element | null; 65 | referenceRenderFunction?: (reference: any) => JSX.Element | null; 66 | relatedQuestionsRenderFunction?: ( 67 | relatedQuestions: any, 68 | sendCustomMessage: (message: string) => void, 69 | ) => JSX.Element | null; 70 | subqueryRenderFunction?: ( 71 | subqueryQuestion: string[], 72 | subqueryResponse: string[], 73 | ) => JSX.Element | null; 74 | loadingRenderFunction?: ( 75 | text: string, 76 | themeConfig: ThemeConfig, 77 | subquery_arrays: any, 78 | type: number, 79 | ) => JSX.Element | null; 80 | }) => { 81 | const subquery_arrays = { 82 | subqueryQuestions: botMessage?.subqueryQuestion, 83 | subqueryResponses: botMessage?.subqueryResponse, 84 | }; 85 | 86 | const getMessage = (text: string) => { 87 | if (apiConfig?.modelStepTypes) { 88 | const modelStepTypes = apiConfig.modelStepTypes; 89 | 90 | if (modelStepTypes.hasOwnProperty(text)) { 91 | return modelStepTypes[text]; 92 | } 93 | } 94 | 95 | return `Preparing content from ${text}...`; 96 | }; 97 | 98 | return ( 99 | 104 | {messages.length === 0 && welcomeMessageRenderFunction(sendCustomMessage)} 105 | 106 | {messages.map((message, index) => ( 107 | 118 | {!isMobile && 119 | ((themeConfig?.components?.Avatar?.showSideUserAvatar && 120 | message.user === humanUser) || 121 | (themeConfig?.components?.Avatar?.showSideBotAvatar && 122 | message.user === botUser)) && ( 123 | 134 | )} 135 | {isMobile && 136 | ((themeConfig?.components?.Avatar?.showSideUserAvatar && 137 | message.user === humanUser) || 138 | (themeConfig?.components?.Avatar?.showSideBotAvatar && 139 | message.user === botUser)) && ( 140 | 155 | )} 156 | {message.user === botUser ? ( 157 | 164 | {themeConfig.chatLayoutConfig?.responseHeader && ( 165 | 173 | 179 | 183 | Response 184 | 185 | 186 | )} 187 | 188 | 195 | 196 | {message.text && ( 197 | 206 | {botMessageRenderFunction(message, messages[index - 1]?.text)} 207 | 208 | )} 209 | 210 | 211 | {message.subqueryQuestion && 212 | message.subqueryResponse && 213 | subqueryRenderFunction(message.subqueryQuestion, message.subqueryResponse)} 214 | 215 | 216 | {message.providers && providerRenderFunction(message.providers)} 217 | 218 | 219 | {message.reference && referenceRenderFunction(message.reference)} 220 | 221 | {(message.streamCompleted || message.stream) && 222 | dataRenderFunction(message.graphData)} 223 | 224 | 225 | {message.related && 226 | relatedQuestionsRenderFunction(message.related, sendCustomMessage)} 227 | 228 | 229 | ) : ( 230 | 231 | {userMessageRenderFunction(message.text)} 232 | 233 | )} 234 | 235 | ))} 236 | {botMessage && isAnyMessageLoading && !showLinearLoader && ( 237 | 238 | {loadingRenderFunction( 239 | getMessage(botMessage.text), 240 | themeConfig, 241 | subquery_arrays, 242 | loaderType, 243 | )} 244 | 245 | )} 246 | {showLinearLoader && ( 247 | 250 | 257 | 258 | 259 | )} 260 | 261 | 262 |
263 |
264 | 265 | ); 266 | }; 267 | 268 | export default ChatbotCore; 269 | --------------------------------------------------------------------------------