Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Frevagpt #69

Open
wants to merge 137 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 127 commits
Commits
Show all changes
137 commits
Select commit Hold shift + click to select a range
75669d5
Boilerplate code for a chat-endpoint in react
Karinon Aug 13, 2024
99fa7e7
fixed some sorting issues for the linter...
Karinon Aug 13, 2024
30a9b54
Merge branch 'main' of github.com:FREVA-CLINT/freva-web into frevagpt
antarcticrainforest Aug 16, 2024
fade7ec
Catch vault connection errors.
antarcticrainforest Aug 16, 2024
e1a0c84
Add skeleton for bot.
antarcticrainforest Aug 16, 2024
f092315
Adapted bot menu entry
Aug 30, 2024
604cf5c
Added conversation functionality including codeblocks and images
Aug 30, 2024
5708ef5
Enabled environment variable handling, added dependencies
Aug 30, 2024
476e92f
Changed method of parsing and fetching data stream
Aug 30, 2024
76b0665
Updated webpack production configs
Aug 30, 2024
76415e1
Added keydown event to input to trigger bot
Sep 2, 2024
fd37b6c
Adapted to utilize Bootstrap
Sep 2, 2024
d5d95ba
Included thread id into conversation and fetching
Sep 5, 2024
3b6f788
Adapted styling of codeblock and conversation bubbles
Sep 6, 2024
bf5d0fe
Added sidebar
Sep 6, 2024
85232c6
Made Codeblock collapsible
Sep 6, 2024
ee64840
Added variant logs
Sep 6, 2024
487b9f7
Added thread si to url
Sep 9, 2024
ae4c3d1
Made thread id a ref instead of state varaible
Sep 9, 2024
aaaf4c1
merged current status of frevagpt
Sep 9, 2024
96eeeae
Outsourced sidepanel
Sep 9, 2024
2cb1965
WIP viewing old threads
Sep 9, 2024
368fa27
adapted conversation to support thread history, adapted codeblock
Sep 10, 2024
8a376f3
undone conversation changes
Sep 11, 2024
89890a2
added example request on climate data
Sep 11, 2024
b654c8f
Formatted Code String
Sep 12, 2024
be0ec6b
Changed data streaming to include buffer being parsed bit by bit
Sep 17, 2024
0057b1b
Adapted fetching of old thread
Sep 18, 2024
cdb9556
added example requests
Sep 18, 2024
5633336
Added hanling of markdown in response
Sep 18, 2024
496185f
Added differentiation for errors
Sep 18, 2024
2fb2510
Added button to stop request
Sep 18, 2024
60ec059
Awaiting whole anser of old thread
Sep 20, 2024
ce64419
Added code hilighting, updated examples using new code escaping backend
Sep 20, 2024
70592f1
Integrated stop button into input, added Button to start new chat
Sep 20, 2024
45029ff
Added Error Type to Output
Sep 23, 2024
2e1a744
Added freva config to bot request
Sep 23, 2024
132d88c
Codeoutput only displayed when content available
Sep 23, 2024
dd6a624
Introduced FrontendError
Sep 23, 2024
b63fcd9
removed additional encoding of user input
Sep 23, 2024
aba1639
disabled input during bot request
Sep 23, 2024
e827fc9
Hilighting manual stop by user
Sep 23, 2024
792f5a7
Refactored loading parameter
Sep 24, 2024
cfda87d
added fetch aborter
Sep 25, 2024
5e7f72d
hiding stop button while no request is done
Sep 25, 2024
939f547
resolved merge conflict
Sep 25, 2024
2ada6a9
changed encoding of user input for requests
Sep 26, 2024
024a422
update requests, added freva requests
Sep 26, 2024
8c12c01
removed console statement
Sep 26, 2024
5ca9378
WIP adaptation of freva bot to use redux
Sep 27, 2024
2ff088b
Moved example requests into own file unrelated to redux
Sep 27, 2024
b6e56ea
Moved helper function sinto untils file unrelated to redux
Sep 27, 2024
003026e
WIP refactoring to use redux for state management
Sep 27, 2024
122adb9
State management using redux
Oct 2, 2024
38e66ef
Resolved merge conflicts
Oct 2, 2024
75bd8d3
added example requests
Oct 2, 2024
d3f8a90
Added play button to chatbot input field
Oct 7, 2024
028c28a
Adapted user input to reset after submit
Oct 7, 2024
ee64fe2
Added hidden switch for selecting bot model
Oct 7, 2024
5cb7bf4
outsourced conversation block to optimize rendering and performance
Oct 8, 2024
5e8d261
added hidden toggle for bot select list
Oct 8, 2024
aa402b7
Fixed assessing thread for stopping request
Oct 17, 2024
fbc2da1
Included error logging for fetch request
BiancaWentzel Oct 18, 2024
1b20a6d
Added suggestion buttons to start conversation
Oct 30, 2024
9b82cbe
Added handling of unresponsible chatbot
Oct 30, 2024
10fac58
Adapted buttons and suggestions to provide inputvalue
Nov 1, 2024
27e1b06
Resolved missing ansynchronity during bot check
Nov 5, 2024
b2e3556
Seperated components into different render functions, covered display…
Nov 5, 2024
8c30e75
removed statement to hide component
Nov 5, 2024
7c1b41d
Adapted according to comments from #60
Nov 5, 2024
339bea7
Added tooltip to suggestion buttons
Nov 5, 2024
89e616c
Adapted suggestion buttons to use responsive grid system
Nov 6, 2024
e845ffe
WIP: fixing linting
Nov 12, 2024
77c5c09
Fixed linting
Nov 13, 2024
87e541c
Prettified code
Nov 13, 2024
d9e335b
Removed watch flag from dev build command
Nov 14, 2024
a977325
Merge pull request #60 from FREVA-CLINT/suggestions
BiancaWentzel Nov 14, 2024
878fa18
removed hidden statement, shortened Component call
Nov 14, 2024
4cac238
Adapted conditional rendering of alert
Nov 14, 2024
7bb01d0
Adapted ping request
Nov 14, 2024
17ce5b6
Merged current state of frevagpt branch
Nov 14, 2024
39a2482
Added support for markdown tables
Nov 15, 2024
c1f9260
Removed watch statement for tests
Nov 15, 2024
e3f990e
Fixed linting
Nov 15, 2024
08de41e
Fixed suggestion display for existing thread
Nov 15, 2024
8c482ef
Fixed linting
Nov 15, 2024
f5f512f
Merge pull request #66 from FREVA-CLINT/fix-suggestions
BiancaWentzel Nov 15, 2024
958677b
Merge branch 'frevagpt' into markdown-table-support
Nov 15, 2024
6f2587d
Merge pull request #65 from FREVA-CLINT/markdown-table-support
BiancaWentzel Nov 15, 2024
a668ab6
Merged from main
Nov 15, 2024
fbc2adf
Merge pull request #67 from FREVA-CLINT/update-from-main
BiancaWentzel Nov 18, 2024
e29989b
Adapted statement determining display of header
Nov 20, 2024
5e4eea6
Merge branch 'frevagpt' into unavailability
Nov 20, 2024
6e1acaf
Merge pull request #61 from FREVA-CLINT/unavailability
BiancaWentzel Nov 20, 2024
e18ea62
Included debug log
Nov 26, 2024
7f9483f
Adapted auth
Nov 26, 2024
06c3854
Changed proxy to enable streaming
Nov 28, 2024
ead2c1b
Live rendering of streamed data, restructured chatbot components
Nov 28, 2024
b0405e4
Fixed linting
Nov 28, 2024
f76a87b
Adapted spinner while response is streamed
Nov 28, 2024
243801f
Shortened proxy view
Dec 2, 2024
f463de6
Removed conditional rendering of Answer component enabling realtime r…
Dec 4, 2024
606018c
Adapted conditional rendering of spinner
Dec 4, 2024
af0b67a
Added code processing placeholder
Dec 4, 2024
df37b21
Handling of parsing error for streamed response
Dec 11, 2024
9649a58
Adapted bubble color for user input
Dec 11, 2024
6bae178
Adapted AnswerComponent to render code in real time
Dec 11, 2024
5996571
Fixed linting
Dec 11, 2024
f9fab2f
Resolved flickering issue of real time code rendering
Dec 11, 2024
c409b1e
Renamed component rendering streamed data in real time
Dec 11, 2024
0327f7e
Adapted PendingAnswerComponent and CodeBlock to look the same, define…
Dec 11, 2024
f745afb
Fixed linting
Dec 11, 2024
64f19d8
Outsourced assistant bubble style into a constant
Dec 11, 2024
c153a90
Merge pull request #68 from FREVA-CLINT/data-treaming
BiancaWentzel Dec 12, 2024
33179fe
Removed unused fragments
Dec 16, 2024
c80eb18
Added linting rule preventing one-line-statements without braces
Dec 16, 2024
6ac470c
Fixed linting
Dec 16, 2024
60d50b7
Exchanged console-error-statements with proper error handling
Dec 16, 2024
4903cfe
Exchanged third-party has with built-in hasOwn
Dec 16, 2024
0318363
Fixed requesting bot on clickung play button
Dec 16, 2024
217eca6
Submit request to backend only if userInput not empty
Dec 16, 2024
7be1cbc
Removed unused depedencies, including bootstrap icons
Dec 16, 2024
f77876f
Removed unused plugins, moved Dotenv to base config
Dec 16, 2024
f890cf5
Exchanged old icons with react icons
Dec 16, 2024
a2e1486
Removed unused rule
Dec 16, 2024
1ea7b93
Moved auth key and freva config to local environment used by proxyview
Dec 16, 2024
0e5c3fd
Using query-string instead of custom function
Dec 16, 2024
81c3f3f
Adapted SidePanel
Dec 16, 2024
617f010
Removed unused dependencies from webpack config
Jan 15, 2025
b5e28fb
Deleted empty file
Jan 15, 2025
8796deb
Added styling classes to input buttons
Jan 15, 2025
69aaa4b
Trimmed unnecessary spaces from input, preventing submission of empty…
Jan 15, 2025
69a1486
Added error handling to bot model request
Jan 15, 2025
465af02
Added error handling and message display on server error
Jan 15, 2025
73b9b1a
Fixed typo
Feb 3, 2025
1b6bfe3
Added timeout
Feb 3, 2025
9ea6059
Merge remote-tracking branch 'origin/frevagpt' into frevagpt
Feb 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@
{
"allowAllPropertiesOnSameLine": true
}
],
"curly": [
"warn",
"all"
]
}
}
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export EVALUATION_SYSTEM_CONFIG_FILE := $(PWD)/docker/local-eval-system.conf
export EVALUATION_SYSTEM_DRS_CONFIG_FILE := $(PWD)/docker/drs_config.toml
export DJANGO_SUPERUSER_PASSWORD := secret
export DEV_MODE := 1
export CHAT_BOT := 1
export COLUMNS=250
export DOCKER_ENV_FILE ?= .env
include $(DOCKER_ENV_FILE)
export
Expand Down
10 changes: 8 additions & 2 deletions assets/js/Containers/Databrowser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ class Databrowser extends React.Component {

return primaryFacets.map((key) => {
const value = facets[key];
if (!value) return undefined;
if (!value) {
return undefined;
}

return (
<FacetPanel
value={value}
Expand All @@ -169,7 +172,10 @@ class Databrowser extends React.Component {
})
.map((key) => {
const value = facets[key];
if (!value) return undefined;
if (!value) {
return undefined;
}

return (
<FacetPanel
value={value}
Expand Down
22 changes: 22 additions & 0 deletions assets/js/Containers/FrevaGPT/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as constants from "./constants";

export function setThread(thread_id) {
return {
type: "SET_THREAD",
payload: thread_id,
};
}

export function setConversation(conversation) {
return {
type: "SET_CONVERSATION",
payload: conversation,
};
}

export const addElement = (element) => (dispatch) => {
dispatch({
type: constants.ADD_ELEMENT,
payload: element,
});
};
139 changes: 139 additions & 0 deletions assets/js/Containers/FrevaGPT/components/ChatBlock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";

import { Col, Card } from "react-bootstrap";

import { isEmpty } from "lodash";

import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";

import { replaceLinebreaks } from "../utils";

import * as constants from "../constants";

import CodeBlock from "./CodeBlock";

class ChatBlock extends React.Component {
constructor(props) {
super(props);

this.renderImage = this.renderImage.bind(this);
this.renderCode = this.renderCode.bind(this);
this.renderUser = this.renderUser.bind(this);
this.renderError = this.renderError.bind(this);
this.renderDefault = this.renderDefault.bind(this);
}

renderImage(element) {
return (
<Col key={element.content} md={constants.BOT_COLUMN_STYLE}>
<img
className="w-100"
src={`data:image/jpeg;base64,${element.content}`}
/>
</Col>
);
}

renderCode(element) {
if (isEmpty(element.content[0])) {
return null;
} else {
return (
<Col md={constants.BOT_COLUMN_STYLE} key={element.content}>
<CodeBlock title={element.variant} code={element.content} />
</Col>
);
}
}

renderUser(element) {
return (
<Col md={{ span: 10, offset: 2 }} key={element.content}>
<Card
className="shadow-sm card-body border-0 border-bottom mb-3"
style={{ backgroundColor: "#eee" }}
>
{element.content}
</Card>
</Col>
);
}

renderError(element) {
return (
<Col md={constants.BOT_COLUMN_STYLE} key={element.content}>
<Card className="shadow-sm card-body border-0 border-bottom mb-3 bg-danger">
<span className="fw-bold">{element.variant}</span>
<ReactMarkdown>{replaceLinebreaks(element.content)}</ReactMarkdown>
</Card>
</Col>
);
}

renderDefault(element) {
return (
<Col md={constants.BOT_COLUMN_STYLE} key={element.content}>
<Card className="shadow-sm card-body border-0 border-bottom mb-3 bg-light">
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{replaceLinebreaks(element.content)}
</ReactMarkdown>
</Card>
</Col>
);
}

renderChatComponents(element) {
switch (element.variant) {
case "ServerHint":
case "StreamEnd":
return null;
case "Image":
return this.renderImage(element);

case "Code":
case "CodeOutput":
return this.renderCode(element);

case "User":
return this.renderUser(element);

case "ServerError":
case "OpenAIError":
case "CodeError":
case "FrontendError":
case "UserStop":
return this.renderError(element);

default:
return this.renderDefault(element);
}
}

render() {
const { conversation } = this.props.chatBlock;

return (
<Col>
{conversation.map((element) => {
return this.renderChatComponents(element);
})}
</Col>
);
}
}

ChatBlock.propTypes = {
chatBlock: PropTypes.shape({
thread: PropTypes.string,
conversation: PropTypes.array,
}),
};

const mapStateToProps = (state) => ({
chatBlock: state.frevaGPTReducer,
});

export default connect(mapStateToProps)(ChatBlock);
33 changes: 33 additions & 0 deletions assets/js/Containers/FrevaGPT/components/CodeBlock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import { Accordion } from "react-bootstrap";

import PropTypes from "prop-types";

import Highlight from "react-highlight";
import "highlight.js/styles/atom-one-light.css";

import { formatCode } from "../utils";

function CodeBlock(props) {
return (
<div className="mb-3">
<Accordion defaultActiveKey="0">
<Accordion.Item eventKey="0">
<Accordion.Header>python</Accordion.Header>
<Accordion.Body>
<Highlight className="python">
{formatCode(props.title, props.code[0])}
</Highlight>
</Accordion.Body>
</Accordion.Item>
</Accordion>
</div>
);
}

CodeBlock.propTypes = {
code: PropTypes.array,
title: PropTypes.string,
};

export default CodeBlock;
93 changes: 93 additions & 0 deletions assets/js/Containers/FrevaGPT/components/PendingAnswerComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";

import { Col, Card, Spinner, Accordion, Row } from "react-bootstrap";

import Markdown from "react-markdown";

import Highlight from "react-highlight";
import "highlight.js/styles/atom-one-light.css";

import * as constants from "../constants";

function PendingAnswerComponent(props) {
const [renderedCode, setRenderedCode] = useState("");

useEffect(() => {
const parsedCode = renderCode(props.content);
if (parsedCode !== "") {
setRenderedCode(parsedCode);
}
}, [props.content]);

function renderCode(rawCode) {
let jsonCode = "";
let codeSnippets = "";

if (!rawCode.endsWith('"}')) {
jsonCode = rawCode + '"}';
} else {
jsonCode = rawCode;
}

try {
const code = JSON.parse(jsonCode);
codeSnippets = code.code;
} catch (err) {
// console.error(err);
}
return codeSnippets;
}

function renderAnswer(props) {
switch (props.variant) {
case "Assistant":
return (
<Col md={constants.BOT_COLUMN_STYLE}>
<Card className="shadow-sm card-body border-0 border-bottom mb-3 bg-light">
<Markdown>{props.content}</Markdown>
</Card>
</Col>
);
case "Code":
case "CodeBlock":
return (
<Col md={constants.BOT_COLUMN_STYLE}>
<div className="mb-3">
<Accordion defaultActiveKey="0">
<Accordion.Item eventKey="0">
<Accordion.Header>python</Accordion.Header>
<Accordion.Body>
<Highlight className="python">{renderedCode}</Highlight>
<span>
<Spinner size="sm" />
<span className="m-2">Analyzing...</span>
</span>
</Accordion.Body>
</Accordion.Item>
</Accordion>
</div>
</Col>
);
case "ServerHint":
return (
<Row className="mb-3">
<Col md={1}>
<Spinner />
</Col>
</Row>
);
default:
return null;
}
}

return renderAnswer(props);
}

PendingAnswerComponent.propTypes = {
content: PropTypes.string,
variant: PropTypes.string,
};

export default PendingAnswerComponent;
63 changes: 63 additions & 0 deletions assets/js/Containers/FrevaGPT/components/SidePanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from "react";
import { Card } from "react-bootstrap";

import { browserHistory } from "react-router";

import { botRequests } from "../exampleRequests";

function SidePanel() {
function changeToThread(thread) {
browserHistory.push({
pathname: "/chatbot/",
search: `?thread_id=${thread}`,
});
}

return (
<div>
<Card className="mb-3 shadow-sm">
<div className="btn btn-outline-secondary border-0 p-3 rounded-top text-start card-header shadow-sm button-div">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • The outer div doesn't seem necessary, you can replace it by a simple <>
  • Don't use btn here. Due to the btn the user experience here implies that the Header of the section/Card is clickable, which it isn't. A simple <Card.Header> is fine as well
  • Likewise, <Card.Body> looks fine for me, too. It isn't collapsible.
  • Maybe add some vertical margins between the links. It is visually a bit hard to distinguish between the different links.
  • What's the point of hiding the link to the thread behind a onClick? I think a <a className="text-wrap" href={`/chatbot/?thread_id=${element.thread}`} > would be totally fine. It would be even better, if you could use <Link to... instead (from import { Link } from "react-router";) because it wouldn't cause the whole website to reload and the user would stay inside react, but this would need more adjustments.

General requests
</div>
<div className="p-3 py-2 collapse show">
{botRequests.general.map((element) => {
return (
<div key={element.thread}>
<a
className="text-wrap"
href=""
onClick={() => changeToThread(element.thread)}
>
{element.title}
</a>
</div>
);
})}
</div>
</Card>

<Card className="mb-3 shadow-sm">
<div className="btn btn-outline-secondary border-0 p-3 rounded-top text-start card-header shadow-sm button-div">
Freva requests
</div>
<div className="p-3 py-2 collapse show">
{botRequests.freva.map((element) => {
return (
<div key={element.thread}>
<a
className="text-wrap"
href=""
onClick={() => changeToThread(element.thread)}
>
{element.title}
</a>
</div>
);
})}
</div>
</Card>
</div>
);
}

export default SidePanel;
Loading
Loading