ctod 0.1.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +65 -105
  2. package/dist/index.js +1 -1
  3. package/examples/chat-demo.ts +70 -0
  4. package/examples/{applications/cosplay.ts → plugin-demo.ts} +20 -13
  5. package/lib/broker/chat.ts +277 -0
  6. package/lib/core/plugin.ts +9 -60
  7. package/lib/index.ts +13 -25
  8. package/lib/plugins/index.ts +6 -1
  9. package/lib/plugins/limiter.ts +4 -4
  10. package/lib/plugins/print-log.ts +32 -73
  11. package/lib/plugins/retry.ts +23 -30
  12. package/lib/plugins/role.ts +26 -33
  13. package/lib/service/{chatgpt35.ts → openai/chat.ts} +17 -32
  14. package/lib/service/{chatgpt3.ts → openai/completion.ts} +12 -27
  15. package/lib/service/{images-generations.ts → openai/images-generation.ts} +7 -22
  16. package/lib/service/openai/index.ts +43 -0
  17. package/package.json +2 -2
  18. package/types/lib/broker/{35.d.ts → chat.d.ts} +42 -17
  19. package/types/lib/core/plugin.d.ts +9 -43
  20. package/types/lib/index.d.ts +12 -25
  21. package/types/lib/plugins/index.d.ts +17 -19
  22. package/types/lib/plugins/limiter.d.ts +4 -4
  23. package/types/lib/plugins/print-log.d.ts +4 -15
  24. package/types/lib/plugins/retry.d.ts +5 -11
  25. package/types/lib/plugins/role.d.ts +4 -10
  26. package/types/lib/service/{chatgpt35.d.ts → openai/chat.d.ts} +14 -24
  27. package/types/lib/service/{chatgpt3.d.ts → openai/completion.d.ts} +9 -19
  28. package/types/lib/service/{images-generations.d.ts → openai/images-generation.d.ts} +4 -14
  29. package/types/lib/service/openai/index.d.ts +22 -0
  30. package/README-TW.md +0 -239
  31. package/TODO +0 -6
  32. package/examples/applications/bbc-news-reader.ts +0 -224
  33. package/examples/applications/story-generations.ts +0 -131
  34. package/examples/applications/talk-generations.ts +0 -257
  35. package/examples/chatgpt3.5-broker.ts +0 -79
  36. package/examples/chatgpt3.5.ts +0 -42
  37. package/examples/utils/index.ts +0 -56
  38. package/lib/broker/3.ts +0 -160
  39. package/lib/broker/35.ts +0 -207
  40. package/lib/broker/index.ts +0 -83
  41. package/types/lib/broker/3.d.ts +0 -71
  42. package/types/lib/broker/index.d.ts +0 -30
