ctod 0.7.0 → 0.7.1
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.
- package/.api-key +1 -0
- package/.nyc_output/42919e68-b472-4a5d-b2d3-5d5153f28467.json +1 -0
- package/.nyc_output/processinfo/42919e68-b472-4a5d-b2d3-5d5153f28467.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/.output/.output/stores//344/270/200/345/240/264/346/234/237/345/276/205/345/267/262/344/271/205/347/232/204/345/222/214/350/247/243/cover-0.png +1 -0
- package/.output/.output/stores//344/270/200/345/240/264/346/234/237/345/276/205/345/267/262/344/271/205/347/232/204/345/222/214/350/247/243/cover-1.png +1 -0
- package/.output/.output/stores//344/270/200/345/240/264/346/234/237/345/276/205/345/267/262/344/271/205/347/232/204/345/222/214/350/247/243/story-config.json +4 -0
- package/.output/.output/stores//344/270/200/345/240/264/346/234/237/345/276/205/345/267/262/344/271/205/347/232/204/345/222/214/350/247/243/story.json +22 -0
- package/.output/.output/stores//345/276/236/351/273/221/346/232/227/350/265/260/345/220/221/345/205/211/346/230/216/cover-0.png +1 -0
- package/.output/.output/stores//345/276/236/351/273/221/346/232/227/350/265/260/345/220/221/345/205/211/346/230/216/cover-1.png +1 -0
- package/.output/.output/stores//345/276/236/351/273/221/346/232/227/350/265/260/345/220/221/345/205/211/346/230/216/story-config.json +4 -0
- package/.output/.output/stores//345/276/236/351/273/221/346/232/227/350/265/260/345/220/221/345/205/211/346/230/216/story.json +24 -0
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/cover-0.png +1 -0
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/cover-1.png +1 -0
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/story-config.json +4 -0
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/story.json +24 -0
- package/.output/.output/stores//350/227/235/350/241/223/345/256/266/347/232/204/351/235/210/346/204/237/cover-0.png +1 -0
- package/.output/.output/stores//350/227/235/350/241/223/345/256/266/347/232/204/351/235/210/346/204/237/cover-1.png +1 -0
- package/.output/.output/stores//350/227/235/350/241/223/345/256/266/347/232/204/351/235/210/346/204/237/story-config.json +4 -0
- package/.output/.output/stores//350/227/235/350/241/223/345/256/266/347/232/204/351/235/210/346/204/237/story.json +28 -0
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/cover-0.png +1 -0
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/cover-1.png +1 -0
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/story-config.json +4 -0
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/story.json +18 -0
- package/.output/.output/stores//350/250/255/350/250/210/350/210/207/351/226/213/347/231/274/347/232/204/346/214/221/346/210/260/content.json +22 -0
- package/.output/.output/talks//344/273/245/347/254/221/350/251/261/347/202/272/345/237/272/347/244/216/347/232/204/351/235/242/350/251/246/content.json +30 -0
- package/.output/.output/talks//344/273/245/347/254/221/350/251/261/347/202/272/345/237/272/347/244/216/347/232/204/351/235/242/350/251/246/cover-1684055229695.png +0 -0
- package/.output/.output/talks//345/234/250/346/224/277/346/262/273/345/200/231/351/201/270/344/272/272/350/276/257/350/253/226/344/270/255/347/232/204/350/252/252/346/234/215/346/200/247/346/272/235/351/200/232/content.json +30 -0
- package/.output/.output/talks//345/234/250/346/224/277/346/262/273/345/200/231/351/201/270/344/272/272/350/276/257/350/253/226/344/270/255/347/232/204/350/252/252/346/234/215/346/200/247/346/272/235/351/200/232/cover-1684056611678.png +0 -0
- package/.output/.output/talks//346/224/276/351/254/206/347/232/204/345/200/231/351/201/270/344/272/272/351/200/262/350/241/214/346/224/277/346/262/273/350/276/257/350/253/226/content.json +36 -0
- package/.output/.output/talks//346/224/276/351/254/206/347/232/204/345/200/231/351/201/270/344/272/272/351/200/262/350/241/214/346/224/277/346/262/273/350/276/257/350/253/226/cover-1684055140609.png +0 -0
- package/.output/.output/talks//346/224/277/346/262/273/347/254/221/350/251/261/content.json +30 -0
- package/.output/.output/talks//346/224/277/346/262/273/347/254/221/350/251/261/cover-1684056246465.png +0 -0
- package/.output/.output/talks//350/251/274/350/253/247/345/256/266/351/225/267/346/225/231/345/270/253/346/234/203/350/255/260/content.json +26 -0
- package/.output/.output/talks//350/251/274/350/253/247/345/256/266/351/225/267/346/225/231/345/270/253/346/234/203/350/255/260/cover-1685785935121.png +0 -0
- package/.output/.output/talks//350/262/241/345/213/231/351/241/247/345/225/217/350/253/256/350/251/242/content.json +26 -0
- package/.output/.output/talks//350/262/241/345/213/231/351/241/247/345/225/217/350/253/256/350/251/242/cover-1685785115833.png +0 -0
- package/.output/.output/talks//351/206/253/347/224/237/345/222/214/347/227/205/344/272/272/350/250/216/350/253/226/346/202/262/345/202/267/content.json +32 -0
- package/.output/.output/talks//351/206/253/347/224/237/345/222/214/347/227/205/344/272/272/350/250/216/350/253/226/346/202/262/345/202/267/cover-1684055075942.png +0 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/examples/basic.ts +0 -89
- package/examples/llama.cpp.ts +0 -56
- package/examples/plugin.ts +0 -118
- package/lib/broker/chat.ts +0 -435
- package/lib/core/parser.ts +0 -62
- package/lib/core/plugin.ts +0 -46
- package/lib/core/translator.ts +0 -115
- package/lib/ctod.ts +0 -71
- package/lib/index.ts +0 -41
- package/lib/plugins/index.ts +0 -38
- package/lib/plugins/limiter.ts +0 -103
- package/lib/plugins/print-log.ts +0 -35
- package/lib/plugins/retry.ts +0 -25
- package/lib/plugins/role.ts +0 -28
- package/lib/service/llama3.cpp/completion.ts +0 -313
- package/lib/service/llama3.cpp/index.ts +0 -53
- package/lib/service/openai/chat.ts +0 -244
- package/lib/service/openai/images-generation.ts +0 -64
- package/lib/service/openai/index.ts +0 -97
- package/lib/service/openai/vision.ts +0 -111
- package/lib/shims.d.ts +0 -4
- package/lib/templates.ts +0 -71
- package/lib/types.ts +0 -4
- package/lib/utils/error.ts +0 -14
- package/lib/utils/validate.ts +0 -64
- package/logo.ai +2 -1141
- package/logo.png +0 -0
- package/types/examples/basic.d.ts +0 -1
- package/types/examples/chat-demo.d.ts +0 -2
- package/types/examples/chat-for-llama.cpp-demo.d.ts +0 -2
- package/types/examples/chat-with-json-schema-demo.d.ts +0 -2
- package/types/examples/llama.cpp.d.ts +0 -2
- package/types/examples/plugin-demo.d.ts +0 -2
- package/types/examples/plugin.d.ts +0 -2
- package/types/examples/stream-for-llama.cpp-demo.d.ts +0 -2
- package/types/examples/vision-demo.d.ts +0 -2
- package/types/lib/broker/chat.d.ts +0 -150
- package/types/lib/core/parser.d.ts +0 -32
- package/types/lib/core/plugin.d.ts +0 -34
- package/types/lib/core/translator.d.ts +0 -67
- package/types/lib/ctod.d.ts +0 -32
- package/types/lib/index.d.ts +0 -34
- package/types/lib/plugins/index.d.ts +0 -47
- package/types/lib/plugins/limiter.d.ts +0 -36
- package/types/lib/plugins/print-log.d.ts +0 -5
- package/types/lib/plugins/retry.d.ts +0 -6
- package/types/lib/plugins/role.d.ts +0 -5
- package/types/lib/service/llama3.cpp/completion.d.ts +0 -61
- package/types/lib/service/llama3.cpp/index.d.ts +0 -19
- package/types/lib/service/openai/chat.d.ts +0 -110
- package/types/lib/service/openai/completion.d.ts +0 -59
- package/types/lib/service/openai/images-generation.d.ts +0 -35
- package/types/lib/service/openai/index.d.ts +0 -29
- package/types/lib/service/openai/vision.d.ts +0 -74
- package/types/lib/templates.d.ts +0 -20
- package/types/lib/types.d.ts +0 -1
- package/types/lib/utils/error.d.ts +0 -11
- package/types/lib/utils/validate.d.ts +0 -16
package/examples/plugin.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
|
2
|
-
/// <reference path="../lib/shims.d.ts" />
|
|
3
|
-
|
|
4
|
-
import fs from 'fs'
|
|
5
|
-
import { flow } from 'power-helper'
|
|
6
|
-
import { prompt } from 'inquirer'
|
|
7
|
-
import { CtoD, ChatBrokerPlugin, plugins, OpenAI } from '../lib/index'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @test npx esno ./examples/plugin.ts
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const apiKey = fs.readFileSync('./.api-key', 'utf-8').trim()
|
|
14
|
-
|
|
15
|
-
const characterPlugin = new ChatBrokerPlugin({
|
|
16
|
-
name: 'character',
|
|
17
|
-
params: () => {
|
|
18
|
-
return {}
|
|
19
|
-
},
|
|
20
|
-
receiveData: yup => {
|
|
21
|
-
return {
|
|
22
|
-
character: yup.string().required()
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
onInstall: ({ receive, attachAfter }) => {
|
|
26
|
-
const characters = new Map<string, string>()
|
|
27
|
-
receive(({ id, data }) => {
|
|
28
|
-
characters.set(id, data.character)
|
|
29
|
-
})
|
|
30
|
-
attachAfter('start', async({ id, setPreMessages }) => {
|
|
31
|
-
const character = characters.get(id)
|
|
32
|
-
setPreMessages([
|
|
33
|
-
{
|
|
34
|
-
role: 'user',
|
|
35
|
-
content: '請你扮演' + character
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
role: 'assistant',
|
|
39
|
-
content: '沒問題,我現在是' + character
|
|
40
|
-
}
|
|
41
|
-
])
|
|
42
|
-
})
|
|
43
|
-
attachAfter('done', async({ id }) => {
|
|
44
|
-
characters.delete(id)
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
flow.run(async () => {
|
|
50
|
-
const { character, action } = await prompt([
|
|
51
|
-
{
|
|
52
|
-
type: 'input',
|
|
53
|
-
name: 'character',
|
|
54
|
-
message: '請輸入角色名稱.',
|
|
55
|
-
default: '派大星'
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
type: 'input',
|
|
59
|
-
name: 'action',
|
|
60
|
-
message: '你想對他問什麼?',
|
|
61
|
-
default: '你最好的朋友是誰?'
|
|
62
|
-
}
|
|
63
|
-
])
|
|
64
|
-
|
|
65
|
-
const ctod = new CtoD({
|
|
66
|
-
plugins: () => {
|
|
67
|
-
return {
|
|
68
|
-
character: characterPlugin.use({}),
|
|
69
|
-
log: plugins.PrintLogPlugin.use({
|
|
70
|
-
detail: true
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
request: OpenAI.createChatRequestWithJsonSchema({
|
|
75
|
-
apiKey,
|
|
76
|
-
config: {
|
|
77
|
-
model: 'gpt-4o'
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
const brokerBuilder = ctod.createBrokerBuilder<{
|
|
83
|
-
action: string
|
|
84
|
-
character: string
|
|
85
|
-
}>({
|
|
86
|
-
install: ({ attach }) => {
|
|
87
|
-
attach('start', async({ data, plugins }) => {
|
|
88
|
-
plugins.character.send({
|
|
89
|
-
character: data.character
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
},
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
const broker = brokerBuilder.create(async({ yup, setMessages }) => {
|
|
96
|
-
setMessages([
|
|
97
|
-
{
|
|
98
|
-
role: 'user',
|
|
99
|
-
content: [
|
|
100
|
-
'請基於你的角色個性,並依據以下指令進行回應:',
|
|
101
|
-
action
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
])
|
|
105
|
-
return {
|
|
106
|
-
message: yup.string().required()
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
try {
|
|
110
|
-
const { message } = await broker.request({
|
|
111
|
-
action,
|
|
112
|
-
character
|
|
113
|
-
})
|
|
114
|
-
console.log(message)
|
|
115
|
-
} catch (error: any) {
|
|
116
|
-
console.error('Error:', error?.response?.data?.error?.message ?? error)
|
|
117
|
-
}
|
|
118
|
-
})
|
package/lib/broker/chat.ts
DELETED
|
@@ -1,435 +0,0 @@
|
|
|
1
|
-
import { TextParser } from '../core/parser'
|
|
2
|
-
import { ChatBrokerPlugin } from '../core/plugin'
|
|
3
|
-
import { Event, flow, Hook, Log } from 'power-helper'
|
|
4
|
-
import { Translator, TranslatorParams } from '../core/translator'
|
|
5
|
-
import { ValidateCallback, ValidateCallbackOutputs } from '../utils/validate'
|
|
6
|
-
import { ParserError } from '../utils/error'
|
|
7
|
-
|
|
8
|
-
export type Message = {
|
|
9
|
-
role: 'system' | 'user' | 'assistant' | (string & Record<string, unknown>)
|
|
10
|
-
name?: string
|
|
11
|
-
content: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type ChatBrokerHooks<
|
|
15
|
-
S extends ValidateCallback<any>,
|
|
16
|
-
O extends ValidateCallback<any>,
|
|
17
|
-
P extends ChatBrokerPlugin<any, any>,
|
|
18
|
-
PS extends Record<string, ReturnType<P['use']>>
|
|
19
|
-
> = {
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @zh 第一次聊天的時候觸發
|
|
23
|
-
* @en Triggered when chatting for the first time
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
start: {
|
|
27
|
-
id: string
|
|
28
|
-
data: ValidateCallbackOutputs<S>
|
|
29
|
-
metadata: Map<string, any>
|
|
30
|
-
plugins: {
|
|
31
|
-
[K in keyof PS]: {
|
|
32
|
-
send: (data: PS[K]['__receiveData']) => void
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
schema: {
|
|
36
|
-
input?: S
|
|
37
|
-
output: O
|
|
38
|
-
}
|
|
39
|
-
messages: Message[]
|
|
40
|
-
setPreMessages: (messages: (Omit<Message, 'content'> & { content: string | string[] })[]) => void
|
|
41
|
-
changeMessages: (messages: Message[]) => void
|
|
42
|
-
changeOutputSchema: (output: O) => void
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @zh 發送聊天訊息給機器人前觸發
|
|
47
|
-
* @en Triggered before sending chat message to bot
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
talkBefore: {
|
|
51
|
-
id: string
|
|
52
|
-
data: ValidateCallbackOutputs<S>
|
|
53
|
-
messages: Message[]
|
|
54
|
-
metadata: Map<string, any>
|
|
55
|
-
lastUserMessage: string
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @zh 當聊天機器人回傳資料的時候觸發
|
|
60
|
-
* @en Triggered when the chatbot returns data
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
talkAfter: {
|
|
64
|
-
id: string
|
|
65
|
-
data: ValidateCallbackOutputs<S>
|
|
66
|
-
response: any
|
|
67
|
-
messages: Message[]
|
|
68
|
-
parseText: string
|
|
69
|
-
metadata: Map<string, any>
|
|
70
|
-
lastUserMessage: string
|
|
71
|
-
/**
|
|
72
|
-
* @zh 宣告解析失敗
|
|
73
|
-
* @en Declare parsing failure
|
|
74
|
-
*/
|
|
75
|
-
parseFail: (error: any) => void
|
|
76
|
-
changeParseText: (text: string) => void
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* @zh 當回傳資料符合規格時觸發
|
|
81
|
-
* @en Triggered when the returned data meets the specifications
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
succeeded: {
|
|
85
|
-
id: string
|
|
86
|
-
metadata: Map<string, any>
|
|
87
|
-
output: ValidateCallbackOutputs<O>
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @zh 當回傳資料不符合規格,或是解析錯誤時觸發
|
|
92
|
-
* @en Triggered when the returned data does not meet the specifications or parsing errors
|
|
93
|
-
*/
|
|
94
|
-
|
|
95
|
-
parseFailed: {
|
|
96
|
-
id: string
|
|
97
|
-
error: any
|
|
98
|
-
retry: () => void
|
|
99
|
-
count: number
|
|
100
|
-
response: any
|
|
101
|
-
metadata: Map<string, any>
|
|
102
|
-
parserFails: { name: string, error: any }[]
|
|
103
|
-
messages: Message[]
|
|
104
|
-
lastUserMessage: string
|
|
105
|
-
changeMessages: (messages: Message[]) => void
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @zh 不論成功失敗,執行結束的時候會執行。
|
|
110
|
-
* @en It will be executed when the execution is completed, regardless of success or failure.
|
|
111
|
-
*/
|
|
112
|
-
|
|
113
|
-
done: {
|
|
114
|
-
id: string
|
|
115
|
-
metadata: Map<string, any>
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export type RequestContext = {
|
|
120
|
-
id: string
|
|
121
|
-
count: number
|
|
122
|
-
isRetry: boolean
|
|
123
|
-
metadata: Map<string, any>
|
|
124
|
-
onCancel: (cb: () => void) => void
|
|
125
|
-
schema: {
|
|
126
|
-
input: any
|
|
127
|
-
output: any
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export type Params<
|
|
132
|
-
S extends ValidateCallback<any>,
|
|
133
|
-
O extends ValidateCallback<any>,
|
|
134
|
-
C extends Record<string, any>,
|
|
135
|
-
P extends ChatBrokerPlugin<any, any>,
|
|
136
|
-
PS extends Record<string, ReturnType<P['use']>>
|
|
137
|
-
> = Omit<TranslatorParams<S, O>, 'parsers'> & {
|
|
138
|
-
name?: string
|
|
139
|
-
plugins?: PS | (() => PS)
|
|
140
|
-
request: (messages: Message[], context: RequestContext) => Promise<string>
|
|
141
|
-
install?: (context: {
|
|
142
|
-
log: Log
|
|
143
|
-
attach: Hook<C>['attach']
|
|
144
|
-
attachAfter: Hook<C>['attachAfter']
|
|
145
|
-
translator: Translator<S, O>
|
|
146
|
-
}) => void
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export class ChatBroker<
|
|
150
|
-
S extends ValidateCallback<any>,
|
|
151
|
-
O extends ValidateCallback<any>,
|
|
152
|
-
P extends ChatBrokerPlugin<any, any>,
|
|
153
|
-
PS extends Record<string, ReturnType<P['use']>>,
|
|
154
|
-
C extends ChatBrokerHooks<S, O, P, PS> = ChatBrokerHooks<S, O, P, PS>
|
|
155
|
-
> {
|
|
156
|
-
protected __hookType!: C
|
|
157
|
-
protected log: Log
|
|
158
|
-
protected hook = new Hook<C>()
|
|
159
|
-
protected params: Params<S, O, C, P, PS>
|
|
160
|
-
protected plugins = {} as PS
|
|
161
|
-
protected installed = false
|
|
162
|
-
protected translator: Translator<S, O>
|
|
163
|
-
protected event = new Event<{
|
|
164
|
-
cancel: {
|
|
165
|
-
requestId: string
|
|
166
|
-
}
|
|
167
|
-
cancelAll: any
|
|
168
|
-
}>()
|
|
169
|
-
|
|
170
|
-
constructor(params: Params<S, O, C, P, PS>) {
|
|
171
|
-
this.log = new Log(params.name ?? 'no name')
|
|
172
|
-
this.params = params
|
|
173
|
-
this.translator = new Translator({
|
|
174
|
-
...params,
|
|
175
|
-
parsers: [
|
|
176
|
-
TextParser.JsonMessage()
|
|
177
|
-
]
|
|
178
|
-
})
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
protected _install(): any {
|
|
182
|
-
if (this.installed === false) {
|
|
183
|
-
this.installed = true
|
|
184
|
-
const context = {
|
|
185
|
-
log: this.log,
|
|
186
|
-
attach: this.hook.attach.bind(this.hook),
|
|
187
|
-
attachAfter: this.hook.attachAfter.bind(this.hook),
|
|
188
|
-
translator: this.translator
|
|
189
|
-
}
|
|
190
|
-
if (this.params.plugins) {
|
|
191
|
-
this.plugins = typeof this.params.plugins === 'function' ? this.params.plugins() : this.params.plugins
|
|
192
|
-
for (let key in this.plugins) {
|
|
193
|
-
this.plugins[key].instance._params.onInstall({
|
|
194
|
-
...context,
|
|
195
|
-
params: this.plugins[key].params,
|
|
196
|
-
receive: this.plugins[key].receive
|
|
197
|
-
})
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
this.params.install?.(context)
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
async cancel(requestId?: string) {
|
|
205
|
-
if (requestId) {
|
|
206
|
-
this.event.emit('cancel', {
|
|
207
|
-
requestId
|
|
208
|
-
})
|
|
209
|
-
} else {
|
|
210
|
-
this.event.emit('cancelAll', {})
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
requestWithId<T extends Translator<S, O>>(data: T['__schemeType']): {
|
|
215
|
-
id: string
|
|
216
|
-
request: Promise<T['__outputType']>
|
|
217
|
-
} {
|
|
218
|
-
this._install()
|
|
219
|
-
let id = flow.createUuid()
|
|
220
|
-
let waitCancel = null as (() => void) | null
|
|
221
|
-
let isCancel = false
|
|
222
|
-
let isSending = false
|
|
223
|
-
|
|
224
|
-
// =================
|
|
225
|
-
//
|
|
226
|
-
// event
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
let listeners = [
|
|
230
|
-
this.event.on('cancel', ({ requestId }) => {
|
|
231
|
-
if (requestId === id) {
|
|
232
|
-
cancelTrigger()
|
|
233
|
-
}
|
|
234
|
-
}),
|
|
235
|
-
this.event.on('cancelAll', () => {
|
|
236
|
-
cancelTrigger()
|
|
237
|
-
})
|
|
238
|
-
]
|
|
239
|
-
let eventOff = () => listeners.forEach(e => e.off())
|
|
240
|
-
let cancelTrigger = () => {
|
|
241
|
-
if (isCancel === false) {
|
|
242
|
-
if (isSending && waitCancel) {
|
|
243
|
-
waitCancel()
|
|
244
|
-
}
|
|
245
|
-
isCancel = true
|
|
246
|
-
eventOff()
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
let onCancel = (cb: () => void) => {
|
|
250
|
-
waitCancel = cb
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// =================
|
|
254
|
-
//
|
|
255
|
-
// main
|
|
256
|
-
//
|
|
257
|
-
|
|
258
|
-
let request = async() => {
|
|
259
|
-
let schema = this.translator.getValidate()
|
|
260
|
-
let output: any = null
|
|
261
|
-
let plugins = {} as any
|
|
262
|
-
let metadata = new Map()
|
|
263
|
-
let question = await this.translator.compile(data, {
|
|
264
|
-
schema
|
|
265
|
-
})
|
|
266
|
-
let preMessages: Message[] = []
|
|
267
|
-
let messages: Message[] = []
|
|
268
|
-
if (question.prompt) {
|
|
269
|
-
messages.push({
|
|
270
|
-
role: 'user',
|
|
271
|
-
content: question.prompt
|
|
272
|
-
})
|
|
273
|
-
}
|
|
274
|
-
for (let key in this.plugins) {
|
|
275
|
-
plugins[key] = {
|
|
276
|
-
send: (data: any) => this.plugins[key].send({
|
|
277
|
-
id,
|
|
278
|
-
data
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
await this.hook.notify('start', {
|
|
283
|
-
id,
|
|
284
|
-
data,
|
|
285
|
-
schema,
|
|
286
|
-
plugins,
|
|
287
|
-
messages,
|
|
288
|
-
metadata,
|
|
289
|
-
setPreMessages: ms => {
|
|
290
|
-
preMessages = ms.map(e => {
|
|
291
|
-
return {
|
|
292
|
-
...e,
|
|
293
|
-
content: Array.isArray(e.content) ? e.content.join('\n') : e.content
|
|
294
|
-
}
|
|
295
|
-
})
|
|
296
|
-
},
|
|
297
|
-
changeMessages: ms => {
|
|
298
|
-
messages = ms
|
|
299
|
-
},
|
|
300
|
-
changeOutputSchema: output => {
|
|
301
|
-
this.translator.changeOutputSchema(output)
|
|
302
|
-
schema = this.translator.getValidate()
|
|
303
|
-
}
|
|
304
|
-
})
|
|
305
|
-
messages = [
|
|
306
|
-
...preMessages,
|
|
307
|
-
...messages
|
|
308
|
-
]
|
|
309
|
-
await flow.asyncWhile(async ({ count, doBreak }) => {
|
|
310
|
-
if (count >= 99) {
|
|
311
|
-
return doBreak()
|
|
312
|
-
}
|
|
313
|
-
let response = ''
|
|
314
|
-
let parseText = ''
|
|
315
|
-
let retryFlag = false
|
|
316
|
-
let lastUserMessage = messages.filter(e => e.role === 'user').slice(-1)[0]?.content || ''
|
|
317
|
-
try {
|
|
318
|
-
await this.hook.notify('talkBefore', {
|
|
319
|
-
id,
|
|
320
|
-
data,
|
|
321
|
-
messages,
|
|
322
|
-
metadata,
|
|
323
|
-
lastUserMessage
|
|
324
|
-
})
|
|
325
|
-
const sender = this.params.request(messages, {
|
|
326
|
-
id,
|
|
327
|
-
count,
|
|
328
|
-
schema,
|
|
329
|
-
onCancel,
|
|
330
|
-
metadata,
|
|
331
|
-
isRetry: retryFlag
|
|
332
|
-
})
|
|
333
|
-
if (isCancel) {
|
|
334
|
-
if (waitCancel) {
|
|
335
|
-
waitCancel()
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
try {
|
|
339
|
-
isSending = true
|
|
340
|
-
response = await sender
|
|
341
|
-
parseText = response
|
|
342
|
-
} finally {
|
|
343
|
-
isSending = false
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
if (isCancel === false) {
|
|
347
|
-
await this.hook.notify('talkAfter', {
|
|
348
|
-
id,
|
|
349
|
-
data,
|
|
350
|
-
response,
|
|
351
|
-
messages,
|
|
352
|
-
parseText,
|
|
353
|
-
metadata,
|
|
354
|
-
lastUserMessage,
|
|
355
|
-
parseFail: (error) => {
|
|
356
|
-
throw new ParserError(error, [])
|
|
357
|
-
},
|
|
358
|
-
changeParseText: text => {
|
|
359
|
-
parseText = text
|
|
360
|
-
}
|
|
361
|
-
})
|
|
362
|
-
output = (await this.translator.parse(parseText)).output
|
|
363
|
-
await this.hook.notify('succeeded', {
|
|
364
|
-
id,
|
|
365
|
-
output,
|
|
366
|
-
metadata
|
|
367
|
-
})
|
|
368
|
-
}
|
|
369
|
-
await this.hook.notify('done', {
|
|
370
|
-
id,
|
|
371
|
-
metadata
|
|
372
|
-
})
|
|
373
|
-
doBreak()
|
|
374
|
-
} catch (error: any) {
|
|
375
|
-
// 如果解析錯誤,可以選擇是否重新解讀
|
|
376
|
-
if (error instanceof ParserError) {
|
|
377
|
-
await this.hook.notify('parseFailed', {
|
|
378
|
-
id,
|
|
379
|
-
error: error.error,
|
|
380
|
-
count,
|
|
381
|
-
response,
|
|
382
|
-
messages,
|
|
383
|
-
metadata,
|
|
384
|
-
lastUserMessage,
|
|
385
|
-
parserFails: error.parserFails,
|
|
386
|
-
retry: () => {
|
|
387
|
-
retryFlag = true
|
|
388
|
-
},
|
|
389
|
-
changeMessages: ms => {
|
|
390
|
-
messages = ms
|
|
391
|
-
}
|
|
392
|
-
})
|
|
393
|
-
if (retryFlag === false) {
|
|
394
|
-
await this.hook.notify('done', {
|
|
395
|
-
id,
|
|
396
|
-
metadata
|
|
397
|
-
})
|
|
398
|
-
throw error
|
|
399
|
-
}
|
|
400
|
-
} else {
|
|
401
|
-
await this.hook.notify('done', {
|
|
402
|
-
id,
|
|
403
|
-
metadata
|
|
404
|
-
})
|
|
405
|
-
throw error
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
})
|
|
409
|
-
return output
|
|
410
|
-
}
|
|
411
|
-
const send = async() => {
|
|
412
|
-
try {
|
|
413
|
-
const result = await request()
|
|
414
|
-
return result
|
|
415
|
-
} finally {
|
|
416
|
-
eventOff()
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
return {
|
|
420
|
-
id,
|
|
421
|
-
request: send()
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* @zh 將請求發出至聊天機器人。
|
|
427
|
-
* @en Send request to chatbot.
|
|
428
|
-
*/
|
|
429
|
-
|
|
430
|
-
async request<T extends Translator<S, O>>(data: T['__schemeType']): Promise<T['__outputType']> {
|
|
431
|
-
const { request } = this.requestWithId(data)
|
|
432
|
-
const output = await request
|
|
433
|
-
return output
|
|
434
|
-
}
|
|
435
|
-
}
|
package/lib/core/parser.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import JSON5 from 'json5'
|
|
2
|
-
|
|
3
|
-
type TextParserParams = {
|
|
4
|
-
/**
|
|
5
|
-
* @zh 解讀器名字。
|
|
6
|
-
* @en The name of the parser.
|
|
7
|
-
*/
|
|
8
|
-
name: string
|
|
9
|
-
/**
|
|
10
|
-
* @zh 解讀文本。
|
|
11
|
-
* @en Read the text.
|
|
12
|
-
*/
|
|
13
|
-
handler: (text: string) => Promise<any>
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export class TextParser {
|
|
17
|
-
private params: TextParserParams
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @zh 盡可能將文字內的 json 解讀出來。
|
|
21
|
-
* @en Try to read the json in the text as much as possible.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
static JsonMessage() {
|
|
25
|
-
return new TextParser({
|
|
26
|
-
name: 'JsonMessage',
|
|
27
|
-
handler: async (text) => {
|
|
28
|
-
try {
|
|
29
|
-
const result = JSON.parse(text)
|
|
30
|
-
return result
|
|
31
|
-
} catch (error) {
|
|
32
|
-
const jsonRegex = /{(?:[^{}]|(?:{[^{}]*}))*}/
|
|
33
|
-
const matchedText = text.match(jsonRegex)?.[0] || ''
|
|
34
|
-
return JSON5.parse(matchedText)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
constructor(params: TextParserParams) {
|
|
41
|
-
this.params = params
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @zh 解讀器名字。
|
|
46
|
-
* @en The name of the parser.
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
get name() {
|
|
50
|
-
return this.params.name
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @zh 解讀文本。
|
|
55
|
-
* @en Read the text.
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
async read(text: string) {
|
|
59
|
-
const result = await this.params.handler(text)
|
|
60
|
-
return result
|
|
61
|
-
}
|
|
62
|
-
}
|
package/lib/core/plugin.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Translator } from './translator'
|
|
2
|
-
import { ChatBrokerHooks } from '../broker/chat'
|
|
3
|
-
import { Log, Hook, Event } from 'power-helper'
|
|
4
|
-
import { ValidateCallback, ValidateCallbackOutputs } from '../utils/validate'
|
|
5
|
-
|
|
6
|
-
type BrokerHooks = ChatBrokerHooks<any, any, any, any>
|
|
7
|
-
type BrokerPluginParams<
|
|
8
|
-
T extends ValidateCallback<any>,
|
|
9
|
-
R extends ValidateCallback<any>
|
|
10
|
-
> = {
|
|
11
|
-
name: string
|
|
12
|
-
params: T
|
|
13
|
-
receiveData: R
|
|
14
|
-
onInstall: (context: {
|
|
15
|
-
log: Log
|
|
16
|
-
params: ValidateCallbackOutputs<T>
|
|
17
|
-
attach: Hook<BrokerHooks>['attach']
|
|
18
|
-
attachAfter: Hook<BrokerHooks>['attachAfter']
|
|
19
|
-
translator: Translator<any, any>
|
|
20
|
-
receive: (callback: (params: {
|
|
21
|
-
id: string
|
|
22
|
-
data: ValidateCallbackOutputs<R>
|
|
23
|
-
}) => void) => void
|
|
24
|
-
}) => void
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class ChatBrokerPlugin<
|
|
28
|
-
T extends ValidateCallback<any>,
|
|
29
|
-
R extends ValidateCallback<any>
|
|
30
|
-
> {
|
|
31
|
-
_event = new Event()
|
|
32
|
-
_params: BrokerPluginParams<T, R>
|
|
33
|
-
constructor(params: BrokerPluginParams<T, R>) {
|
|
34
|
-
this._params = params
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
use(params: ValidateCallbackOutputs<T>) {
|
|
38
|
-
return {
|
|
39
|
-
instance: this as any,
|
|
40
|
-
params,
|
|
41
|
-
send: (data: ValidateCallbackOutputs<R>) => { this._event.emit('receive', data) },
|
|
42
|
-
receive: (callback: any) => { this._event.on('receive', callback) },
|
|
43
|
-
__receiveData: null as unknown as ValidateCallbackOutputs<R>
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|