Skip to content

Commit

Permalink
Chatbox improve (#70)
Browse files Browse the repository at this point in the history
* retrieve max_tokens from request

Signed-off-by: cbh778899 <[email protected]>

* add max_tokens & new lines when got \n

Signed-off-by: cbh778899 <[email protected]>

* remove dot animation on received message

Signed-off-by: cbh778899 <[email protected]>

* try-catch json parse errors to prevent when content is too long to receive

Signed-off-by: cbh778899 <[email protected]>

* replace all double-space to \xa0\xa0

Signed-off-by: cbh778899 <[email protected]>

* Add demo_ui.py to project (#68)

* Add demo_ui.py to project

Uploaded demo_ui.py file to project example folder. 

Signed-off-by: Zuhayer C <[email protected]>

* Replace "Customary xxxxxx: chatbot" with project name

Signed-off-by: Zuhayer C <[email protected]>

---------

Signed-off-by: Zuhayer C <[email protected]>

* update README

Signed-off-by: cbh778899 <[email protected]>

---------

Signed-off-by: cbh778899 <[email protected]>
Signed-off-by: Zuhayer C <[email protected]>
Co-authored-by: Zuhayer C <[email protected]>
  • Loading branch information
cbh778899 and ZooHigher26 committed Aug 30, 2024
1 parent a5eba68 commit 4a480db
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 24 deletions.
47 changes: 31 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,45 @@ make dev
```
**NOTE:** `make dev` Requires Node.js environment installed, or at least have `node_modules` specified in `package.json` installed on your server. Please see [Local Machine](#local-machine) section.

## Embed your chatbot into website
To embed a chatbot to your website, simply add
## Lint
To start lint your code, simply run
```shell
npm run lint
```

## APIs

### Docs
Go to the url of your project, default [http://localhost:8000](http://localhost:8000) if you didn't disabled the `Docs` route, then you can see docs and try it on.
See [demo video](#setup-and-api-usage-demo-video).

### Monitor
This project got monitor build with swagger-stats, when you got this project running, just go to `<Your Server>:<Your Port>/stats`.
For example, [http://localhost:8000/stats](http://localhost:8000/stats)

### Chatbox
> When you set up the project and didn't disabled the `chatbox` API, you can get a quick-setup chatbot with some basic styles on your own website, which calls the `/v1/chat/completions` API for inference.
To set it up, simply add
```html
<script src='http://localhost:8000/chatbox?base_url=http%3A%2F%2Flocalhost%3A8000' defer></script>
<script src='http://localhost:8000/chatbox' defer></script>
```
into the bottom of your html body element. So easy!
Please change the `http://localhost:8000` and the base_url in request query to your real host to make sure it works.

If you want to hide the real link, in your javascript code you can do
```js
const chatbox_script = await (await fetch("http://localhost:8000/chatbox?base_url=http%3A%2F%2Flocalhost%3A8000")).blob();
const chatbox_script = await (await fetch("http://localhost:8000/chatbox")).blob();
const chatbox_url = URL.createObjectURL(chatbox_script);
const script_elem = document.createElement('script');
script_elem.src = chatbox_url;
document.body.append(script_elem);
```
And remember to use `URL.revokeObjectURL(chatbox_url)` if you don't need it anymore.

## Lint
To start lint your code, simply run
```shell
npm run lint
```

## Monitor
This project got monitor build with swagger-stats, when you got this project running, just go to `<Your Server>:<Your Port>/stats`.
For example, [http://localhost:8000/stats](http://localhost:8000/stats)
And remember to use `URL.revokeObjectURL(chatbox_url)` if you don't need it anymore.

Extra parameters ([request query](https://en.wikipedia.org/wiki/Query_string)) you can add to it are:
* `base_url`: `String`
> Add this when in production, otherwise the requests won't send to correct route.
> Default `http://localhost:8000`.
* `max_tokens`: `Integer`
> Add this when you want to limit tokens can be generated, is useful in production.
> Default `128`
7 changes: 6 additions & 1 deletion actions/inference.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ async function doInference(req_body, callback, isStream) {
const { value, done } = await reader.read();
if(done) break;
const data = value.split("data: ").pop()
callback(JSON.parse(data));
try {
callback(JSON.parse(data));
} catch(error) {
console.log(error)
callback({content: "", stop: true})
}
}
} else {
const eng_resp = await post('completion', { body: req_body });
Expand Down
3 changes: 2 additions & 1 deletion routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ function indexRoute() {

if(isRouteEnabled("index", "chatbox")) {
router.get('/chatbox', (req, res)=>{
const { base_url, max_tokens } = req.query;
res.setHeader("Content-Type", "application/json; charset=utf-8")
res.send(generateScript(req.query.base_url));
res.send(generateScript(base_url, max_tokens));
})
}

Expand Down
39 changes: 33 additions & 6 deletions tools/web_embed.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Generates the script with base_url, to simply embed a chatbot in web page
* @param {String} base_url The url to send request, default `http://localhost:8000`
*/
export function generateScript(base_url = 'http://localhost:8000') {
export function generateScript(base_url = 'http://localhost:8000', max_tokens = 128) {
return `
(function() {
'use strict';
Expand Down Expand Up @@ -105,6 +105,7 @@ const styles = \`
border-radius: 20px;
border: 1px solid gray;
padding: 0px 40px 0px 10px;
box-sizing: border-box;
}
Expand Down Expand Up @@ -176,6 +177,7 @@ const styles = \`
top: 40px;
display: block;
overflow-y: auto;
overflow-x: hidden;
padding: 20px;
box-sizing: border-box;
}
Expand All @@ -188,6 +190,12 @@ const styles = \`
text-align: center;
text-decoration: none;
display: block;
transition-duration: .3s;
}
.chatbox > .expanded-page > .conversations > .power-by:hover {
transform: scale(1.2);
font-weight: bold;
}
.chatbox > .expanded-page > .conversations > .bubble {
Expand All @@ -199,6 +207,8 @@ const styles = \`
margin: auto;
font-size: 17px;
margin-bottom: 10px;
word-wrap: break-word;
max-width: calc(100% - 40px);
}
.chatbox > .expanded-page > .conversations > .bubble.empty {
Expand Down Expand Up @@ -291,7 +301,9 @@ const styles = \`
function createElement(tagName, className, textContent) {
const elem = document.createElement(tagName);
elem.className = className;
elem.textContent = textContent;
textContent.split("\\n").forEach(content=>{
elem.append(content, document.createElement("br"))
})
return elem;
}
Expand All @@ -313,22 +325,37 @@ const styles = \`
{role: 'system', content: "You are a helpful assistant solves problem"},
{role: 'user', content: message}
],
stream: true
stream: true,
max_tokens: ${max_tokens}
})
});
if(resp.ok) {
const reader = resp.body.pipeThrough(new TextDecoderStream()).getReader();
let response = ''
let response = '', started = false;
while(true) {
const { value, done } = await reader.read();
if(!started) {
started = true;
pending_conversation.textContent = '';
}
if(done) break;
try {
value.split("\\n\\n").forEach(json_str => {
if(json_str) {
const { choices } = JSON.parse(json_str);
const content = choices[0].delta.content
let content = choices[0].delta.content
content = content.replaceAll(" ", "\\xa0\\xa0");
response += content;
pending_conversation.textContent = response;
if(content.includes("\\n")) {
const content_parts = content.split("\\n")
const arr_len = content_parts.length - 1;
for(let i = 0; i < content_parts.length; i++) {
pending_conversation.append(content_parts[i])
if(i < arr_len) {
pending_conversation.append(document.createElement("br"));
}
}
} else pending_conversation.append(content);
conversation_main.scrollTo({
behavior: "smooth",
top: conversation_main.scrollHeight
Expand Down

0 comments on commit 4a480db

Please sign in to comment.