@@ -1,42 +0,0 @@
1
- import { flow } from 'power-helper'
2
- import { prompt } from 'inquirer'
3
- import { ChatGPT35 } from '../lib/index'
4
-
5
- /**
6
- * @zh 這裡示範如何透過 ChatGPT35 持續對話
7
- * @en Here is a demonstration of how to use ChatGPT35Broker to obtain the best index from the user's queries.
8
- * @test npx ts-node ./examples/chatgpt3.5.ts
9
- */
10
-
11
- flow.run(async() => {
12
- const { apiKey } = await prompt([
13
- {
14
- type: 'input',
15
- name: 'apiKey',
16
- message: 'Please enter API key.',
17
- default: ''
18
- }
19
- ])
20
- if (!apiKey) {
21
- throw new Error('Unable to find API key.')
22
- }
23
- let bot = new ChatGPT35()
24
- let talk = bot.chat.bind(bot)
25
- bot.setConfiguration(apiKey)
26
- await flow.asyncWhile(async({ count, doBreak }) => {
27
- if (count >= 99) {
28
- return doBreak()
29
- }
30
- const { text } = await prompt([
31
- {
32
- type: 'input',
33
- name: 'text',
34
- message: 'Please enter what you want to say.',
35
- default: ''
36
- }
37
- ])
38
- const response = await talk(text)
39
- talk = response.nextTalk
40
- console.log('AI:', response.result.text)
41
- })
42
- })
@@ -1,56 +0,0 @@
1
- import fs from 'fs'
2
- import { Buffer } from 'buffer'
3
- import { prompt } from 'inquirer'
4
-
5
- type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'latin1' | 'binary' | 'hex'
6
-
7
- /**
8
- * @zh 你可以透過在根目錄中加入 .key 檔案,來自動讀取 API key
9
- * @en You can automatically read the API key by adding the .key file in the root directory.
10
- */
11
-
12
- export const getKey = async() => {
13
- let apiKey = ''
14
- let keyFile = './.key'
15
- if (fs.existsSync(keyFile)) {
16
- apiKey = fs.readFileSync('./.key').toString()
17
- }
18
- if (!apiKey) {
19
- const { inputApiKey } = await prompt([
20
- {
21
- type: 'input',
22
- name: 'inputApiKey',
23
- message: 'Please enter API key.',
24
- default: ''
25
- }
26
- ])
27
- apiKey = inputApiKey
28
- }
29
- if (!apiKey) {
30
- throw new Error('Unable to find API key.')
31
- }
32
- return apiKey
33
- }
34
-
35
- /**
36
- * @zh 定義輸出資料夾位置
37
- * @en Define the output folder location
38
- */
39
-
40
- export const definedOutputDir = (dirName: string) => {
41
- let dir = `.output/${dirName}`
42
- if (fs.existsSync(dir) === false) {
43
- fs.mkdirSync(dir, {
44
- recursive: true
45
- })
46
- }
47
- return {
48
- write(fileName: string, content: Buffer | string | Record<any, any>, encode: BufferEncoding = 'utf-8') {
49
- let data = content
50
- if (Buffer.isBuffer(content) === false && typeof content !== 'string') {
51
- data = JSON.stringify(content, null, 4)
52
- }
53
- fs.writeFileSync(`${dir}/${fileName}`, data, encode)
54
- }
55
- }
56
- }
package/lib/broker/3.ts DELETED
@@ -1,160 +0,0 @@
1
- import { flow } from 'power-helper'
2
- import { Translator } from '../core/translator'
3
- import { BaseBroker } from './index'
4
- import { Broker3Plugin } from '../core/plugin'
5
- import { ChatGPT3, ChatGPT3TalkResponse } from '../service/chatgpt3'
6
- import { ValidateCallback, ValidateCallbackOutputs } from '../utils/validate'
7
-
8
- export class ChatGPT3Broker<
9
- S extends ValidateCallback<any>,
10
- O extends ValidateCallback<any>,
11
- P extends Broker3Plugin<any, any>,
12
- PS extends Record<string, ReturnType<P['use']>>
13
- > extends BaseBroker<S, O, P, PS, {
14
-
15
- /**
16
- * @zh 發送聊天訊息給機器人前觸發
17
- * @en Triggered before sending chat message to bot
18
- */
19
-
20
- talkBefore: {
21
- id: string
22
- data: ValidateCallbackOutputs<S>
23
- prompt: string
24
- plugins: {
25
- [K in keyof PS]: {
26
- send: (data: PS[K]['__receiveData']) => void
27
- }
28
- }
29
- }
30
-
31
- /**
32
- * @zh 當聊天機器人回傳資料的時候觸發
33
- * @en Triggered when the chatbot returns data
34
- */
35
-
36
- talkAfter: {
37
- id: string
38
- data: ValidateCallbackOutputs<S>
39
- prompt: string
40
- response: ChatGPT3TalkResponse
41
- parseText: string
42
- changeParseText: (text: string) => void
43
- }
44
-
45
- /**
46
- * @zh 當回傳資料符合規格時觸發
47
- * @en Triggered when the returned data meets the specifications
48
- */
49
-
50
- succeeded: {
51
- id: string
52
- output: ValidateCallbackOutputs<O>
53
- }
54
-
55
- /**
56
- * @zh 當回傳資料不符合規格,或是解析錯誤時觸發
57
- * @en Triggered when the returned data does not meet the specifications or parsing errors
58
- */
59
-
60
- parseFailed: {
61
- id: string
62
- error: any
63
- count: number
64
- retry: () => void
65
- response: ChatGPT3TalkResponse
66
- parserFails: { name: string, error: any }[]
67
- changePrompt: (text: string) => void
68
- }
69
-
70
- /**
71
- * @zh 不論成功失敗,執行結束的時候會執行。
72
- * @en It will be executed when the execution is completed, regardless of success or failure.
73
- */
74
-
75
- done: {
76
- id: string
77
- }
78
- }> {
79
-
80
- bot: ChatGPT3 = new ChatGPT3()
81
-
82
- /**
83
- * @zh 將請求發出至聊天機器人。
84
- * @en Send request to chatbot.
85
- */
86
-
87
- async request<T extends Translator<S, O>>(data: T['__schemeType']): Promise<T['__outputType']> {
88
- this._install()
89
- let id = flow.createUuid()
90
- let output: any = null
91
- let question = await this.translator.compile(data)
92
- await flow.asyncWhile(async ({ count, doBreak }) => {
93
- if (count >= 10) {
94
- return doBreak()
95
- }
96
- let response: ChatGPT3TalkResponse = null as any
97
- let parseText = ''
98
- let retryFlag = false
99
- let plugins = {} as any
100
- for (let key in this.plugins) {
101
- plugins[key] = {
102
- send: (data: any) => this.plugins[key].send({
103
- id,
104
- data
105
- })
106
- }
107
- }
108
- try {
109
- await this.hook.notify('talkBefore', {
110
- id,
111
- data,
112
- plugins,
113
- prompt: question.prompt
114
- })
115
- response = await this.bot.talk(question.prompt)
116
- parseText = response.text
117
- await this.hook.notify('talkAfter', {
118
- id,
119
- data,
120
- prompt: question.prompt,
121
- response,
122
- parseText,
123
- changeParseText: text => {
124
- parseText = text
125
- }
126
- })
127
- output = (await this.translator.parse(parseText)).output
128
- await this.hook.notify('succeeded', {
129
- id,
130
- output
131
- })
132
- await this.hook.notify('done', { id })
133
- doBreak()
134
- } catch (error: any) {
135
- // 如果解析錯誤,可以選擇是否重新解讀
136
- if (error.isParserError) {
137
- await this.hook.notify('parseFailed', {
138
- id,
139
- error: error.error,
140
- count,
141
- response,
142
- parserFails: error.parserFails,
143
- retry: () => {
144
- retryFlag = true
145
- },
146
- changePrompt: (text) => {
147
- question.prompt = text
148
- }
149
- })
150
- if (retryFlag === false) {
151
- return doBreak()
152
- }
153
- }
154
- await this.hook.notify('done', { id })
155
- throw error
156
- }
157
- })
158
- return output
159
- }
160
- }
package/lib/broker/35.ts DELETED
@@ -1,207 +0,0 @@
1
- import { flow } from 'power-helper'
2
- import { BaseBroker } from './index'
3
- import { Translator } from '../core/translator'
4
- import { Broker35Plugin } from '../core/plugin'
5
- import { ValidateCallback, ValidateCallbackOutputs } from '../utils/validate'
6
- import { ChatGPT35, ChatGPT35Message, ChatGPT35TalkResponse } from '../service/chatgpt35'
7
-
8
- export class ChatGPT35Broker<
9
- S extends ValidateCallback<any>,
10
- O extends ValidateCallback<any>,
11
- P extends Broker35Plugin<any, any>,
12
- PS extends Record<string, ReturnType<P['use']>>
13
- > extends BaseBroker<S, O, P, PS, {
14
-
15
- /**
16
- * @zh 第一次聊天的時候觸發
17
- * @en Triggered when chatting for the first time
18
- */
19
-
20
- talkFirst: {
21
- id: string
22
- data: ValidateCallbackOutputs<S>
23
- plugins: {
24
- [K in keyof PS]: {
25
- send: (data: PS[K]['__receiveData']) => void
26
- }
27
- }
28
- messages: ChatGPT35Message[]
29
- setPreMessages: (messages: ChatGPT35Message[]) => void
30
- changeMessages: (messages: ChatGPT35Message[]) => void
31
- }
32
-
33
- /**
34
- * @zh 發送聊天訊息給機器人前觸發
35
- * @en Triggered before sending chat message to bot
36
- */
37
-
38
- talkBefore: {
39
- id: string
40
- data: ValidateCallbackOutputs<S>
41
- messages: ChatGPT35Message[]
42
- lastUserMessage: string
43
- }
44
-
45
- /**
46
- * @zh 當聊天機器人回傳資料的時候觸發
47
- * @en Triggered when the chatbot returns data
48
- */
49
-
50
- talkAfter: {
51
- id: string
52
- data: ValidateCallbackOutputs<S>
53
- response: ChatGPT35TalkResponse
54
- messages: ChatGPT35Message[]
55
- parseText: string
56
- lastUserMessage: string
57
- changeParseText: (text: string) => void
58
- }
59
-
60
- /**
61
- * @zh 當回傳資料符合規格時觸發
62
- * @en Triggered when the returned data meets the specifications
63
- */
64
-
65
- succeeded: {
66
- id: string
67
- output: ValidateCallbackOutputs<O>
68
- }
69
-
70
- /**
71
- * @zh 當回傳資料不符合規格,或是解析錯誤時觸發
72
- * @en Triggered when the returned data does not meet the specifications or parsing errors
73
- */
74
-
75
- parseFailed: {
76
- id: string
77
- error: any
78
- retry: () => void
79
- count: number
80
- response: ChatGPT35TalkResponse
81
- parserFails: { name: string, error: any }[]
82
- messages: ChatGPT35Message[]
83
- lastUserMessage: string
84
- changeMessages: (messages: ChatGPT35Message[]) => void
85
- }
86
-
87
- /**
88
- * @zh 不論成功失敗,執行結束的時候會執行。
89
- * @en It will be executed when the execution is completed, regardless of success or failure.
90
- */
91
-
92
- done: {
93
- id: string
94
- }
95
- }> {
96
- bot: ChatGPT35 = new ChatGPT35()
97
-
98
- /**
99
- * @zh 將請求發出至聊天機器人。
100
- * @en Send request to chatbot.
101
- */
102
-
103
- async request<T extends Translator<S, O>>(data: T['__schemeType']): Promise<T['__outputType']> {
104
- this._install()
105
- let id = flow.createUuid()
106
- let output: any = null
107
- let plugins = {} as any
108
- let question = await this.translator.compile(data)
109
- let messages: ChatGPT35Message[] = [
110
- {
111
- role: 'user',
112
- content: question.prompt
113
- }
114
- ]
115
- for (let key in this.plugins) {
116
- plugins[key] = {
117
- send: (data: any) => this.plugins[key].send({
118
- id,
119
- data
120
- })
121
- }
122
- }
123
- await this.hook.notify('talkFirst', {
124
- id,
125
- data,
126
- plugins,
127
- messages,
128
- setPreMessages: ms => {
129
- messages = [
130
- ...ms,
131
- {
132
- role: 'user',
133
- content: question.prompt
134
- }
135
- ]
136
- },
137
- changeMessages: ms => {
138
- messages = ms
139
- }
140
- })
141
- await flow.asyncWhile(async ({ count, doBreak }) => {
142
- if (count >= 10) {
143
- return doBreak()
144
- }
145
- let response: ChatGPT35TalkResponse = null as any
146
- let parseText = ''
147
- let retryFlag = false
148
- let lastUserMessage = messages.filter(e => e.role === 'user').slice(-1)[0]?.content || ''
149
- try {
150
- await this.hook.notify('talkBefore', {
151
- id,
152
- data,
153
- messages,
154
- lastUserMessage
155
- })
156
- response = await this.bot.talk(messages)
157
- parseText = response.text
158
- await this.hook.notify('talkAfter', {
159
- id,
160
- data,
161
- response,
162
- parseText,
163
- messages: response.newMessages,
164
- lastUserMessage,
165
- changeParseText: text => {
166
- parseText = text
167
- }
168
- })
169
- messages = response.newMessages
170
- output = (await this.translator.parse(parseText)).output
171
- await this.hook.notify('succeeded', {
172
- id,
173
- output
174
- })
175
- await this.hook.notify('done', { id })
176
- doBreak()
177
- } catch (error: any) {
178
- // 如果解析錯誤,可以選擇是否重新解讀
179
- if (error.isParserError) {
180
- await this.hook.notify('parseFailed', {
181
- id,
182
- error: error.error,
183
- count,
184
- response,
185
- messages,
186
- lastUserMessage,
187
- parserFails: error.parserFails,
188
- retry: () => {
189
- retryFlag = true
190
- },
191
- changeMessages: ms => {
192
- messages = ms
193
- }
194
- })
195
- if (retryFlag === false) {
196
- await this.hook.notify('done', { id })
197
- throw error
198
- }
199
- } else {
200
- await this.hook.notify('done', { id })
201
- throw error
202
- }
203
- }
204
- })
205
- return output
206
- }
207
- }
@@ -1,83 +0,0 @@
1
- import { Hook, Log } from 'power-helper'
2
- import { ChatGPT3 } from '../service/chatgpt3'
3
- import { ChatGPT35 } from '../service/chatgpt35'
4
- import { TextParser } from '../core/parser'
5
- import { ValidateCallback } from '../utils/validate'
6
- import { Translator, TranslatorParams } from '../core/translator'
7
- import { Broker3Plugin, Broker35Plugin } from '../core/plugin'
8
-
9
- export type Params<
10
- S extends ValidateCallback<any>,
11
- O extends ValidateCallback<any>,
12
- C extends Record<string, any>,
13
- P extends Broker3Plugin<any, any> | Broker35Plugin<any, any>,
14
- PS extends Record<string, ReturnType<P['use']>>
15
- > = Omit<TranslatorParams<S, O>, 'parsers'> & {
16
- name?: string
17
- plugins?: PS | (() => PS)
18
- install: (context: {
19
- log: Log
20
- bot: ChatGPT3 | ChatGPT35
21
- attach: Hook<C>['attach']
22
- attachAfter: Hook<C>['attachAfter']
23
- translator: Translator<S, O>
24
- }) => void
25
- }
26
-
27
- export class BaseBroker<
28
- S extends ValidateCallback<any>,
29
- O extends ValidateCallback<any>,
30
- P extends Broker3Plugin<any, any> | Broker35Plugin<any, any>,
31
- PS extends Record<string, ReturnType<P['use']>>,
32
- C extends Record<string, any>
33
- > {
34
- protected __hookType!: C
35
- protected log: Log
36
- protected hook = new Hook<C>()
37
- protected bot!: ChatGPT3 | ChatGPT35
38
- protected params: Params<S, O, C, P, PS>
39
- protected plugins = {} as PS
40
- protected installed = false
41
- protected translator: Translator<S, O>
42
-
43
- constructor(params: Params<S, O, C, P, PS>) {
44
- this.log = new Log(params.name ?? 'no name')
45
- this.params = params
46
- this.translator = new Translator({
47
- ...params,
48
- parsers: [
49
- TextParser.JsonMessage()
50
- ]
51
- })
52
- }
53
-
54
- protected _install(): any {
55
- if (this.installed === false) {
56
- this.installed = true
57
- if (this.bot) {
58
- const context = {
59
- bot: this.bot,
60
- log: this.log,
61
- attach: this.hook.attach.bind(this.hook),
62
- attachAfter: this.hook.attachAfter.bind(this.hook),
63
- translator: this.translator
64
- }
65
- this.params.install(context)
66
- if (this.params.plugins) {
67
- this.plugins = typeof this.params.plugins === 'function' ? this.params.plugins() : this.params.plugins
68
- for (let key in this.plugins) {
69
- this.plugins[key].instance._params.onInstall({
70
- ...context,
71
- params: this.plugins[key].params,
72
- receive: this.plugins[key].receive
73
- })
74
- }
75
- }
76
- }
77
- }
78
- }
79
-
80
- protected request(_data: any): any {
81
- throw Error('DON\'T CALL THIS!')
82
- }
83
- }
@@ -1,71 +0,0 @@
1
- import { Translator } from '../core/translator';
2
- import { BaseBroker } from './index';
3
- import { Broker3Plugin } from '../core/plugin';
4
- import { ChatGPT3, ChatGPT3TalkResponse } from '../service/chatgpt3';
5
- import { ValidateCallback, ValidateCallbackOutputs } from '../utils/validate';
6
- export declare class ChatGPT3Broker<S extends ValidateCallback<any>, O extends ValidateCallback<any>, P extends Broker3Plugin<any, any>, PS extends Record<string, ReturnType<P['use']>>> extends BaseBroker<S, O, P, PS, {
7
- /**
8
- * @zh 發送聊天訊息給機器人前觸發
9
- * @en Triggered before sending chat message to bot
10
- */
11
- talkBefore: {
12
- id: string;
13
- data: ValidateCallbackOutputs<S>;
14
- prompt: string;
15
- plugins: {
16
- [K in keyof PS]: {
17
- send: (data: PS[K]['__receiveData']) => void;
18
- };
19
- };
20
- };
21
- /**
22
- * @zh 當聊天機器人回傳資料的時候觸發
23
- * @en Triggered when the chatbot returns data
24
- */
25
- talkAfter: {
26
- id: string;
27
- data: ValidateCallbackOutputs<S>;
28
- prompt: string;
29
- response: ChatGPT3TalkResponse;
30
- parseText: string;
31
- changeParseText: (text: string) => void;
32
- };
33
- /**
34
- * @zh 當回傳資料符合規格時觸發
35
- * @en Triggered when the returned data meets the specifications
36
- */
37
- succeeded: {
38
- id: string;
39
- output: ValidateCallbackOutputs<O>;
40
- };
41
- /**
42
- * @zh 當回傳資料不符合規格,或是解析錯誤時觸發
43
- * @en Triggered when the returned data does not meet the specifications or parsing errors
44
- */
45
- parseFailed: {
46
- id: string;
47
- error: any;
48
- count: number;
49
- retry: () => void;
50
- response: ChatGPT3TalkResponse;
51
- parserFails: {
52
- name: string;
53
- error: any;
54
- }[];
55
- changePrompt: (text: string) => void;
56
- };
57
- /**
58
- * @zh 不論成功失敗,執行結束的時候會執行。
59
- * @en It will be executed when the execution is completed, regardless of success or failure.
60
- */
61
- done: {
62
- id: string;
63
- };
64
- }> {
65
- bot: ChatGPT3;
66
- /**
67
- * @zh 將請求發出至聊天機器人。
68
- * @en Send request to chatbot.
69
- */
70
- request<T extends Translator<S, O>>(data: T['__schemeType']): Promise<T['__outputType']>;
71
- }
@@ -1,30 +0,0 @@
1
- import { Hook, Log } from 'power-helper';
2
- import { ChatGPT3 } from '../service/chatgpt3';
3
- import { ChatGPT35 } from '../service/chatgpt35';
4
- import { ValidateCallback } from '../utils/validate';
5
- import { Translator, TranslatorParams } from '../core/translator';
6
- import { Broker3Plugin, Broker35Plugin } from '../core/plugin';
7
- export declare type Params<S extends ValidateCallback<any>, O extends ValidateCallback<any>, C extends Record<string, any>, P extends Broker3Plugin<any, any> | Broker35Plugin<any, any>, PS extends Record<string, ReturnType<P['use']>>> = Omit<TranslatorParams<S, O>, 'parsers'> & {
8
- name?: string;
9
- plugins?: PS | (() => PS);
10
- install: (context: {
11
- log: Log;
12
- bot: ChatGPT3 | ChatGPT35;
13
- attach: Hook<C>['attach'];
14
- attachAfter: Hook<C>['attachAfter'];
15
- translator: Translator<S, O>;
16
- }) => void;
17
- };
18
- export declare class BaseBroker<S extends ValidateCallback<any>, O extends ValidateCallback<any>, P extends Broker3Plugin<any, any> | Broker35Plugin<any, any>, PS extends Record<string, ReturnType<P['use']>>, C extends Record<string, any>> {
19
- protected __hookType: C;
20
- protected log: Log;
21
- protected hook: import("power-helper/dist/modules/hook").Hook<C>;
22
- protected bot: ChatGPT3 | ChatGPT35;
23
- protected params: Params<S, O, C, P, PS>;
24
- protected plugins: PS;
25
- protected installed: boolean;
26
- protected translator: Translator<S, O>;
27
- constructor(params: Params<S, O, C, P, PS>);
28
- protected _install(): any;
29
- protected request(_data: any): any;
30
- }