ctod 0.7.1 → 0.7.2
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/examples/basic.ts +97 -0
- package/examples/llama.cpp.ts +56 -0
- package/examples/plugin.ts +118 -0
- package/lib/broker/chat.ts +435 -0
- package/lib/core/parser.ts +62 -0
- package/lib/core/plugin.ts +46 -0
- package/lib/core/translator.ts +115 -0
- package/lib/ctod.ts +71 -0
- package/lib/index.ts +41 -0
- package/lib/plugins/index.ts +38 -0
- package/lib/plugins/limiter.ts +103 -0
- package/lib/plugins/print-log.ts +35 -0
- package/lib/plugins/retry.ts +25 -0
- package/lib/plugins/role.ts +28 -0
- package/lib/service/llama3.cpp/completion.ts +313 -0
- package/lib/service/llama3.cpp/index.ts +53 -0
- package/lib/service/openai/chat.ts +244 -0
- package/lib/service/openai/images-generation.ts +64 -0
- package/lib/service/openai/index.ts +97 -0
- package/lib/service/openai/vision.ts +111 -0
- package/lib/shims.d.ts +4 -0
- package/lib/templates.ts +71 -0
- package/lib/types.ts +4 -0
- package/lib/utils/error.ts +14 -0
- package/lib/utils/validate.ts +64 -0
- package/package.json +1 -1
- package/types/examples/basic.d.ts +1 -0
- package/types/examples/chat-demo.d.ts +2 -0
- package/types/examples/chat-for-llama.cpp-demo.d.ts +2 -0
- package/types/examples/chat-with-json-schema-demo.d.ts +2 -0
- package/types/examples/llama.cpp.d.ts +2 -0
- package/types/examples/plugin-demo.d.ts +2 -0
- package/types/examples/plugin.d.ts +2 -0
- package/types/examples/stream-for-llama.cpp-demo.d.ts +2 -0
- package/types/examples/vision-demo.d.ts +2 -0
- package/types/lib/broker/chat.d.ts +150 -0
- package/types/lib/core/parser.d.ts +32 -0
- package/types/lib/core/plugin.d.ts +34 -0
- package/types/lib/core/translator.d.ts +67 -0
- package/types/lib/ctod.d.ts +32 -0
- package/types/lib/index.d.ts +34 -0
- package/types/lib/plugins/index.d.ts +47 -0
- package/types/lib/plugins/limiter.d.ts +36 -0
- package/types/lib/plugins/print-log.d.ts +5 -0
- package/types/lib/plugins/retry.d.ts +6 -0
- package/types/lib/plugins/role.d.ts +5 -0
- package/types/lib/service/llama3.cpp/completion.d.ts +61 -0
- package/types/lib/service/llama3.cpp/index.d.ts +19 -0
- package/types/lib/service/openai/chat.d.ts +110 -0
- package/types/lib/service/openai/completion.d.ts +59 -0
- package/types/lib/service/openai/images-generation.d.ts +35 -0
- package/types/lib/service/openai/index.d.ts +29 -0
- package/types/lib/service/openai/vision.d.ts +74 -0
- package/types/lib/templates.d.ts +20 -0
- package/types/lib/types.d.ts +1 -0
- package/types/lib/utils/error.d.ts +11 -0
- package/types/lib/utils/validate.d.ts +16 -0
- package/.api-key +0 -1
- package/.nyc_output/42919e68-b472-4a5d-b2d3-5d5153f28467.json +0 -1
- package/.nyc_output/processinfo/42919e68-b472-4a5d-b2d3-5d5153f28467.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- 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 +0 -1
- 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 +0 -1
- 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 +0 -4
- 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 +0 -22
- 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 +0 -1
- 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 +0 -1
- 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 +0 -4
- 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 +0 -24
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/cover-0.png +0 -1
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/cover-1.png +0 -1
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/story-config.json +0 -4
- package/.output/.output/stores//347/240/264/347/242/216/347/232/204/345/271/273/350/261/241/story.json +0 -24
- 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 +0 -1
- 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 +0 -1
- 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 +0 -4
- package/.output/.output/stores//350/227/235/350/241/223/345/256/266/347/232/204/351/235/210/346/204/237/story.json +0 -28
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/cover-0.png +0 -1
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/cover-1.png +0 -1
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/story-config.json +0 -4
- package/.output/.output/stores//350/250/230/346/206/266/345/225/206/344/272/272/story.json +0 -18
- 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 +0 -22
- 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 +0 -30
- 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 +0 -30
- 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 +0 -36
- 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 +0 -30
- 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 +0 -26
- 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 +0 -26
- 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 +0 -32
- 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
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { TextParser } from './parser'
|
|
2
|
+
import { validate, ValidateCallback, ValidateCallbackOutputs } from '../utils/validate'
|
|
3
|
+
import { ParserError } from '../utils/error'
|
|
4
|
+
|
|
5
|
+
export type TranslatorParams<
|
|
6
|
+
S extends ValidateCallback<any>,
|
|
7
|
+
O extends ValidateCallback<any>
|
|
8
|
+
> = {
|
|
9
|
+
/**
|
|
10
|
+
* @zh 輸入的資料格式。
|
|
11
|
+
* @en The input data format.
|
|
12
|
+
*/
|
|
13
|
+
input?: S
|
|
14
|
+
/**
|
|
15
|
+
* @zh 輸出的資料格式。
|
|
16
|
+
* @en The output data format.
|
|
17
|
+
*/
|
|
18
|
+
output: O
|
|
19
|
+
/**
|
|
20
|
+
* @zh 註冊解讀文字的解析器。
|
|
21
|
+
* @en Register the parser to interpret the text.
|
|
22
|
+
*/
|
|
23
|
+
parsers: TextParser[]
|
|
24
|
+
/**
|
|
25
|
+
* @zh 組合輸入資料成為提示文字。
|
|
26
|
+
* @en Combine the input data into a prompt.
|
|
27
|
+
*/
|
|
28
|
+
question?: (data: ValidateCallbackOutputs<S>, context: {
|
|
29
|
+
schema: {
|
|
30
|
+
input?: S
|
|
31
|
+
output: O
|
|
32
|
+
}
|
|
33
|
+
}) => Promise<string | string[]>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class Translator<
|
|
37
|
+
S extends ValidateCallback<any>,
|
|
38
|
+
O extends ValidateCallback<any>
|
|
39
|
+
> {
|
|
40
|
+
private params: TranslatorParams<S, O>
|
|
41
|
+
|
|
42
|
+
constructor(params: TranslatorParams<S, O>) {
|
|
43
|
+
this.params = params
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get __schemeType(): ValidateCallbackOutputs<S> {
|
|
47
|
+
return null as any
|
|
48
|
+
}
|
|
49
|
+
get __outputType(): ValidateCallbackOutputs<O> {
|
|
50
|
+
return null as any
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @zh 組合輸入資料成為提示文字。
|
|
55
|
+
* @en Combine the input data into a prompt.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
async compile(data: ValidateCallbackOutputs<S>, context: {
|
|
59
|
+
schema: {
|
|
60
|
+
input?: S
|
|
61
|
+
output: O
|
|
62
|
+
}
|
|
63
|
+
}) {
|
|
64
|
+
const scheme = this.params.input ? validate(data, this.params.input) : data
|
|
65
|
+
const prompt = this.params.question ? await this.params.question(scheme, context) : ''
|
|
66
|
+
return {
|
|
67
|
+
scheme,
|
|
68
|
+
prompt: Array.isArray(prompt) ? prompt.join('\n') : prompt
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getValidate() {
|
|
73
|
+
return {
|
|
74
|
+
input: this.params.input,
|
|
75
|
+
output: this.params.output
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
changeOutputSchema(schema: O) {
|
|
80
|
+
this.params.output = schema
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @zh 將文字轉換成序列化資料。
|
|
85
|
+
* @en Convert text to serialized data.
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
async parse(text: string) {
|
|
89
|
+
let result: any = undefined
|
|
90
|
+
let parserName = ''
|
|
91
|
+
let parserFails: { name: string, error: any }[] = []
|
|
92
|
+
for (let parse of this.params.parsers) {
|
|
93
|
+
try {
|
|
94
|
+
result = await parse.read(text)
|
|
95
|
+
parserName = parse.name
|
|
96
|
+
} catch (error) {
|
|
97
|
+
result = undefined
|
|
98
|
+
parserFails.push({
|
|
99
|
+
name: parse.name,
|
|
100
|
+
error
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
let output = validate(result, this.params.output)
|
|
106
|
+
return {
|
|
107
|
+
output,
|
|
108
|
+
parserName,
|
|
109
|
+
parserFails
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {
|
|
112
|
+
throw new ParserError(error, parserFails)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
package/lib/ctod.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ChatBroker, Message, Params as ChatBrokerParams, ChatBrokerHooks, RequestContext } from './broker/chat'
|
|
2
|
+
import { ChatBrokerPlugin } from './core/plugin'
|
|
3
|
+
import { Schema } from 'yup'
|
|
4
|
+
import * as Yup from 'yup'
|
|
5
|
+
|
|
6
|
+
type IO = any
|
|
7
|
+
|
|
8
|
+
export class CtoD<
|
|
9
|
+
P extends ChatBrokerPlugin<IO, IO>,
|
|
10
|
+
PS extends Record<string, ReturnType<P['use']>>
|
|
11
|
+
> {
|
|
12
|
+
params
|
|
13
|
+
constructor(params: {
|
|
14
|
+
request: (messages: Message[], context: RequestContext) => Promise<string>
|
|
15
|
+
plugins?: () => PS
|
|
16
|
+
}) {
|
|
17
|
+
this.params = params
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
createBrokerBuilder<I extends Record<string, any>>(params?: {
|
|
21
|
+
install?: ChatBrokerParams<() => I, IO, ChatBrokerHooks<() => I, IO, P, PS>, P, PS>['install']
|
|
22
|
+
}) {
|
|
23
|
+
return {
|
|
24
|
+
create: <O extends Record<string, Schema>>(install: (context: {
|
|
25
|
+
id: string
|
|
26
|
+
yup: typeof Yup
|
|
27
|
+
data: I
|
|
28
|
+
plugins: {
|
|
29
|
+
[K in keyof PS]: {
|
|
30
|
+
send: (data: PS[K]['__receiveData']) => void
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
setMessages: (messages: (Omit<Message, 'content'> & { content: string | string[] })[]) => void
|
|
34
|
+
metadata: Map<string, any>
|
|
35
|
+
}) => Promise<O>) => {
|
|
36
|
+
return new ChatBroker<
|
|
37
|
+
() => I,
|
|
38
|
+
() => O,
|
|
39
|
+
P,
|
|
40
|
+
PS,
|
|
41
|
+
ChatBrokerHooks<() => I, () => O, P, PS>
|
|
42
|
+
>({
|
|
43
|
+
output: () => ({} as any),
|
|
44
|
+
install: (context) => {
|
|
45
|
+
params?.install?.(context)
|
|
46
|
+
context.attach('start', async({ id, plugins, data, metadata, changeMessages, changeOutputSchema }) => {
|
|
47
|
+
const schema = await install({
|
|
48
|
+
id,
|
|
49
|
+
data: data as any,
|
|
50
|
+
plugins,
|
|
51
|
+
yup: Yup,
|
|
52
|
+
setMessages: (messages) => {
|
|
53
|
+
changeMessages(messages.map(e => {
|
|
54
|
+
return {
|
|
55
|
+
role: e.role,
|
|
56
|
+
content: Array.isArray(e.content) ? e.content.join('\n') : e.content
|
|
57
|
+
}
|
|
58
|
+
}))
|
|
59
|
+
},
|
|
60
|
+
metadata
|
|
61
|
+
})
|
|
62
|
+
changeOutputSchema(() => schema)
|
|
63
|
+
})
|
|
64
|
+
},
|
|
65
|
+
plugins: this.params.plugins ? (() => this.params.plugins!()) : undefined,
|
|
66
|
+
request: this.params.request
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
package/lib/index.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export * as plugins from './plugins'
|
|
2
|
+
export * as templates from './templates'
|
|
3
|
+
export { CtoD } from './ctod'
|
|
4
|
+
export { validateToJsonSchema, defineYupSchema, ValidateCallback } from './utils/validate'
|
|
5
|
+
export { OpenAI } from './service/openai'
|
|
6
|
+
export { Llama3Cpp } from './service/llama3.cpp'
|
|
7
|
+
export { TextParser } from './core/parser'
|
|
8
|
+
export { ChatGPTMessage } from './service/openai/chat'
|
|
9
|
+
export { ChatBroker } from './broker/chat'
|
|
10
|
+
export { ChatBrokerPlugin } from './core/plugin'
|
|
11
|
+
export { Translator, TranslatorParams } from './core/translator'
|
|
12
|
+
|
|
13
|
+
import * as plugins from './plugins'
|
|
14
|
+
import * as templates from './templates'
|
|
15
|
+
import { OpenAI } from './service/openai'
|
|
16
|
+
import { CtoD } from './ctod'
|
|
17
|
+
import { Llama3Cpp } from './service/llama3.cpp'
|
|
18
|
+
import { Translator } from './core/translator'
|
|
19
|
+
import { TextParser } from './core/parser'
|
|
20
|
+
import { ChatBroker } from './broker/chat'
|
|
21
|
+
import { ChatBrokerPlugin } from './core/plugin'
|
|
22
|
+
import { validateToJsonSchema, defineYupSchema } from './utils/validate'
|
|
23
|
+
|
|
24
|
+
export const ctod = {
|
|
25
|
+
CtoD,
|
|
26
|
+
OpenAI,
|
|
27
|
+
Llama3Cpp,
|
|
28
|
+
plugins,
|
|
29
|
+
templates,
|
|
30
|
+
ChatBroker,
|
|
31
|
+
Translator,
|
|
32
|
+
TextParser,
|
|
33
|
+
ChatBrokerPlugin,
|
|
34
|
+
defineYupSchema,
|
|
35
|
+
validateToJsonSchema
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = ctod
|
|
39
|
+
module.exports.ctod = ctod
|
|
40
|
+
|
|
41
|
+
export default ctod
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Retry from './retry'
|
|
2
|
+
import PrintLog from './print-log'
|
|
3
|
+
import Limiter from './limiter'
|
|
4
|
+
import Role from './role'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @zh 一個基於印出 log 的 plugin。
|
|
8
|
+
* @en A plugin based on printing log.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const PrintLogPlugin = PrintLog
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @zh 當解析失敗時,會自動重試的對話。
|
|
15
|
+
* @en A conversation that will automatically retry when parsing fails.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export const RetryPlugin = Retry
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @zh 限制使用流量,這個 plugin 可以有效讓所有對話不會再限制內同時發送,可用於在開發過程中遭遇伺服器因頻率過高而阻擋請求。
|
|
22
|
+
* @en Limit the use of traffic. This plugin can effectively prevent all conversations from being sent at the same time within the limit, and can be used when the server blocks requests due to high frequency during development.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export const LimiterPlugin = Limiter.plugin
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @zh 排程系統將全域託管,有什麼必要設定可以來更動它的狀態,例如:關閉排程。
|
|
29
|
+
* @en The scheduling system will be globally hosted. What is necessary to set can come to change its status, for example: close the schedule.
|
|
30
|
+
*/
|
|
31
|
+
export const LimiterPluginGlobState = Limiter
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @zh 設定角色扮演。
|
|
35
|
+
* @en Set role play.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
export const RolePlugin = Role
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { ChatBrokerPlugin } from '../core/plugin'
|
|
2
|
+
import { Event, flow, Schedule } from 'power-helper'
|
|
3
|
+
|
|
4
|
+
type Events = {
|
|
5
|
+
run: {
|
|
6
|
+
id: string
|
|
7
|
+
}
|
|
8
|
+
waitTimeChange: {
|
|
9
|
+
waitTime: number
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const config = {
|
|
14
|
+
limit: 3,
|
|
15
|
+
interval: 60000,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const state = {
|
|
19
|
+
event: new Event<Events>(),
|
|
20
|
+
schedule: null as Schedule | null,
|
|
21
|
+
waitTimes: [] as number[],
|
|
22
|
+
waitQueue: [] as string[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
/**
|
|
27
|
+
* @zh 你可以監聽一些事件行為,例如還需要等待多少時間。
|
|
28
|
+
* @en You can listen for some event behaviors, such as how long you still need to wait.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
event: state.event,
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @zh 預設是每分鐘限制3次,你可以在設定中改變限制流量。
|
|
35
|
+
* @en By default, the limit is 3 times per minute, and you can change the limit flow in the settings.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
config,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @zh 由於排程會在背景持續倒數,如果有關閉程式的需求,需要手動進行移除。
|
|
42
|
+
* @en Since the schedule will continue to count down in the background, if there is a need to close the program, you need to manually remove it.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
closeSchedule: () => {
|
|
46
|
+
if (state.schedule) {
|
|
47
|
+
state.schedule.close()
|
|
48
|
+
state.schedule = null
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @zh Plugin 的接口
|
|
54
|
+
* @en Plugin interface
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
plugin: new ChatBrokerPlugin({
|
|
58
|
+
name: 'limiter',
|
|
59
|
+
params: () => {
|
|
60
|
+
return {}
|
|
61
|
+
},
|
|
62
|
+
receiveData: () => {
|
|
63
|
+
return {}
|
|
64
|
+
},
|
|
65
|
+
onInstall({ attach }) {
|
|
66
|
+
if (state.schedule == null) {
|
|
67
|
+
state.schedule = new Schedule()
|
|
68
|
+
state.schedule.add('calc queue', 1000, async() => {
|
|
69
|
+
const now = Date.now()
|
|
70
|
+
state.waitTimes = state.waitTimes.filter(time => {
|
|
71
|
+
return now - time < config.interval
|
|
72
|
+
})
|
|
73
|
+
if (state.waitTimes.length !== config.limit) {
|
|
74
|
+
let nextId = state.waitQueue.shift()
|
|
75
|
+
if (nextId) {
|
|
76
|
+
state.waitTimes.push(Date.now())
|
|
77
|
+
state.event.emit('run', {
|
|
78
|
+
id: nextId
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
} else if (state.waitTimes[0]) {
|
|
82
|
+
state.event.emit('waitTimeChange', {
|
|
83
|
+
waitTime: Math.floor(60 - (now - state.waitTimes[0]) / 1000)
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
state.schedule.play()
|
|
88
|
+
}
|
|
89
|
+
attach('talkBefore', async() => {
|
|
90
|
+
const uid = flow.createUuid()
|
|
91
|
+
state.waitQueue.push(uid)
|
|
92
|
+
return new Promise(resolve => {
|
|
93
|
+
state.event.on('run', ({ id }, { off }) => {
|
|
94
|
+
if (id === uid) {
|
|
95
|
+
off()
|
|
96
|
+
resolve()
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ChatBrokerPlugin } from '../core/plugin'
|
|
2
|
+
|
|
3
|
+
export default new ChatBrokerPlugin({
|
|
4
|
+
name: 'print-log',
|
|
5
|
+
params: yup => {
|
|
6
|
+
return {
|
|
7
|
+
detail: yup.boolean().default(false)
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
receiveData: () => {
|
|
11
|
+
return {}
|
|
12
|
+
},
|
|
13
|
+
onInstall({ params, log, attach }) {
|
|
14
|
+
attach('talkBefore', async({ lastUserMessage, messages }) => {
|
|
15
|
+
log.print('Send:', { color: 'green' })
|
|
16
|
+
if (params.detail) {
|
|
17
|
+
log.print('\n' + JSON.stringify(messages, null, 4))
|
|
18
|
+
} else {
|
|
19
|
+
log.print('\n' + lastUserMessage)
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
attach('talkAfter', async({ parseText }) => {
|
|
23
|
+
log.print('Receive:', { color: 'cyan' })
|
|
24
|
+
log.print('\n' + parseText)
|
|
25
|
+
})
|
|
26
|
+
attach('succeeded', async({ output }) => {
|
|
27
|
+
log.print('Output:', { color: 'yellow' })
|
|
28
|
+
try {
|
|
29
|
+
log.print('\n' + JSON.stringify(output, null, 4))
|
|
30
|
+
} catch (error) {
|
|
31
|
+
log.print('\n' + output)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ChatBrokerPlugin } from '../core/plugin'
|
|
2
|
+
|
|
3
|
+
export default new ChatBrokerPlugin({
|
|
4
|
+
name: 'retry',
|
|
5
|
+
params: yup => {
|
|
6
|
+
return {
|
|
7
|
+
retry: yup.number().required().default(1),
|
|
8
|
+
printWarn: yup.boolean().required().default(true)
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
receiveData: () => {
|
|
12
|
+
return {}
|
|
13
|
+
},
|
|
14
|
+
onInstall({ log, attach, params }) {
|
|
15
|
+
attach('parseFailed', async({ count, retry, messages, changeMessages }) => {
|
|
16
|
+
if (count <= params.retry) {
|
|
17
|
+
if (params.printWarn) {
|
|
18
|
+
log.print(`Is Failed, Retry ${count} times.`)
|
|
19
|
+
}
|
|
20
|
+
changeMessages(messages)
|
|
21
|
+
retry()
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ChatBrokerPlugin } from '../core/plugin'
|
|
2
|
+
|
|
3
|
+
export default new ChatBrokerPlugin({
|
|
4
|
+
name: 'role',
|
|
5
|
+
params: yup => {
|
|
6
|
+
return {
|
|
7
|
+
role: yup.string().required()
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
receiveData: () => {
|
|
11
|
+
return {}
|
|
12
|
+
},
|
|
13
|
+
onInstall({ attach, params }) {
|
|
14
|
+
attach('start', async({ messages, changeMessages }) => {
|
|
15
|
+
changeMessages([
|
|
16
|
+
{
|
|
17
|
+
role: 'user',
|
|
18
|
+
content: `你現在是${params.role}。`
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
role: 'assistant',
|
|
22
|
+
content: `沒問題,我現在是${params.role},有什麼可以幫你的嗎?`
|
|
23
|
+
},
|
|
24
|
+
...messages
|
|
25
|
+
])
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
})
|