Skip to content

Commit 47dc134

Browse files
committed
Add detailed content to "Adding a New AI Bot" section in CONTRIBUTION.md
1 parent 6456ef0 commit 47dc134

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed

CONTRIBUTION.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,228 @@ export default KnowNothingBot;
238238
6. **Submit a Pull Request**: Once you have tested your bot and ensured it works correctly, submit a pull request following the steps mentioned in the "How to Submit Pull Requests" section.
239239

240240
Thank you for your contributions! We appreciate your efforts and look forward to your involvement in our community.
241+
242+
### Advanced Topics on Bot Development
243+
244+
#### UI order configuration
245+
246+
In the `src/bots/index.js` file, you can find the `all` array like
247+
248+
```javascript
249+
// Add to the main bot list
250+
const all = [
251+
ChatGPT35Bot.getInstance(),
252+
ChatGPT4Bot.getInstance(),
253+
OpenAIAPI35Bot.getInstance(),
254+
OpenAIAPI4Bot.getInstance(),
255+
BingChatCreativeBot.getInstance(),
256+
BingChatBalancedBot.getInstance(),
257+
BingChatPreciseBot.getInstance(),
258+
WenxinQianfanBot.getInstance(),
259+
SparkBot.getInstance(),
260+
MOSSBot.getInstance(),
261+
BardBot.getInstance(),
262+
...existing_bots...
263+
];
264+
```
265+
266+
You can change the order of the bots in this array to control their display order in the UI.
267+
For example, if you want to move the `BardBot` between `MOSSBot` and `WenxinQianfanBot`, you can modify the array like this:
268+
269+
```javascript
270+
const all = [
271+
ChatGPT35Bot.getInstance(),
272+
ChatGPT4Bot.getInstance(),
273+
OpenAIAPI35Bot.getInstance(),
274+
OpenAIAPI4Bot.getInstance(),
275+
BingChatCreativeBot.getInstance(),
276+
BingChatBalancedBot.getInstance(),
277+
BingChatPreciseBot.getInstance(),
278+
MOSSBot.getInstance(),
279+
BardBot.getInstance(), // Moved BardBot here
280+
WenxinQianfanBot.getInstance(),
281+
SparkBot.getInstance(),
282+
...existing_bots...
283+
];
284+
```
285+
286+
#### Setting component implementation
287+
288+
To fulfill other core functions, you need login functionality, API key configuration, etc. If your bot does not require login, or you don't mind putting the key directly in the code (strongly not recommended), you can skip this section.
289+
290+
##### Create a settings component
291+
292+
In the `src/components/BotSettings/` directory, create a new file named `KnowNothingBotSettings.vue`.
293+
294+
You can use existing settings components as templates:
295+
296+
1. If you only need login functionality, just copy `BardBotSettings.vue` and change import Bot from `@/bots/BardBot;` to import Bot from `@/bots/KnowNothingBot;`.
297+
- (Note: Some websites have implemented security measures to prevent ChatALL and similar clients from accessing them. If you encounter such situations, you will need to do a lot of hack work.)
298+
2. If you only need to configure the API key, copy `WenxinQianfanBotSettings.vue` and modify it, but this will require more work.
299+
3. Complex setups with multiple configuration options require additional implementation steps.
300+
301+
##### Add settings field
302+
303+
ChatALL's settings UI is built using [Vuetify 3](https://vuetifyjs.com/).
304+
Refer to the [Vuetify 3 official documentation](https://vuetifyjs.com/en/introduction/why-vuetify/) to see and test the rich components it supports.
305+
306+
By reviewing the existing implementation, you can adapt the code to suit your bot’s settings.
307+
308+
ChatALL's settings are stored in local storage using the [`vuex-persist`](https://github.com/championswimmer/vuex-persist). It's very handy, though the documentation is not readable enough.
309+
Here is a brief introduction on how to use it:
310+
311+
First, in `src/store/index.js`, add the following code:
312+
313+
```javascript
314+
export default createStore({
315+
state: {
316+
...
317+
knowNothing: {
318+
setting1: "",
319+
setting2: "",
320+
},
321+
...
322+
},
323+
mutations: {
324+
...
325+
setKnowNothing(state, { setting1, setting2 }) {
326+
state.knowNothing = { setting1, setting2 };
327+
},
328+
...
329+
},
330+
...
331+
});
332+
```
333+
334+
`setting1`, `setting2`, and sub-objects can be added, deleted, or modified as you like. Just make sure the top-level object is `knowNothing`, even if it only has one configuration.
335+
336+
Then, in `KnowNothingBotSettings.vue`, add the following code:
337+
338+
```javascript
339+
export default {
340+
...
341+
methods: {
342+
...mapMutations(["setKnowNothing"]),
343+
setSetting1(value){
344+
this.setKnowNothing({
345+
...this.knowNothing,
346+
setting1: value
347+
})
348+
},
349+
setSetting2(value){
350+
this.setKnowNothing({
351+
...this.knowNothing,
352+
setting2: value
353+
})
354+
},
355+
},
356+
computed: {
357+
...mapState(["knowNothing"])
358+
}
359+
}
360+
```
361+
362+
Finally, bind the `v-model` of the Vuetify component to the corresponding `knowNothing.xxx`, and point the action to the corresponding `setXxx()` function. For example:
363+
364+
```html
365+
<v-text-field
366+
v-model="knowNothing.setting1"
367+
@update:model-value="setSetting1"
368+
></v-text-field>
369+
```
370+
371+
Done! Run the program and open DevTools to check if the values are correctly stored in the "Application" tab.
372+
373+
In `KnowNothingBot.js`, using the parameters you set is straightforward:
374+
375+
```javascript
376+
...
377+
import store from "@/store";
378+
...
379+
store.state.knowNothing.setting1
380+
store.state.knowNothing.setting2
381+
const { setting1, setting2 } = store.state.knowNothing;
382+
...
383+
```
384+
385+
#### Detailed _sendPrompt() patterns
386+
387+
This is the core function, which sends and receives messages.
388+
389+
Reference existing bots depending on your interface type:
390+
391+
1. For standard HTTP APIs: see `BardBot.js`
392+
2. For SSE-based APIs: see `ChatGPTBot.js`
393+
3. For WebSocket APIs: see `BingChatBot.js`
394+
395+
How you send and parse messages depends on the specific chatbot. Once you receive a response or hit an error, do the following:
396+
397+
1. If the response only contains new incremental text, and you need to assemble all the text yourself, then call `onUpdateResponse(callbackParam, { content: text, done: false });`.
398+
2. After receiving all the text, call `onUpdateResponse(callbackParam, { content: text, done: true });` to update all the data. If the text has already been `onUpdateResponse` before, you can just call `onUpdateResponse(callbackParam, { done: true });`.
399+
3. When ending normally, call `resolve()`.
400+
4. If an error occurs, call `reject(error)`. The `error` can be an exception or an error message string. ChatALL will automatically handle it and display it to the user.
401+
402+
#### checkAvailability() implementation
403+
404+
ChatALL calls the `checkAvailability()` function to check if the bot is available when it starts for the first time, refreshes the page (Command+R or Ctrl+R), and completes the settings.
405+
406+
In general, it performs these checks:
407+
408+
1. Is the login valid?
409+
2. Is the API key configured properly?
410+
3. Are all the other necessary conditions met?
411+
412+
If everything is good, `checkAvailability()` should return `true`.
413+
Else, it should return `false`.
414+
415+
#### Custom bot icons
416+
417+
Place the icon file in `public/bots/knownothing-logo.png`, and modify `KnowNothingBot.js`:
418+
419+
```javascript
420+
static _logoFilename = "knownothing-logo.png";
421+
```
422+
423+
#### Multi-language support in JS/HTML
424+
425+
Language files are located in `src/i18n/locales/`, named with language codes and in .json format.
426+
You need to add at least the following for your bot:
427+
428+
`en.json`
429+
```json
430+
{
431+
...
432+
"knowNothing": {
433+
"name": "Know Nothing"
434+
},
435+
...
436+
}
437+
```
438+
439+
`zh.json`
440+
```json
441+
{
442+
...
443+
"knowNothing": {
444+
"name": "啥都不懂"
445+
},
446+
...
447+
}
448+
```
449+
450+
Plus any other strings your bot needs.
451+
452+
In JavaScript, you can use the following code to call the multi-language support:
453+
454+
```javascript
455+
import i18n from "@/i18n";
456+
...
457+
i18n.global.t("knowNothing.name")
458+
...
459+
```
460+
461+
In HTML, you can use the following code:
462+
463+
```html
464+
{{ $t("knowNothing.name") }}
465+
```

0 commit comments

Comments
 (0)