@livekit/agents-plugin-livekit 0.1.3 → 1.0.0-next.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.
- package/dist/hf_utils.cjs +272 -0
- package/dist/hf_utils.cjs.map +1 -0
- package/dist/hf_utils.d.cts +40 -0
- package/dist/hf_utils.d.ts +40 -0
- package/dist/hf_utils.d.ts.map +1 -0
- package/dist/hf_utils.js +237 -0
- package/dist/hf_utils.js.map +1 -0
- package/dist/hf_utils.test.cjs +330 -0
- package/dist/hf_utils.test.cjs.map +1 -0
- package/dist/hf_utils.test.d.cts +2 -0
- package/dist/hf_utils.test.d.ts +2 -0
- package/dist/hf_utils.test.d.ts.map +1 -0
- package/dist/hf_utils.test.js +307 -0
- package/dist/hf_utils.test.js.map +1 -0
- package/dist/index.cjs +27 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -6
- package/dist/index.js.map +1 -1
- package/dist/turn_detector/base.cjs +202 -0
- package/dist/turn_detector/base.cjs.map +1 -0
- package/dist/turn_detector/base.d.cts +52 -0
- package/dist/turn_detector/base.d.ts +52 -0
- package/dist/turn_detector/base.d.ts.map +1 -0
- package/dist/turn_detector/base.js +172 -0
- package/dist/turn_detector/base.js.map +1 -0
- package/dist/turn_detector/constants.cjs +44 -0
- package/dist/turn_detector/constants.cjs.map +1 -0
- package/dist/turn_detector/constants.d.cts +7 -0
- package/dist/turn_detector/constants.d.ts +7 -0
- package/dist/turn_detector/constants.d.ts.map +1 -0
- package/dist/turn_detector/constants.js +16 -0
- package/dist/turn_detector/constants.js.map +1 -0
- package/dist/turn_detector/english.cjs +52 -0
- package/dist/turn_detector/english.cjs.map +1 -0
- package/dist/turn_detector/english.d.cts +11 -0
- package/dist/turn_detector/english.d.ts +11 -0
- package/dist/turn_detector/english.d.ts.map +1 -0
- package/dist/turn_detector/english.js +26 -0
- package/dist/turn_detector/english.js.map +1 -0
- package/dist/turn_detector/index.cjs +53 -0
- package/dist/turn_detector/index.cjs.map +1 -0
- package/dist/turn_detector/index.d.cts +5 -0
- package/dist/turn_detector/index.d.ts +5 -0
- package/dist/turn_detector/index.d.ts.map +1 -0
- package/dist/turn_detector/index.js +23 -0
- package/dist/turn_detector/index.js.map +1 -0
- package/dist/turn_detector/multilingual.cjs +144 -0
- package/dist/turn_detector/multilingual.cjs.map +1 -0
- package/dist/turn_detector/multilingual.d.cts +15 -0
- package/dist/turn_detector/multilingual.d.ts +15 -0
- package/dist/turn_detector/multilingual.d.ts.map +1 -0
- package/dist/turn_detector/multilingual.js +118 -0
- package/dist/turn_detector/multilingual.js.map +1 -0
- package/dist/turn_detector/utils.cjs +54 -0
- package/dist/turn_detector/utils.cjs.map +1 -0
- package/dist/turn_detector/utils.d.cts +35 -0
- package/dist/turn_detector/utils.d.ts +35 -0
- package/dist/turn_detector/utils.d.ts.map +1 -0
- package/dist/turn_detector/utils.js +29 -0
- package/dist/turn_detector/utils.js.map +1 -0
- package/dist/turn_detector/utils.test.cjs +196 -0
- package/dist/turn_detector/utils.test.cjs.map +1 -0
- package/dist/turn_detector/utils.test.d.cts +2 -0
- package/dist/turn_detector/utils.test.d.ts +2 -0
- package/dist/turn_detector/utils.test.d.ts.map +1 -0
- package/dist/turn_detector/utils.test.js +195 -0
- package/dist/turn_detector/utils.test.js.map +1 -0
- package/package.json +5 -4
- package/src/hf_utils.test.ts +392 -0
- package/src/hf_utils.ts +365 -0
- package/src/index.ts +32 -9
- package/src/turn_detector/base.ts +238 -0
- package/src/turn_detector/constants.ts +16 -0
- package/src/turn_detector/english.ts +27 -0
- package/src/turn_detector/index.ts +21 -0
- package/src/turn_detector/multilingual.ts +145 -0
- package/src/turn_detector/utils.test.ts +231 -0
- package/src/turn_detector/utils.ts +76 -0
- package/dist/turn_detector.cjs +0 -129
- package/dist/turn_detector.cjs.map +0 -1
- package/dist/turn_detector.d.cts +0 -22
- package/dist/turn_detector.d.ts +0 -22
- package/dist/turn_detector.d.ts.map +0 -1
- package/dist/turn_detector.js +0 -102
- package/dist/turn_detector.js.map +0 -1
- package/dist/turn_detector.onnx +0 -0
- package/src/turn_detector.onnx +0 -0
- package/src/turn_detector.ts +0 -121
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { InferenceRunner } from '@livekit/agents';
|
|
5
|
+
import { INFERENCE_METHOD_EN } from './english.js';
|
|
6
|
+
import { INFERENCE_METHOD_MULTILINGUAL } from './multilingual.js';
|
|
7
|
+
|
|
8
|
+
export { EOUModel } from './base.js';
|
|
9
|
+
export { EnglishModel } from './english.js';
|
|
10
|
+
export { MultilingualModel } from './multilingual.js';
|
|
11
|
+
export { getUnicodeCategory, normalizeText } from './utils.js';
|
|
12
|
+
|
|
13
|
+
InferenceRunner.registerRunner(
|
|
14
|
+
INFERENCE_METHOD_EN,
|
|
15
|
+
new URL('./english.js', import.meta.url).toString(),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
InferenceRunner.registerRunner(
|
|
19
|
+
INFERENCE_METHOD_MULTILINGUAL,
|
|
20
|
+
new URL('./multilingual.js', import.meta.url).toString(),
|
|
21
|
+
);
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import type { llm } from '@livekit/agents';
|
|
5
|
+
import { getJobContext, log } from '@livekit/agents';
|
|
6
|
+
import { EOUModel, EOURunnerBase } from './base.js';
|
|
7
|
+
import { MAX_HISTORY_TURNS } from './constants.js';
|
|
8
|
+
|
|
9
|
+
const REMOTE_INFERENCE_TIMEOUT = 2000;
|
|
10
|
+
|
|
11
|
+
export const INFERENCE_METHOD_MULTILINGUAL = 'lk_end_of_utterance_multilingual';
|
|
12
|
+
|
|
13
|
+
export class EUORunnerMultilingual extends EOURunnerBase {
|
|
14
|
+
constructor() {
|
|
15
|
+
super('multilingual');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class MultilingualModel extends EOUModel {
|
|
20
|
+
#logger = log();
|
|
21
|
+
|
|
22
|
+
constructor(unlikelyThreshold?: number) {
|
|
23
|
+
super({
|
|
24
|
+
modelType: 'multilingual',
|
|
25
|
+
unlikelyThreshold,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
inferenceMethod(): string {
|
|
30
|
+
return INFERENCE_METHOD_MULTILINGUAL;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async unlikelyThreshold(language?: string): Promise<number | undefined> {
|
|
34
|
+
if (!language) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let threshold = await super.unlikelyThreshold(language);
|
|
39
|
+
if (threshold === undefined) {
|
|
40
|
+
const url = remoteInferenceUrl();
|
|
41
|
+
if (!url) return undefined;
|
|
42
|
+
|
|
43
|
+
const resp = await fetch(url, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
language,
|
|
47
|
+
}),
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
},
|
|
51
|
+
signal: AbortSignal.timeout(REMOTE_INFERENCE_TIMEOUT),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!resp.ok) {
|
|
55
|
+
throw new Error(`Failed to fetch threshold: ${resp.statusText}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const data = (await resp.json()) as { threshold: number | undefined };
|
|
59
|
+
threshold = data.threshold;
|
|
60
|
+
if (threshold) {
|
|
61
|
+
const languages = await this.languagesFuture.await;
|
|
62
|
+
languages[language] = { threshold };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return threshold;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async predictEndOfTurn(chatCtx: llm.ChatContext, timeout: number = 3): Promise<number> {
|
|
70
|
+
const url = remoteInferenceUrl();
|
|
71
|
+
if (!url) {
|
|
72
|
+
return await super.predictEndOfTurn(chatCtx, timeout);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Copy and process chat context similar to Python implementation
|
|
76
|
+
const messages = chatCtx
|
|
77
|
+
.copy({
|
|
78
|
+
excludeFunctionCall: true,
|
|
79
|
+
excludeInstructions: true,
|
|
80
|
+
excludeEmptyMessage: true,
|
|
81
|
+
})
|
|
82
|
+
.truncate(MAX_HISTORY_TURNS);
|
|
83
|
+
|
|
84
|
+
// Get job context and build request
|
|
85
|
+
const ctx = getJobContext();
|
|
86
|
+
const request: any = {
|
|
87
|
+
...messages.toJSON({
|
|
88
|
+
excludeImage: true,
|
|
89
|
+
excludeAudio: true,
|
|
90
|
+
excludeTimestamp: true,
|
|
91
|
+
}),
|
|
92
|
+
jobId: ctx.job.id,
|
|
93
|
+
workerId: ctx.workerId,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Add agentId from environment variable if available
|
|
97
|
+
const agentId = process.env.LIVEKIT_AGENT_ID;
|
|
98
|
+
if (agentId) {
|
|
99
|
+
request.agentId = agentId;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const startedAt = performance.now();
|
|
103
|
+
|
|
104
|
+
this.#logger.debug({ url, request }, '=== remote EOU inference');
|
|
105
|
+
|
|
106
|
+
const resp = await fetch(url, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
body: JSON.stringify(request),
|
|
109
|
+
headers: {
|
|
110
|
+
'Content-Type': 'application/json',
|
|
111
|
+
},
|
|
112
|
+
signal: AbortSignal.timeout(REMOTE_INFERENCE_TIMEOUT),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (!resp.ok) {
|
|
116
|
+
throw new Error(`Failed to predict end of turn: ${resp.statusText}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const data = await resp.json();
|
|
120
|
+
const probability = data.probability;
|
|
121
|
+
if (typeof probability === 'number' && probability >= 0) {
|
|
122
|
+
this.#logger.debug(
|
|
123
|
+
{
|
|
124
|
+
eouProbability: probability,
|
|
125
|
+
duration: (performance.now() - startedAt) / 1000,
|
|
126
|
+
},
|
|
127
|
+
'eou prediction',
|
|
128
|
+
);
|
|
129
|
+
return probability;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// default to indicate no prediction
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function remoteInferenceUrl() {
|
|
138
|
+
const urlBase = process.env.LIVEKIT_REMOTE_EOT_URL;
|
|
139
|
+
if (!urlBase) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
return `${urlBase}/eot/multi`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export default EUORunnerMultilingual;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { getUnicodeCategory, normalizeText } from './utils.js';
|
|
6
|
+
|
|
7
|
+
describe('getUnicodeCategory', () => {
|
|
8
|
+
it('should identify basic ASCII punctuation', () => {
|
|
9
|
+
expect(getUnicodeCategory('!')).toBe('P');
|
|
10
|
+
expect(getUnicodeCategory('"')).toBe('P');
|
|
11
|
+
expect(getUnicodeCategory('#')).toBe('P');
|
|
12
|
+
expect(getUnicodeCategory('$')).toBe('P');
|
|
13
|
+
expect(getUnicodeCategory('%')).toBe('P');
|
|
14
|
+
expect(getUnicodeCategory('&')).toBe('P');
|
|
15
|
+
expect(getUnicodeCategory("'")).toBe('P');
|
|
16
|
+
expect(getUnicodeCategory('(')).toBe('P');
|
|
17
|
+
expect(getUnicodeCategory(')')).toBe('P');
|
|
18
|
+
expect(getUnicodeCategory('*')).toBe('P');
|
|
19
|
+
expect(getUnicodeCategory('+')).toBe('P');
|
|
20
|
+
expect(getUnicodeCategory(',')).toBe('P');
|
|
21
|
+
expect(getUnicodeCategory('-')).toBe('P');
|
|
22
|
+
expect(getUnicodeCategory('.')).toBe('P');
|
|
23
|
+
expect(getUnicodeCategory('/')).toBe('P');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should identify colon/semicolon punctuation', () => {
|
|
27
|
+
expect(getUnicodeCategory(':')).toBe('P');
|
|
28
|
+
expect(getUnicodeCategory(';')).toBe('P');
|
|
29
|
+
expect(getUnicodeCategory('<')).toBe('P');
|
|
30
|
+
expect(getUnicodeCategory('=')).toBe('P');
|
|
31
|
+
expect(getUnicodeCategory('>')).toBe('P');
|
|
32
|
+
expect(getUnicodeCategory('?')).toBe('P');
|
|
33
|
+
expect(getUnicodeCategory('@')).toBe('P');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should identify bracket punctuation', () => {
|
|
37
|
+
expect(getUnicodeCategory('[')).toBe('P');
|
|
38
|
+
expect(getUnicodeCategory('\\')).toBe('P');
|
|
39
|
+
expect(getUnicodeCategory(']')).toBe('P');
|
|
40
|
+
expect(getUnicodeCategory('^')).toBe('P');
|
|
41
|
+
expect(getUnicodeCategory('_')).toBe('P');
|
|
42
|
+
expect(getUnicodeCategory('`')).toBe('P');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should identify brace punctuation', () => {
|
|
46
|
+
expect(getUnicodeCategory('{')).toBe('P');
|
|
47
|
+
expect(getUnicodeCategory('|')).toBe('P');
|
|
48
|
+
expect(getUnicodeCategory('}')).toBe('P');
|
|
49
|
+
expect(getUnicodeCategory('~')).toBe('P');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should identify extended punctuation', () => {
|
|
53
|
+
expect(getUnicodeCategory('¡')).toBe('P');
|
|
54
|
+
expect(getUnicodeCategory('¿')).toBe('P');
|
|
55
|
+
expect(getUnicodeCategory('«')).toBe('P');
|
|
56
|
+
expect(getUnicodeCategory('»')).toBe('P');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should not identify letters as punctuation', () => {
|
|
60
|
+
expect(getUnicodeCategory('a')).toBe('');
|
|
61
|
+
expect(getUnicodeCategory('A')).toBe('');
|
|
62
|
+
expect(getUnicodeCategory('z')).toBe('');
|
|
63
|
+
expect(getUnicodeCategory('Z')).toBe('');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should not identify numbers as punctuation', () => {
|
|
67
|
+
expect(getUnicodeCategory('0')).toBe('');
|
|
68
|
+
expect(getUnicodeCategory('1')).toBe('');
|
|
69
|
+
expect(getUnicodeCategory('9')).toBe('');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should not identify whitespace as punctuation', () => {
|
|
73
|
+
expect(getUnicodeCategory(' ')).toBe('');
|
|
74
|
+
expect(getUnicodeCategory('\t')).toBe('');
|
|
75
|
+
expect(getUnicodeCategory('\n')).toBe('');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should handle empty string', () => {
|
|
79
|
+
expect(getUnicodeCategory('')).toBe('');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should handle unicode characters', () => {
|
|
83
|
+
expect(getUnicodeCategory('é')).toBe('');
|
|
84
|
+
expect(getUnicodeCategory('ñ')).toBe('');
|
|
85
|
+
expect(getUnicodeCategory('ç')).toBe('');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('normalizeText', () => {
|
|
90
|
+
describe('basic functionality', () => {
|
|
91
|
+
it('should convert to lowercase', () => {
|
|
92
|
+
expect(normalizeText('HELLO')).toBe('hello');
|
|
93
|
+
expect(normalizeText('HeLLo')).toBe('hello');
|
|
94
|
+
expect(normalizeText('WORLD')).toBe('world');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should remove basic punctuation', () => {
|
|
98
|
+
expect(normalizeText('Hello!')).toBe('hello');
|
|
99
|
+
expect(normalizeText('Hello?')).toBe('hello');
|
|
100
|
+
expect(normalizeText('Hello.')).toBe('hello');
|
|
101
|
+
expect(normalizeText('Hello,')).toBe('hello');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should preserve apostrophes', () => {
|
|
105
|
+
expect(normalizeText("I'm happy")).toBe("i'm happy");
|
|
106
|
+
expect(normalizeText("don't worry")).toBe("don't worry");
|
|
107
|
+
expect(normalizeText("it's great")).toBe("it's great");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should preserve hyphens', () => {
|
|
111
|
+
expect(normalizeText('well-trained')).toBe('well-trained');
|
|
112
|
+
expect(normalizeText('state-of-the-art')).toBe('state-of-the-art');
|
|
113
|
+
expect(normalizeText('co-worker')).toBe('co-worker');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should collapse multiple whitespace', () => {
|
|
117
|
+
expect(normalizeText('hello world')).toBe('hello world');
|
|
118
|
+
expect(normalizeText('multiple spaces here')).toBe('multiple spaces here');
|
|
119
|
+
expect(normalizeText('tab\t\tspaces')).toBe('tab spaces');
|
|
120
|
+
expect(normalizeText('newline\n\nspaces')).toBe('newline spaces');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should trim leading and trailing whitespace', () => {
|
|
124
|
+
expect(normalizeText(' hello ')).toBe('hello');
|
|
125
|
+
expect(normalizeText('\t\nhello\t\n')).toBe('hello');
|
|
126
|
+
expect(normalizeText(' hello world ')).toBe('hello world');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe('comprehensive test cases', () => {
|
|
131
|
+
it('should handle the basic greeting case', () => {
|
|
132
|
+
expect(normalizeText('Hi, how can I help you today?')).toBe('hi how can i help you today');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should handle contractions and hyphens', () => {
|
|
136
|
+
expect(normalizeText("I'm a well-trained assistant!")).toBe("i'm a well-trained assistant");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should remove various punctuation types', () => {
|
|
140
|
+
expect(normalizeText('Hello!!! What??? Price: $19.99 (20% off).')).toBe(
|
|
141
|
+
'hello what price 1999 20 off',
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should handle multiple spaces', () => {
|
|
146
|
+
expect(normalizeText('Multiple spaces here')).toBe('multiple spaces here');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should handle unicode characters', () => {
|
|
150
|
+
expect(normalizeText('Café entrées naïve résumé')).toBe('café entrées naïve résumé');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should handle mixed punctuation and unicode', () => {
|
|
154
|
+
expect(normalizeText('¿Cómo estás? ¡Muy bien!')).toBe('cómo estás muy bien');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('edge cases', () => {
|
|
159
|
+
it('should handle empty string', () => {
|
|
160
|
+
expect(normalizeText('')).toBe('');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should handle whitespace-only string', () => {
|
|
164
|
+
expect(normalizeText(' ')).toBe('');
|
|
165
|
+
expect(normalizeText('\t\n ')).toBe('');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should handle punctuation-only string', () => {
|
|
169
|
+
expect(normalizeText('!!!')).toBe('');
|
|
170
|
+
expect(normalizeText('???')).toBe('');
|
|
171
|
+
expect(normalizeText('...')).toBe('');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should handle mixed punctuation and preserved characters', () => {
|
|
175
|
+
expect(normalizeText('!@#$%^&*()_+-={}[]|\\:;"\'<>?,./')).toBe("-'");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should handle numbers with punctuation', () => {
|
|
179
|
+
expect(normalizeText('$19.99')).toBe('1999');
|
|
180
|
+
expect(normalizeText('(555) 123-4567')).toBe('555 123-4567');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('should handle special unicode punctuation', () => {
|
|
184
|
+
expect(normalizeText('Hello… world!')).toBe('hello world');
|
|
185
|
+
expect(normalizeText('"Quoted text"')).toBe('quoted text');
|
|
186
|
+
expect(normalizeText("'Single quotes'")).toBe("'single quotes'");
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('unicode normalization', () => {
|
|
191
|
+
it('should apply NFKC normalization', () => {
|
|
192
|
+
expect(normalizeText('café')).toBe('café');
|
|
193
|
+
expect(normalizeText('naïve')).toBe('naïve');
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should handle combining characters', () => {
|
|
197
|
+
const eWithCombiningAcute = 'caf\u0065\u0301';
|
|
198
|
+
const precomposedE = 'café';
|
|
199
|
+
expect(normalizeText(eWithCombiningAcute)).toBe(normalizeText(precomposedE));
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('real-world examples', () => {
|
|
204
|
+
it('should handle typical assistant responses', () => {
|
|
205
|
+
expect(normalizeText('Hello! How can I assist you today?')).toBe(
|
|
206
|
+
'hello how can i assist you today',
|
|
207
|
+
);
|
|
208
|
+
expect(normalizeText("I'm here to help with any questions you might have.")).toBe(
|
|
209
|
+
"i'm here to help with any questions you might have",
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should handle typical user queries', () => {
|
|
214
|
+
expect(normalizeText("What's the weather like?")).toBe("what's the weather like");
|
|
215
|
+
expect(normalizeText('Can you help me with my order?')).toBe('can you help me with my order');
|
|
216
|
+
expect(normalizeText('I need assistance, please!')).toBe('i need assistance please');
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('should handle incomplete sentences', () => {
|
|
220
|
+
expect(normalizeText('What is the weather in')).toBe('what is the weather in');
|
|
221
|
+
expect(normalizeText('I am looking for')).toBe('i am looking for');
|
|
222
|
+
expect(normalizeText('Could you please')).toBe('could you please');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('should handle multilingual text', () => {
|
|
226
|
+
expect(normalizeText('Bonjour! Comment ça va?')).toBe('bonjour comment ça va');
|
|
227
|
+
expect(normalizeText('¡Hola! ¿Cómo estás?')).toBe('hola cómo estás');
|
|
228
|
+
expect(normalizeText('Guten Tag! Wie geht es Ihnen?')).toBe('guten tag wie geht es ihnen');
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Text normalization utilities for EOU turn detector
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Simple unicode category detection for punctuation
|
|
11
|
+
* Mimics Python's unicodedata.category() for punctuation detection
|
|
12
|
+
*/
|
|
13
|
+
export function getUnicodeCategory(char: string): string {
|
|
14
|
+
const code = char.codePointAt(0);
|
|
15
|
+
if (!code) return '';
|
|
16
|
+
|
|
17
|
+
// Basic punctuation ranges (simplified version to match Python unicodedata.category)
|
|
18
|
+
if (
|
|
19
|
+
(code >= 0x21 && code <= 0x2f) || // !"#$%&'()*+,-./
|
|
20
|
+
(code >= 0x3a && code <= 0x40) || // :;<=>?@
|
|
21
|
+
(code >= 0x5b && code <= 0x60) || // [\]^_`
|
|
22
|
+
(code >= 0x7b && code <= 0x7e) || // {|}~
|
|
23
|
+
(code >= 0xa0 && code <= 0xbf) || // Latin-1 punctuation
|
|
24
|
+
(code >= 0x2000 && code <= 0x206f) || // General punctuation
|
|
25
|
+
(code >= 0x3000 && code <= 0x303f)
|
|
26
|
+
) {
|
|
27
|
+
// CJK symbols and punctuation
|
|
28
|
+
return 'P';
|
|
29
|
+
}
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Normalizes text to match the training data format used by the EOU model
|
|
35
|
+
*
|
|
36
|
+
* This function applies the following transformations:
|
|
37
|
+
* 1. Converts to lowercase
|
|
38
|
+
* 2. Applies Unicode NFKC normalization
|
|
39
|
+
* 3. Removes all punctuation except apostrophes (') and hyphens (-)
|
|
40
|
+
* 4. Collapses multiple whitespace characters into single spaces
|
|
41
|
+
* 5. Trims leading and trailing whitespace
|
|
42
|
+
*
|
|
43
|
+
* @param text - The input text to normalize
|
|
44
|
+
* @returns The normalized text
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* normalizeText("Hi, how can I help you today?")
|
|
49
|
+
* // Returns: "hi how can i help you today"
|
|
50
|
+
*
|
|
51
|
+
* normalizeText("I'm a well-trained assistant!")
|
|
52
|
+
* // Returns: "i'm a well-trained assistant"
|
|
53
|
+
*
|
|
54
|
+
* normalizeText("Price: $19.99 (20% off).")
|
|
55
|
+
* // Returns: "price 1999 20 off"
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function normalizeText(text: string): string {
|
|
59
|
+
if (!text) return '';
|
|
60
|
+
|
|
61
|
+
let normalized = text.toLowerCase().normalize('NFKC');
|
|
62
|
+
|
|
63
|
+
// Remove punctuation except apostrophes and hyphens
|
|
64
|
+
// Using character-by-character approach to match Python logic
|
|
65
|
+
normalized = Array.from(normalized)
|
|
66
|
+
.filter((ch) => {
|
|
67
|
+
const category = getUnicodeCategory(ch);
|
|
68
|
+
return !(category.startsWith('P') && ch !== "'" && ch !== '-');
|
|
69
|
+
})
|
|
70
|
+
.join('');
|
|
71
|
+
|
|
72
|
+
// Collapse whitespace and trim
|
|
73
|
+
normalized = normalized.replace(/\s+/g, ' ').trim();
|
|
74
|
+
|
|
75
|
+
return normalized;
|
|
76
|
+
}
|
package/dist/turn_detector.cjs
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var turn_detector_exports = {};
|
|
20
|
-
__export(turn_detector_exports, {
|
|
21
|
-
EOUModel: () => EOUModel,
|
|
22
|
-
EOURunner: () => EOURunner,
|
|
23
|
-
default: () => turn_detector_default
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(turn_detector_exports);
|
|
26
|
-
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
|
|
27
|
-
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
28
|
-
var import_transformers = require("@huggingface/transformers");
|
|
29
|
-
var import_agents = require("@livekit/agents");
|
|
30
|
-
var import_node_url = require("node:url");
|
|
31
|
-
var import_onnxruntime_node = require("onnxruntime-node");
|
|
32
|
-
const MAX_HISTORY = 4;
|
|
33
|
-
class EOURunner extends import_agents.InferenceRunner {
|
|
34
|
-
static INFERENCE_METHOD = "lk_end_of_utterance";
|
|
35
|
-
#tokenizerPromise;
|
|
36
|
-
#session;
|
|
37
|
-
#tokenizer;
|
|
38
|
-
#logger = (0, import_agents.log)();
|
|
39
|
-
constructor() {
|
|
40
|
-
super();
|
|
41
|
-
this.#tokenizerPromise = import_transformers.AutoTokenizer.from_pretrained("livekit/turn-detector", {
|
|
42
|
-
revision: "v1.2.0"
|
|
43
|
-
// local_files_only: true, // TODO(nbsp): can't find it
|
|
44
|
-
});
|
|
45
|
-
this.#session = import_onnxruntime_node.InferenceSession.create(
|
|
46
|
-
(0, import_node_url.fileURLToPath)(new URL("turn_detector.onnx", importMetaUrl).href),
|
|
47
|
-
{
|
|
48
|
-
executionProviders: [{ name: "cpu" }]
|
|
49
|
-
}
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
async initialize() {
|
|
53
|
-
this.#tokenizer = await this.#tokenizerPromise;
|
|
54
|
-
}
|
|
55
|
-
async run(data) {
|
|
56
|
-
const text = this.#formatChatContext(data);
|
|
57
|
-
const startTime = Date.now();
|
|
58
|
-
const inputs = this.#tokenizer.encode(text, { add_special_tokens: false });
|
|
59
|
-
const outputs = await this.#session.then(
|
|
60
|
-
(session) => session.run({ input_ids: new import_onnxruntime_node.Tensor("int64", inputs, [1, inputs.length]) }, ["prob"])
|
|
61
|
-
);
|
|
62
|
-
const endTime = Date.now();
|
|
63
|
-
const logits = outputs.prob;
|
|
64
|
-
const eouProbability = logits.data[0];
|
|
65
|
-
this.#logger.child({ eouProbability, input: text, duration: endTime - startTime }).debug("eou prediction");
|
|
66
|
-
return eouProbability;
|
|
67
|
-
}
|
|
68
|
-
#formatChatContext(ctx) {
|
|
69
|
-
const newCtx = [];
|
|
70
|
-
for (const msg of ctx) {
|
|
71
|
-
if (!msg.content) continue;
|
|
72
|
-
newCtx.push(msg);
|
|
73
|
-
}
|
|
74
|
-
const convoText = this.#tokenizer.apply_chat_template(newCtx, {
|
|
75
|
-
add_generation_prompt: false,
|
|
76
|
-
tokenize: false
|
|
77
|
-
});
|
|
78
|
-
return convoText.slice(0, convoText.lastIndexOf("<|im_end|>"));
|
|
79
|
-
}
|
|
80
|
-
async close() {
|
|
81
|
-
await this.#session.then((session) => session.release());
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
class EOUModel {
|
|
85
|
-
unlikelyThreshold;
|
|
86
|
-
#executor;
|
|
87
|
-
constructor(unlikelyThreshold = 0.15) {
|
|
88
|
-
this.unlikelyThreshold = unlikelyThreshold;
|
|
89
|
-
this.#executor = import_agents.CurrentJobContext.getCurrent().inferenceExecutor;
|
|
90
|
-
}
|
|
91
|
-
supportsLanguage(language) {
|
|
92
|
-
if (!language) return false;
|
|
93
|
-
const parts = language.toLowerCase().split("-");
|
|
94
|
-
return parts[0] === "en" || parts[0] === "english";
|
|
95
|
-
}
|
|
96
|
-
async predictEndOfTurn(chatCtx) {
|
|
97
|
-
let messages = [];
|
|
98
|
-
for (const msg of chatCtx.messages) {
|
|
99
|
-
if (msg.role !== import_agents.llm.ChatRole.ASSISTANT && msg.role !== import_agents.llm.ChatRole.USER) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
if (typeof msg.content === "string") {
|
|
103
|
-
messages.push({
|
|
104
|
-
role: msg.role === import_agents.llm.ChatRole.ASSISTANT ? "assistant" : "user",
|
|
105
|
-
content: msg.content
|
|
106
|
-
});
|
|
107
|
-
} else if (Array.isArray(msg.content)) {
|
|
108
|
-
for (const content of msg.content) {
|
|
109
|
-
if (typeof content === "string") {
|
|
110
|
-
messages.push({
|
|
111
|
-
role: msg.role === import_agents.llm.ChatRole.ASSISTANT ? "assistant" : "user",
|
|
112
|
-
content
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
messages = messages.slice(-MAX_HISTORY);
|
|
119
|
-
const result = await this.#executor.doInference(EOURunner.INFERENCE_METHOD, messages);
|
|
120
|
-
return result;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
var turn_detector_default = EOURunner;
|
|
124
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
125
|
-
0 && (module.exports = {
|
|
126
|
-
EOUModel,
|
|
127
|
-
EOURunner
|
|
128
|
-
});
|
|
129
|
-
//# sourceMappingURL=turn_detector.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/turn_detector.ts","../../../node_modules/.pnpm/tsup@8.3.5_@microsoft+api-extractor@7.43.7_@types+node@22.5.5__postcss@8.4.38_tsx@4.19.2_typescript@5.4.5/node_modules/tsup/assets/cjs_shims.js"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { PreTrainedTokenizer } from '@huggingface/transformers';\nimport { AutoTokenizer } from '@huggingface/transformers';\nimport type { ipc } from '@livekit/agents';\nimport { CurrentJobContext, InferenceRunner, llm, log } from '@livekit/agents';\nimport { fileURLToPath } from 'node:url';\nimport { InferenceSession, Tensor } from 'onnxruntime-node';\n\nconst MAX_HISTORY = 4;\n\ntype RawChatContext = { role: string; content: string }[];\n\nexport class EOURunner extends InferenceRunner {\n static INFERENCE_METHOD = 'lk_end_of_utterance';\n #tokenizerPromise: Promise<PreTrainedTokenizer>;\n #session: Promise<InferenceSession>;\n #tokenizer?: PreTrainedTokenizer;\n #logger = log();\n\n constructor() {\n super();\n this.#tokenizerPromise = AutoTokenizer.from_pretrained('livekit/turn-detector', {\n revision: 'v1.2.0',\n // local_files_only: true, // TODO(nbsp): can't find it\n });\n this.#session = InferenceSession.create(\n fileURLToPath(new URL('turn_detector.onnx', import.meta.url).href),\n {\n executionProviders: [{ name: 'cpu' }],\n },\n );\n }\n\n async initialize() {\n this.#tokenizer = await this.#tokenizerPromise;\n }\n\n async run(data: RawChatContext): Promise<number | undefined> {\n const text = this.#formatChatContext(data);\n const startTime = Date.now();\n const inputs = this.#tokenizer!.encode(text, { add_special_tokens: false });\n const outputs = await this.#session.then((session) =>\n session.run({ input_ids: new Tensor('int64', inputs, [1, inputs.length]) }, ['prob']),\n );\n const endTime = Date.now();\n const logits = outputs.prob!;\n const eouProbability = logits.data[0] as number;\n this.#logger\n .child({ eouProbability, input: text, duration: endTime - startTime })\n .debug('eou prediction');\n return eouProbability;\n }\n\n #formatChatContext(ctx: RawChatContext): string {\n const newCtx: RawChatContext = [];\n for (const msg of ctx) {\n if (!msg.content) continue;\n newCtx.push(msg);\n }\n\n const convoText = this.#tokenizer!.apply_chat_template(newCtx, {\n add_generation_prompt: false,\n tokenize: false,\n }) as string;\n // remove EOU token from current utterance\n return convoText.slice(0, convoText.lastIndexOf('<|im_end|>'));\n }\n\n async close() {\n await this.#session.then((session) => session.release());\n }\n}\n\nexport class EOUModel {\n readonly unlikelyThreshold: number;\n #executor: ipc.InferenceExecutor;\n\n constructor(unlikelyThreshold = 0.15) {\n this.unlikelyThreshold = unlikelyThreshold;\n this.#executor = CurrentJobContext.getCurrent().inferenceExecutor;\n }\n\n supportsLanguage(language?: string) {\n if (!language) return false;\n const parts = language.toLowerCase().split('-');\n return parts[0] === 'en' || parts[0] === 'english';\n }\n\n async predictEndOfTurn(chatCtx: llm.ChatContext): Promise<number> {\n let messages: RawChatContext = [];\n\n for (const msg of chatCtx.messages) {\n if (msg.role !== llm.ChatRole.ASSISTANT && msg.role !== llm.ChatRole.USER) {\n continue;\n }\n\n if (typeof msg.content === 'string') {\n messages.push({\n role: msg.role === llm.ChatRole.ASSISTANT ? 'assistant' : 'user',\n content: msg.content,\n });\n } else if (Array.isArray(msg.content)) {\n for (const content of msg.content) {\n if (typeof content === 'string') {\n messages.push({\n role: msg.role === llm.ChatRole.ASSISTANT ? 'assistant' : 'user',\n content: content,\n });\n }\n }\n }\n }\n messages = messages.slice(-MAX_HISTORY);\n const result = await this.#executor.doInference(EOURunner.INFERENCE_METHOD, messages);\n return result as any;\n }\n}\n\nexport default EOURunner;\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n"],"mappings":"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","names":[]}
|
package/dist/turn_detector.d.cts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { InferenceRunner, llm } from '@livekit/agents';
|
|
2
|
-
type RawChatContext = {
|
|
3
|
-
role: string;
|
|
4
|
-
content: string;
|
|
5
|
-
}[];
|
|
6
|
-
export declare class EOURunner extends InferenceRunner {
|
|
7
|
-
#private;
|
|
8
|
-
static INFERENCE_METHOD: string;
|
|
9
|
-
constructor();
|
|
10
|
-
initialize(): Promise<void>;
|
|
11
|
-
run(data: RawChatContext): Promise<number | undefined>;
|
|
12
|
-
close(): Promise<void>;
|
|
13
|
-
}
|
|
14
|
-
export declare class EOUModel {
|
|
15
|
-
#private;
|
|
16
|
-
readonly unlikelyThreshold: number;
|
|
17
|
-
constructor(unlikelyThreshold?: number);
|
|
18
|
-
supportsLanguage(language?: string): boolean;
|
|
19
|
-
predictEndOfTurn(chatCtx: llm.ChatContext): Promise<number>;
|
|
20
|
-
}
|
|
21
|
-
export default EOURunner;
|
|
22
|
-
//# sourceMappingURL=turn_detector.d.ts.map
|
package/dist/turn_detector.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { InferenceRunner, llm } from '@livekit/agents';
|
|
2
|
-
type RawChatContext = {
|
|
3
|
-
role: string;
|
|
4
|
-
content: string;
|
|
5
|
-
}[];
|
|
6
|
-
export declare class EOURunner extends InferenceRunner {
|
|
7
|
-
#private;
|
|
8
|
-
static INFERENCE_METHOD: string;
|
|
9
|
-
constructor();
|
|
10
|
-
initialize(): Promise<void>;
|
|
11
|
-
run(data: RawChatContext): Promise<number | undefined>;
|
|
12
|
-
close(): Promise<void>;
|
|
13
|
-
}
|
|
14
|
-
export declare class EOUModel {
|
|
15
|
-
#private;
|
|
16
|
-
readonly unlikelyThreshold: number;
|
|
17
|
-
constructor(unlikelyThreshold?: number);
|
|
18
|
-
supportsLanguage(language?: string): boolean;
|
|
19
|
-
predictEndOfTurn(chatCtx: llm.ChatContext): Promise<number>;
|
|
20
|
-
}
|
|
21
|
-
export default EOURunner;
|
|
22
|
-
//# sourceMappingURL=turn_detector.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"turn_detector.d.ts","sourceRoot":"","sources":["../src/turn_detector.ts"],"names":[],"mappings":"AAMA,OAAO,EAAqB,eAAe,EAAE,GAAG,EAAO,MAAM,iBAAiB,CAAC;AAM/E,KAAK,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC;AAE1D,qBAAa,SAAU,SAAQ,eAAe;;IAC5C,MAAM,CAAC,gBAAgB,SAAyB;;IAoB1C,UAAU;IAIV,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IA+BtD,KAAK;CAGZ;AAED,qBAAa,QAAQ;;IACnB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAGvB,iBAAiB,SAAO;IAKpC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM;IAM5B,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;CA4BlE;AAED,eAAe,SAAS,CAAC"}
|