@livekit/agents 0.5.1 → 0.6.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/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/index.cjs +2 -0
- package/dist/llm/index.cjs.map +1 -1
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +2 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/llm.cjs +47 -3
- package/dist/llm/llm.cjs.map +1 -1
- package/dist/llm/llm.d.ts +15 -2
- package/dist/llm/llm.d.ts.map +1 -1
- package/dist/llm/llm.js +46 -3
- package/dist/llm/llm.js.map +1 -1
- package/dist/metrics/base.cjs +44 -0
- package/dist/metrics/base.cjs.map +1 -0
- package/dist/metrics/base.d.ts +96 -0
- package/dist/metrics/base.d.ts.map +1 -0
- package/dist/metrics/base.js +20 -0
- package/dist/metrics/base.js.map +1 -0
- package/dist/metrics/index.cjs +35 -0
- package/dist/metrics/index.cjs.map +1 -0
- package/dist/metrics/index.d.ts +5 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +9 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/usage_collector.cjs +53 -0
- package/dist/metrics/usage_collector.cjs.map +1 -0
- package/dist/metrics/usage_collector.d.ts +14 -0
- package/dist/metrics/usage_collector.d.ts.map +1 -0
- package/dist/metrics/usage_collector.js +29 -0
- package/dist/metrics/usage_collector.js.map +1 -0
- package/dist/metrics/utils.cjs +104 -0
- package/dist/metrics/utils.cjs.map +1 -0
- package/dist/metrics/utils.d.ts +10 -0
- package/dist/metrics/utils.d.ts.map +1 -0
- package/dist/metrics/utils.js +73 -0
- package/dist/metrics/utils.js.map +1 -0
- package/dist/multimodal/multimodal_agent.cjs +7 -13
- package/dist/multimodal/multimodal_agent.cjs.map +1 -1
- package/dist/multimodal/multimodal_agent.d.ts +1 -4
- package/dist/multimodal/multimodal_agent.d.ts.map +1 -1
- package/dist/multimodal/multimodal_agent.js +7 -13
- package/dist/multimodal/multimodal_agent.js.map +1 -1
- package/dist/pipeline/agent_output.cjs +9 -2
- package/dist/pipeline/agent_output.cjs.map +1 -1
- package/dist/pipeline/agent_output.d.ts +1 -0
- package/dist/pipeline/agent_output.d.ts.map +1 -1
- package/dist/pipeline/agent_output.js +9 -2
- package/dist/pipeline/agent_output.js.map +1 -1
- package/dist/pipeline/index.cjs +2 -0
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.d.ts +1 -1
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +3 -1
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/pipeline_agent.cjs +168 -70
- package/dist/pipeline/pipeline_agent.cjs.map +1 -1
- package/dist/pipeline/pipeline_agent.d.ts +10 -4
- package/dist/pipeline/pipeline_agent.d.ts.map +1 -1
- package/dist/pipeline/pipeline_agent.js +171 -73
- package/dist/pipeline/pipeline_agent.js.map +1 -1
- package/dist/pipeline/speech_handle.cjs +49 -1
- package/dist/pipeline/speech_handle.cjs.map +1 -1
- package/dist/pipeline/speech_handle.d.ts +12 -2
- package/dist/pipeline/speech_handle.d.ts.map +1 -1
- package/dist/pipeline/speech_handle.js +50 -2
- package/dist/pipeline/speech_handle.js.map +1 -1
- package/dist/stt/index.cjs.map +1 -1
- package/dist/stt/index.d.ts +1 -1
- package/dist/stt/index.d.ts.map +1 -1
- package/dist/stt/index.js.map +1 -1
- package/dist/stt/stream_adapter.cjs +15 -5
- package/dist/stt/stream_adapter.cjs.map +1 -1
- package/dist/stt/stream_adapter.d.ts +4 -1
- package/dist/stt/stream_adapter.d.ts.map +1 -1
- package/dist/stt/stream_adapter.js +15 -5
- package/dist/stt/stream_adapter.js.map +1 -1
- package/dist/stt/stt.cjs +46 -2
- package/dist/stt/stt.cjs.map +1 -1
- package/dist/stt/stt.d.ts +25 -3
- package/dist/stt/stt.d.ts.map +1 -1
- package/dist/stt/stt.js +46 -2
- package/dist/stt/stt.js.map +1 -1
- package/dist/tts/index.cjs +4 -2
- package/dist/tts/index.cjs.map +1 -1
- package/dist/tts/index.d.ts +1 -1
- package/dist/tts/index.d.ts.map +1 -1
- package/dist/tts/index.js +3 -1
- package/dist/tts/index.js.map +1 -1
- package/dist/tts/stream_adapter.cjs +14 -3
- package/dist/tts/stream_adapter.cjs.map +1 -1
- package/dist/tts/stream_adapter.d.ts +3 -0
- package/dist/tts/stream_adapter.d.ts.map +1 -1
- package/dist/tts/stream_adapter.js +15 -4
- package/dist/tts/stream_adapter.js.map +1 -1
- package/dist/tts/tts.cjs +109 -6
- package/dist/tts/tts.cjs.map +1 -1
- package/dist/tts/tts.d.ts +24 -1
- package/dist/tts/tts.d.ts.map +1 -1
- package/dist/tts/tts.js +107 -5
- package/dist/tts/tts.js.map +1 -1
- package/dist/vad.cjs +43 -2
- package/dist/vad.cjs.map +1 -1
- package/dist/vad.d.ts +21 -4
- package/dist/vad.d.ts.map +1 -1
- package/dist/vad.js +43 -2
- package/dist/vad.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -1
- package/src/llm/index.ts +2 -0
- package/src/llm/llm.ts +55 -3
- package/src/metrics/base.ts +127 -0
- package/src/metrics/index.ts +20 -0
- package/src/metrics/usage_collector.ts +40 -0
- package/src/metrics/utils.ts +100 -0
- package/src/multimodal/multimodal_agent.ts +12 -17
- package/src/pipeline/agent_output.ts +14 -7
- package/src/pipeline/index.ts +1 -1
- package/src/pipeline/pipeline_agent.ts +210 -95
- package/src/pipeline/speech_handle.ts +67 -2
- package/src/stt/index.ts +2 -0
- package/src/stt/stream_adapter.ts +17 -5
- package/src/stt/stt.ts +67 -3
- package/src/tts/index.ts +2 -0
- package/src/tts/stream_adapter.ts +17 -4
- package/src/tts/tts.ts +127 -4
- package/src/vad.ts +61 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport type {\n AgentMetrics,\n STTMetrics,\n LLMMetrics,\n TTSMetrics,\n VADMetrics,\n PipelineSTTMetrics,\n PipelineEOUMetrics,\n PipelineLLMMetrics,\n PipelineTTSMetrics,\n PipelineVADMetrics,\n MultimodalLLMMetrics,\n} from './base.js';\nexport { MultimodalLLMError } from './base.js';\nexport { type UsageSummary, UsageCollector } from './usage_collector.js';\nexport { logMetrics } from './utils.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,kBAAmC;AACnC,6BAAkD;AAClD,mBAA2B;","names":[]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { AgentMetrics, STTMetrics, LLMMetrics, TTSMetrics, VADMetrics, PipelineSTTMetrics, PipelineEOUMetrics, PipelineLLMMetrics, PipelineTTSMetrics, PipelineVADMetrics, MultimodalLLMMetrics, } from './base.js';
|
|
2
|
+
export { MultimodalLLMError } from './base.js';
|
|
3
|
+
export { type UsageSummary, UsageCollector } from './usage_collector.js';
|
|
4
|
+
export { logMetrics } from './utils.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,YAAY,EACZ,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport type {\n AgentMetrics,\n STTMetrics,\n LLMMetrics,\n TTSMetrics,\n VADMetrics,\n PipelineSTTMetrics,\n PipelineEOUMetrics,\n PipelineLLMMetrics,\n PipelineTTSMetrics,\n PipelineVADMetrics,\n MultimodalLLMMetrics,\n} from './base.js';\nexport { MultimodalLLMError } from './base.js';\nexport { type UsageSummary, UsageCollector } from './usage_collector.js';\nexport { logMetrics } from './utils.js';\n"],"mappings":"AAiBA,SAAS,0BAA0B;AACnC,SAA4B,sBAAsB;AAClD,SAAS,kBAAkB;","names":[]}
|
|
@@ -0,0 +1,53 @@
|
|
|
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 usage_collector_exports = {};
|
|
20
|
+
__export(usage_collector_exports, {
|
|
21
|
+
UsageCollector: () => UsageCollector
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(usage_collector_exports);
|
|
24
|
+
var import_utils = require("./utils.cjs");
|
|
25
|
+
class UsageCollector {
|
|
26
|
+
#summary;
|
|
27
|
+
constructor() {
|
|
28
|
+
this.#summary = {
|
|
29
|
+
llmPromptTokens: 0,
|
|
30
|
+
llmCompletionTokens: 0,
|
|
31
|
+
ttsCharactersCount: 0,
|
|
32
|
+
sttAudioDuration: 0
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
collect(metrics) {
|
|
36
|
+
if ((0, import_utils.isLLMMetrics)(metrics)) {
|
|
37
|
+
this.#summary.llmPromptTokens += metrics.promptTokens;
|
|
38
|
+
this.#summary.llmCompletionTokens += metrics.completionTokens;
|
|
39
|
+
} else if ((0, import_utils.isTTSMetrics)(metrics)) {
|
|
40
|
+
this.#summary.ttsCharactersCount += metrics.charactersCount;
|
|
41
|
+
} else if ((0, import_utils.isSTTMetrics)(metrics)) {
|
|
42
|
+
this.#summary.sttAudioDuration += metrics.audioDuration;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
get summary() {
|
|
46
|
+
return { ...this.#summary };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
50
|
+
0 && (module.exports = {
|
|
51
|
+
UsageCollector
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=usage_collector.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/usage_collector.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AgentMetrics } from './base.js';\nimport { isLLMMetrics, isSTTMetrics, isTTSMetrics } from './utils.js';\n\nexport interface UsageSummary {\n llmPromptTokens: number;\n llmCompletionTokens: number;\n ttsCharactersCount: number;\n sttAudioDuration: number;\n}\n\nexport class UsageCollector {\n #summary: UsageSummary;\n\n constructor() {\n this.#summary = {\n llmPromptTokens: 0,\n llmCompletionTokens: 0,\n ttsCharactersCount: 0,\n sttAudioDuration: 0,\n };\n }\n\n collect(metrics: AgentMetrics) {\n if (isLLMMetrics(metrics)) {\n this.#summary.llmPromptTokens += metrics.promptTokens;\n this.#summary.llmCompletionTokens += metrics.completionTokens;\n } else if (isTTSMetrics(metrics)) {\n this.#summary.ttsCharactersCount += metrics.charactersCount;\n } else if (isSTTMetrics(metrics)) {\n this.#summary.sttAudioDuration += metrics.audioDuration;\n }\n }\n\n get summary(): UsageSummary {\n return { ...this.#summary };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,mBAAyD;AASlD,MAAM,eAAe;AAAA,EAC1B;AAAA,EAEA,cAAc;AACZ,SAAK,WAAW;AAAA,MACd,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,MACrB,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,QAAQ,SAAuB;AAC7B,YAAI,2BAAa,OAAO,GAAG;AACzB,WAAK,SAAS,mBAAmB,QAAQ;AACzC,WAAK,SAAS,uBAAuB,QAAQ;AAAA,IAC/C,eAAW,2BAAa,OAAO,GAAG;AAChC,WAAK,SAAS,sBAAsB,QAAQ;AAAA,IAC9C,eAAW,2BAAa,OAAO,GAAG;AAChC,WAAK,SAAS,oBAAoB,QAAQ;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,IAAI,UAAwB;AAC1B,WAAO,EAAE,GAAG,KAAK,SAAS;AAAA,EAC5B;AACF;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentMetrics } from './base.js';
|
|
2
|
+
export interface UsageSummary {
|
|
3
|
+
llmPromptTokens: number;
|
|
4
|
+
llmCompletionTokens: number;
|
|
5
|
+
ttsCharactersCount: number;
|
|
6
|
+
sttAudioDuration: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class UsageCollector {
|
|
9
|
+
#private;
|
|
10
|
+
constructor();
|
|
11
|
+
collect(metrics: AgentMetrics): void;
|
|
12
|
+
get summary(): UsageSummary;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=usage_collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage_collector.d.ts","sourceRoot":"","sources":["../../src/metrics/usage_collector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,cAAc;;;IAYzB,OAAO,CAAC,OAAO,EAAE,YAAY;IAW7B,IAAI,OAAO,IAAI,YAAY,CAE1B;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isLLMMetrics, isSTTMetrics, isTTSMetrics } from "./utils.js";
|
|
2
|
+
class UsageCollector {
|
|
3
|
+
#summary;
|
|
4
|
+
constructor() {
|
|
5
|
+
this.#summary = {
|
|
6
|
+
llmPromptTokens: 0,
|
|
7
|
+
llmCompletionTokens: 0,
|
|
8
|
+
ttsCharactersCount: 0,
|
|
9
|
+
sttAudioDuration: 0
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
collect(metrics) {
|
|
13
|
+
if (isLLMMetrics(metrics)) {
|
|
14
|
+
this.#summary.llmPromptTokens += metrics.promptTokens;
|
|
15
|
+
this.#summary.llmCompletionTokens += metrics.completionTokens;
|
|
16
|
+
} else if (isTTSMetrics(metrics)) {
|
|
17
|
+
this.#summary.ttsCharactersCount += metrics.charactersCount;
|
|
18
|
+
} else if (isSTTMetrics(metrics)) {
|
|
19
|
+
this.#summary.sttAudioDuration += metrics.audioDuration;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
get summary() {
|
|
23
|
+
return { ...this.#summary };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
UsageCollector
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=usage_collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/usage_collector.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AgentMetrics } from './base.js';\nimport { isLLMMetrics, isSTTMetrics, isTTSMetrics } from './utils.js';\n\nexport interface UsageSummary {\n llmPromptTokens: number;\n llmCompletionTokens: number;\n ttsCharactersCount: number;\n sttAudioDuration: number;\n}\n\nexport class UsageCollector {\n #summary: UsageSummary;\n\n constructor() {\n this.#summary = {\n llmPromptTokens: 0,\n llmCompletionTokens: 0,\n ttsCharactersCount: 0,\n sttAudioDuration: 0,\n };\n }\n\n collect(metrics: AgentMetrics) {\n if (isLLMMetrics(metrics)) {\n this.#summary.llmPromptTokens += metrics.promptTokens;\n this.#summary.llmCompletionTokens += metrics.completionTokens;\n } else if (isTTSMetrics(metrics)) {\n this.#summary.ttsCharactersCount += metrics.charactersCount;\n } else if (isSTTMetrics(metrics)) {\n this.#summary.sttAudioDuration += metrics.audioDuration;\n }\n }\n\n get summary(): UsageSummary {\n return { ...this.#summary };\n }\n}\n"],"mappings":"AAIA,SAAS,cAAc,cAAc,oBAAoB;AASlD,MAAM,eAAe;AAAA,EAC1B;AAAA,EAEA,cAAc;AACZ,SAAK,WAAW;AAAA,MACd,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,MACrB,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,QAAQ,SAAuB;AAC7B,QAAI,aAAa,OAAO,GAAG;AACzB,WAAK,SAAS,mBAAmB,QAAQ;AACzC,WAAK,SAAS,uBAAuB,QAAQ;AAAA,IAC/C,WAAW,aAAa,OAAO,GAAG;AAChC,WAAK,SAAS,sBAAsB,QAAQ;AAAA,IAC9C,WAAW,aAAa,OAAO,GAAG;AAChC,WAAK,SAAS,oBAAoB,QAAQ;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,IAAI,UAAwB;AAC1B,WAAO,EAAE,GAAG,KAAK,SAAS;AAAA,EAC5B;AACF;","names":[]}
|
|
@@ -0,0 +1,104 @@
|
|
|
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 utils_exports = {};
|
|
20
|
+
__export(utils_exports, {
|
|
21
|
+
isLLMMetrics: () => isLLMMetrics,
|
|
22
|
+
isPipelineEOUMetrics: () => isPipelineEOUMetrics,
|
|
23
|
+
isPipelineLLMMetrics: () => isPipelineLLMMetrics,
|
|
24
|
+
isPipelineTTSMetrics: () => isPipelineTTSMetrics,
|
|
25
|
+
isSTTMetrics: () => isSTTMetrics,
|
|
26
|
+
isTTSMetrics: () => isTTSMetrics,
|
|
27
|
+
isVADMetrics: () => isVADMetrics,
|
|
28
|
+
logMetrics: () => logMetrics
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(utils_exports);
|
|
31
|
+
var import_log = require("../log.cjs");
|
|
32
|
+
const logMetrics = (metrics) => {
|
|
33
|
+
const logger = (0, import_log.log)();
|
|
34
|
+
if (isPipelineLLMMetrics(metrics)) {
|
|
35
|
+
logger.child({
|
|
36
|
+
sequenceId: metrics.sequenceId,
|
|
37
|
+
ttft: metrics.ttft,
|
|
38
|
+
inputTokens: metrics.promptTokens,
|
|
39
|
+
outputTokens: metrics.completionTokens,
|
|
40
|
+
tokensPerSecond: metrics.tokensPerSecond
|
|
41
|
+
}).info("Pipeline LLM metrics");
|
|
42
|
+
} else if (isLLMMetrics(metrics)) {
|
|
43
|
+
logger.child({
|
|
44
|
+
ttft: metrics.ttft,
|
|
45
|
+
inputTokens: metrics.promptTokens,
|
|
46
|
+
outputTokens: metrics.completionTokens,
|
|
47
|
+
tokensPerSecond: metrics.tokensPerSecond
|
|
48
|
+
}).info("LLM metrics");
|
|
49
|
+
} else if (isPipelineTTSMetrics(metrics)) {
|
|
50
|
+
logger.child({
|
|
51
|
+
sequenceId: metrics.sequenceId,
|
|
52
|
+
ttfb: metrics.ttfb,
|
|
53
|
+
audioDuration: metrics.audioDuration
|
|
54
|
+
}).info("Pipeline TTS metrics");
|
|
55
|
+
} else if (isTTSMetrics(metrics)) {
|
|
56
|
+
logger.child({
|
|
57
|
+
ttfb: metrics.ttfb,
|
|
58
|
+
audioDuration: metrics.audioDuration
|
|
59
|
+
}).info("TTS metrics");
|
|
60
|
+
} else if (isPipelineEOUMetrics(metrics)) {
|
|
61
|
+
logger.child({
|
|
62
|
+
sequenceId: metrics.sequenceId,
|
|
63
|
+
endOfUtteranceDelay: metrics.endOfUtteranceDelay,
|
|
64
|
+
transcriptionDelay: metrics.transcriptionDelay
|
|
65
|
+
}).info("Pipeline EOU metrics");
|
|
66
|
+
} else if (isSTTMetrics(metrics)) {
|
|
67
|
+
logger.child({
|
|
68
|
+
audioDuration: metrics.audioDuration
|
|
69
|
+
}).info("STT metrics");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const isLLMMetrics = (metrics) => {
|
|
73
|
+
return !!metrics.ttft;
|
|
74
|
+
};
|
|
75
|
+
const isPipelineLLMMetrics = (metrics) => {
|
|
76
|
+
return isLLMMetrics(metrics) && !!metrics.sequenceId;
|
|
77
|
+
};
|
|
78
|
+
const isVADMetrics = (metrics) => {
|
|
79
|
+
return !!metrics.inferenceCount;
|
|
80
|
+
};
|
|
81
|
+
const isPipelineEOUMetrics = (metrics) => {
|
|
82
|
+
return !!metrics.endOfUtteranceDelay;
|
|
83
|
+
};
|
|
84
|
+
const isTTSMetrics = (metrics) => {
|
|
85
|
+
return !!metrics.ttfb;
|
|
86
|
+
};
|
|
87
|
+
const isPipelineTTSMetrics = (metrics) => {
|
|
88
|
+
return isTTSMetrics(metrics) && !!metrics.sequenceId;
|
|
89
|
+
};
|
|
90
|
+
const isSTTMetrics = (metrics) => {
|
|
91
|
+
return !(isLLMMetrics(metrics) || isVADMetrics(metrics) || isPipelineEOUMetrics(metrics) || isTTSMetrics(metrics));
|
|
92
|
+
};
|
|
93
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
94
|
+
0 && (module.exports = {
|
|
95
|
+
isLLMMetrics,
|
|
96
|
+
isPipelineEOUMetrics,
|
|
97
|
+
isPipelineLLMMetrics,
|
|
98
|
+
isPipelineTTSMetrics,
|
|
99
|
+
isSTTMetrics,
|
|
100
|
+
isTTSMetrics,
|
|
101
|
+
isVADMetrics,
|
|
102
|
+
logMetrics
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log } from '../log.js';\nimport type {\n AgentMetrics,\n LLMMetrics,\n PipelineEOUMetrics,\n PipelineLLMMetrics,\n PipelineTTSMetrics,\n STTMetrics,\n TTSMetrics,\n VADMetrics,\n} from './base.js';\n\nexport const logMetrics = (metrics: AgentMetrics) => {\n const logger = log();\n if (isPipelineLLMMetrics(metrics)) {\n logger\n .child({\n sequenceId: metrics.sequenceId,\n ttft: metrics.ttft,\n inputTokens: metrics.promptTokens,\n outputTokens: metrics.completionTokens,\n tokensPerSecond: metrics.tokensPerSecond,\n })\n .info('Pipeline LLM metrics');\n } else if (isLLMMetrics(metrics)) {\n logger\n .child({\n ttft: metrics.ttft,\n inputTokens: metrics.promptTokens,\n outputTokens: metrics.completionTokens,\n tokensPerSecond: metrics.tokensPerSecond,\n })\n .info('LLM metrics');\n } else if (isPipelineTTSMetrics(metrics)) {\n logger\n .child({\n sequenceId: metrics.sequenceId,\n ttfb: metrics.ttfb,\n audioDuration: metrics.audioDuration,\n })\n .info('Pipeline TTS metrics');\n } else if (isTTSMetrics(metrics)) {\n logger\n .child({\n ttfb: metrics.ttfb,\n audioDuration: metrics.audioDuration,\n })\n .info('TTS metrics');\n } else if (isPipelineEOUMetrics(metrics)) {\n logger\n .child({\n sequenceId: metrics.sequenceId,\n endOfUtteranceDelay: metrics.endOfUtteranceDelay,\n transcriptionDelay: metrics.transcriptionDelay,\n })\n .info('Pipeline EOU metrics');\n } else if (isSTTMetrics(metrics)) {\n logger\n .child({\n audioDuration: metrics.audioDuration,\n })\n .info('STT metrics');\n }\n};\n\nexport const isLLMMetrics = (metrics: AgentMetrics): metrics is LLMMetrics => {\n return !!(metrics as LLMMetrics).ttft;\n};\n\nexport const isPipelineLLMMetrics = (metrics: AgentMetrics): metrics is PipelineLLMMetrics => {\n return isLLMMetrics(metrics) && !!(metrics as PipelineLLMMetrics).sequenceId;\n};\n\nexport const isVADMetrics = (metrics: AgentMetrics): metrics is VADMetrics => {\n return !!(metrics as VADMetrics).inferenceCount;\n};\n\nexport const isPipelineEOUMetrics = (metrics: AgentMetrics): metrics is PipelineEOUMetrics => {\n return !!(metrics as PipelineEOUMetrics).endOfUtteranceDelay;\n};\n\nexport const isTTSMetrics = (metrics: AgentMetrics): metrics is TTSMetrics => {\n return !!(metrics as TTSMetrics).ttfb;\n};\n\nexport const isPipelineTTSMetrics = (metrics: AgentMetrics): metrics is PipelineTTSMetrics => {\n return isTTSMetrics(metrics) && !!(metrics as PipelineTTSMetrics).sequenceId;\n};\n\nexport const isSTTMetrics = (metrics: AgentMetrics): metrics is STTMetrics => {\n return !(\n isLLMMetrics(metrics) ||\n isVADMetrics(metrics) ||\n isPipelineEOUMetrics(metrics) ||\n isTTSMetrics(metrics)\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAoB;AAYb,MAAM,aAAa,CAAC,YAA0B;AACnD,QAAM,aAAS,gBAAI;AACnB,MAAI,qBAAqB,OAAO,GAAG;AACjC,WACG,MAAM;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,IAC3B,CAAC,EACA,KAAK,sBAAsB;AAAA,EAChC,WAAW,aAAa,OAAO,GAAG;AAChC,WACG,MAAM;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,IAC3B,CAAC,EACA,KAAK,aAAa;AAAA,EACvB,WAAW,qBAAqB,OAAO,GAAG;AACxC,WACG,MAAM;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,eAAe,QAAQ;AAAA,IACzB,CAAC,EACA,KAAK,sBAAsB;AAAA,EAChC,WAAW,aAAa,OAAO,GAAG;AAChC,WACG,MAAM;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,eAAe,QAAQ;AAAA,IACzB,CAAC,EACA,KAAK,aAAa;AAAA,EACvB,WAAW,qBAAqB,OAAO,GAAG;AACxC,WACG,MAAM;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,qBAAqB,QAAQ;AAAA,MAC7B,oBAAoB,QAAQ;AAAA,IAC9B,CAAC,EACA,KAAK,sBAAsB;AAAA,EAChC,WAAW,aAAa,OAAO,GAAG;AAChC,WACG,MAAM;AAAA,MACL,eAAe,QAAQ;AAAA,IACzB,CAAC,EACA,KAAK,aAAa;AAAA,EACvB;AACF;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,CAAC,CAAE,QAAuB;AACnC;AAEO,MAAM,uBAAuB,CAAC,YAAyD;AAC5F,SAAO,aAAa,OAAO,KAAK,CAAC,CAAE,QAA+B;AACpE;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,CAAC,CAAE,QAAuB;AACnC;AAEO,MAAM,uBAAuB,CAAC,YAAyD;AAC5F,SAAO,CAAC,CAAE,QAA+B;AAC3C;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,CAAC,CAAE,QAAuB;AACnC;AAEO,MAAM,uBAAuB,CAAC,YAAyD;AAC5F,SAAO,aAAa,OAAO,KAAK,CAAC,CAAE,QAA+B;AACpE;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,EACL,aAAa,OAAO,KACpB,aAAa,OAAO,KACpB,qBAAqB,OAAO,KAC5B,aAAa,OAAO;AAExB;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AgentMetrics, LLMMetrics, PipelineEOUMetrics, PipelineLLMMetrics, PipelineTTSMetrics, STTMetrics, TTSMetrics, VADMetrics } from './base.js';
|
|
2
|
+
export declare const logMetrics: (metrics: AgentMetrics) => void;
|
|
3
|
+
export declare const isLLMMetrics: (metrics: AgentMetrics) => metrics is LLMMetrics;
|
|
4
|
+
export declare const isPipelineLLMMetrics: (metrics: AgentMetrics) => metrics is PipelineLLMMetrics;
|
|
5
|
+
export declare const isVADMetrics: (metrics: AgentMetrics) => metrics is VADMetrics;
|
|
6
|
+
export declare const isPipelineEOUMetrics: (metrics: AgentMetrics) => metrics is PipelineEOUMetrics;
|
|
7
|
+
export declare const isTTSMetrics: (metrics: AgentMetrics) => metrics is TTSMetrics;
|
|
8
|
+
export declare const isPipelineTTSMetrics: (metrics: AgentMetrics) => metrics is PipelineTTSMetrics;
|
|
9
|
+
export declare const isSTTMetrics: (metrics: AgentMetrics) => metrics is STTMetrics;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/metrics/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,UAAU,EACX,MAAM,WAAW,CAAC;AAEnB,eAAO,MAAM,UAAU,YAAa,YAAY,SAmD/C,CAAC;AAEF,eAAO,MAAM,YAAY,YAAa,YAAY,0BAEjD,CAAC;AAEF,eAAO,MAAM,oBAAoB,YAAa,YAAY,kCAEzD,CAAC;AAEF,eAAO,MAAM,YAAY,YAAa,YAAY,0BAEjD,CAAC;AAEF,eAAO,MAAM,oBAAoB,YAAa,YAAY,kCAEzD,CAAC;AAEF,eAAO,MAAM,YAAY,YAAa,YAAY,0BAEjD,CAAC;AAEF,eAAO,MAAM,oBAAoB,YAAa,YAAY,kCAEzD,CAAC;AAEF,eAAO,MAAM,YAAY,YAAa,YAAY,0BAOjD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { log } from "../log.js";
|
|
2
|
+
const logMetrics = (metrics) => {
|
|
3
|
+
const logger = log();
|
|
4
|
+
if (isPipelineLLMMetrics(metrics)) {
|
|
5
|
+
logger.child({
|
|
6
|
+
sequenceId: metrics.sequenceId,
|
|
7
|
+
ttft: metrics.ttft,
|
|
8
|
+
inputTokens: metrics.promptTokens,
|
|
9
|
+
outputTokens: metrics.completionTokens,
|
|
10
|
+
tokensPerSecond: metrics.tokensPerSecond
|
|
11
|
+
}).info("Pipeline LLM metrics");
|
|
12
|
+
} else if (isLLMMetrics(metrics)) {
|
|
13
|
+
logger.child({
|
|
14
|
+
ttft: metrics.ttft,
|
|
15
|
+
inputTokens: metrics.promptTokens,
|
|
16
|
+
outputTokens: metrics.completionTokens,
|
|
17
|
+
tokensPerSecond: metrics.tokensPerSecond
|
|
18
|
+
}).info("LLM metrics");
|
|
19
|
+
} else if (isPipelineTTSMetrics(metrics)) {
|
|
20
|
+
logger.child({
|
|
21
|
+
sequenceId: metrics.sequenceId,
|
|
22
|
+
ttfb: metrics.ttfb,
|
|
23
|
+
audioDuration: metrics.audioDuration
|
|
24
|
+
}).info("Pipeline TTS metrics");
|
|
25
|
+
} else if (isTTSMetrics(metrics)) {
|
|
26
|
+
logger.child({
|
|
27
|
+
ttfb: metrics.ttfb,
|
|
28
|
+
audioDuration: metrics.audioDuration
|
|
29
|
+
}).info("TTS metrics");
|
|
30
|
+
} else if (isPipelineEOUMetrics(metrics)) {
|
|
31
|
+
logger.child({
|
|
32
|
+
sequenceId: metrics.sequenceId,
|
|
33
|
+
endOfUtteranceDelay: metrics.endOfUtteranceDelay,
|
|
34
|
+
transcriptionDelay: metrics.transcriptionDelay
|
|
35
|
+
}).info("Pipeline EOU metrics");
|
|
36
|
+
} else if (isSTTMetrics(metrics)) {
|
|
37
|
+
logger.child({
|
|
38
|
+
audioDuration: metrics.audioDuration
|
|
39
|
+
}).info("STT metrics");
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const isLLMMetrics = (metrics) => {
|
|
43
|
+
return !!metrics.ttft;
|
|
44
|
+
};
|
|
45
|
+
const isPipelineLLMMetrics = (metrics) => {
|
|
46
|
+
return isLLMMetrics(metrics) && !!metrics.sequenceId;
|
|
47
|
+
};
|
|
48
|
+
const isVADMetrics = (metrics) => {
|
|
49
|
+
return !!metrics.inferenceCount;
|
|
50
|
+
};
|
|
51
|
+
const isPipelineEOUMetrics = (metrics) => {
|
|
52
|
+
return !!metrics.endOfUtteranceDelay;
|
|
53
|
+
};
|
|
54
|
+
const isTTSMetrics = (metrics) => {
|
|
55
|
+
return !!metrics.ttfb;
|
|
56
|
+
};
|
|
57
|
+
const isPipelineTTSMetrics = (metrics) => {
|
|
58
|
+
return isTTSMetrics(metrics) && !!metrics.sequenceId;
|
|
59
|
+
};
|
|
60
|
+
const isSTTMetrics = (metrics) => {
|
|
61
|
+
return !(isLLMMetrics(metrics) || isVADMetrics(metrics) || isPipelineEOUMetrics(metrics) || isTTSMetrics(metrics));
|
|
62
|
+
};
|
|
63
|
+
export {
|
|
64
|
+
isLLMMetrics,
|
|
65
|
+
isPipelineEOUMetrics,
|
|
66
|
+
isPipelineLLMMetrics,
|
|
67
|
+
isPipelineTTSMetrics,
|
|
68
|
+
isSTTMetrics,
|
|
69
|
+
isTTSMetrics,
|
|
70
|
+
isVADMetrics,
|
|
71
|
+
logMetrics
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log } from '../log.js';\nimport type {\n AgentMetrics,\n LLMMetrics,\n PipelineEOUMetrics,\n PipelineLLMMetrics,\n PipelineTTSMetrics,\n STTMetrics,\n TTSMetrics,\n VADMetrics,\n} from './base.js';\n\nexport const logMetrics = (metrics: AgentMetrics) => {\n const logger = log();\n if (isPipelineLLMMetrics(metrics)) {\n logger\n .child({\n sequenceId: metrics.sequenceId,\n ttft: metrics.ttft,\n inputTokens: metrics.promptTokens,\n outputTokens: metrics.completionTokens,\n tokensPerSecond: metrics.tokensPerSecond,\n })\n .info('Pipeline LLM metrics');\n } else if (isLLMMetrics(metrics)) {\n logger\n .child({\n ttft: metrics.ttft,\n inputTokens: metrics.promptTokens,\n outputTokens: metrics.completionTokens,\n tokensPerSecond: metrics.tokensPerSecond,\n })\n .info('LLM metrics');\n } else if (isPipelineTTSMetrics(metrics)) {\n logger\n .child({\n sequenceId: metrics.sequenceId,\n ttfb: metrics.ttfb,\n audioDuration: metrics.audioDuration,\n })\n .info('Pipeline TTS metrics');\n } else if (isTTSMetrics(metrics)) {\n logger\n .child({\n ttfb: metrics.ttfb,\n audioDuration: metrics.audioDuration,\n })\n .info('TTS metrics');\n } else if (isPipelineEOUMetrics(metrics)) {\n logger\n .child({\n sequenceId: metrics.sequenceId,\n endOfUtteranceDelay: metrics.endOfUtteranceDelay,\n transcriptionDelay: metrics.transcriptionDelay,\n })\n .info('Pipeline EOU metrics');\n } else if (isSTTMetrics(metrics)) {\n logger\n .child({\n audioDuration: metrics.audioDuration,\n })\n .info('STT metrics');\n }\n};\n\nexport const isLLMMetrics = (metrics: AgentMetrics): metrics is LLMMetrics => {\n return !!(metrics as LLMMetrics).ttft;\n};\n\nexport const isPipelineLLMMetrics = (metrics: AgentMetrics): metrics is PipelineLLMMetrics => {\n return isLLMMetrics(metrics) && !!(metrics as PipelineLLMMetrics).sequenceId;\n};\n\nexport const isVADMetrics = (metrics: AgentMetrics): metrics is VADMetrics => {\n return !!(metrics as VADMetrics).inferenceCount;\n};\n\nexport const isPipelineEOUMetrics = (metrics: AgentMetrics): metrics is PipelineEOUMetrics => {\n return !!(metrics as PipelineEOUMetrics).endOfUtteranceDelay;\n};\n\nexport const isTTSMetrics = (metrics: AgentMetrics): metrics is TTSMetrics => {\n return !!(metrics as TTSMetrics).ttfb;\n};\n\nexport const isPipelineTTSMetrics = (metrics: AgentMetrics): metrics is PipelineTTSMetrics => {\n return isTTSMetrics(metrics) && !!(metrics as PipelineTTSMetrics).sequenceId;\n};\n\nexport const isSTTMetrics = (metrics: AgentMetrics): metrics is STTMetrics => {\n return !(\n isLLMMetrics(metrics) ||\n isVADMetrics(metrics) ||\n isPipelineEOUMetrics(metrics) ||\n isTTSMetrics(metrics)\n );\n};\n"],"mappings":"AAGA,SAAS,WAAW;AAYb,MAAM,aAAa,CAAC,YAA0B;AACnD,QAAM,SAAS,IAAI;AACnB,MAAI,qBAAqB,OAAO,GAAG;AACjC,WACG,MAAM;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,IAC3B,CAAC,EACA,KAAK,sBAAsB;AAAA,EAChC,WAAW,aAAa,OAAO,GAAG;AAChC,WACG,MAAM;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,IAC3B,CAAC,EACA,KAAK,aAAa;AAAA,EACvB,WAAW,qBAAqB,OAAO,GAAG;AACxC,WACG,MAAM;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,eAAe,QAAQ;AAAA,IACzB,CAAC,EACA,KAAK,sBAAsB;AAAA,EAChC,WAAW,aAAa,OAAO,GAAG;AAChC,WACG,MAAM;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,eAAe,QAAQ;AAAA,IACzB,CAAC,EACA,KAAK,aAAa;AAAA,EACvB,WAAW,qBAAqB,OAAO,GAAG;AACxC,WACG,MAAM;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,qBAAqB,QAAQ;AAAA,MAC7B,oBAAoB,QAAQ;AAAA,IAC9B,CAAC,EACA,KAAK,sBAAsB;AAAA,EAChC,WAAW,aAAa,OAAO,GAAG;AAChC,WACG,MAAM;AAAA,MACL,eAAe,QAAQ;AAAA,IACzB,CAAC,EACA,KAAK,aAAa;AAAA,EACvB;AACF;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,CAAC,CAAE,QAAuB;AACnC;AAEO,MAAM,uBAAuB,CAAC,YAAyD;AAC5F,SAAO,aAAa,OAAO,KAAK,CAAC,CAAE,QAA+B;AACpE;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,CAAC,CAAE,QAAuB;AACnC;AAEO,MAAM,uBAAuB,CAAC,YAAyD;AAC5F,SAAO,CAAC,CAAE,QAA+B;AAC3C;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,CAAC,CAAE,QAAuB;AACnC;AAEO,MAAM,uBAAuB,CAAC,YAAyD;AAC5F,SAAO,aAAa,OAAO,KAAK,CAAC,CAAE,QAA+B;AACpE;AAEO,MAAM,eAAe,CAAC,YAAiD;AAC5E,SAAO,EACL,aAAa,OAAO,KACpB,aAAa,OAAO,KACpB,qBAAqB,OAAO,KAC5B,aAAa,OAAO;AAExB;","names":[]}
|
|
@@ -234,6 +234,7 @@ class MultimodalAgent extends import_node_events.EventEmitter {
|
|
|
234
234
|
});
|
|
235
235
|
this.#session.on("input_speech_started", (ev) => {
|
|
236
236
|
var _a2, _b;
|
|
237
|
+
this.emit("user_started_speaking");
|
|
237
238
|
if (this.#playingHandle && !this.#playingHandle.done) {
|
|
238
239
|
this.#playingHandle.interrupt();
|
|
239
240
|
this.#session.conversation.item.truncate(
|
|
@@ -264,6 +265,9 @@ class MultimodalAgent extends import_node_events.EventEmitter {
|
|
|
264
265
|
this.#pendingFunctionCalls.delete(ev.callId);
|
|
265
266
|
this.#updateState();
|
|
266
267
|
});
|
|
268
|
+
this.#session.on("metrics_collected", (metrics) => {
|
|
269
|
+
this.emit("metrics_collected", metrics);
|
|
270
|
+
});
|
|
267
271
|
resolve(this.#session);
|
|
268
272
|
});
|
|
269
273
|
}
|
|
@@ -325,19 +329,9 @@ class MultimodalAgent extends import_node_events.EventEmitter {
|
|
|
325
329
|
}
|
|
326
330
|
};
|
|
327
331
|
this.subscribedTrack = track;
|
|
328
|
-
|
|
329
|
-
this.
|
|
330
|
-
}
|
|
331
|
-
let cancel;
|
|
332
|
-
this.readMicroTask = {
|
|
333
|
-
promise: new Promise((resolve, reject) => {
|
|
334
|
-
cancel = () => {
|
|
335
|
-
reject(new Error("Task cancelled"));
|
|
336
|
-
};
|
|
337
|
-
readAudioStreamTask(new import_rtc_node.AudioStream(track, this.model.sampleRate, this.model.numChannels)).then(resolve).catch(reject);
|
|
338
|
-
}),
|
|
339
|
-
cancel: () => cancel()
|
|
340
|
-
};
|
|
332
|
+
this.readMicroTask = new Promise((resolve, reject) => {
|
|
333
|
+
readAudioStreamTask(new import_rtc_node.AudioStream(track, this.model.sampleRate, this.model.numChannels)).then(resolve).catch(reject);
|
|
334
|
+
});
|
|
341
335
|
}
|
|
342
336
|
#getLocalTrackSid() {
|
|
343
337
|
var _a;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/multimodal/multimodal_agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type {\n LocalTrackPublication,\n RemoteAudioTrack,\n RemoteParticipant,\n RemoteTrack,\n RemoteTrackPublication,\n Room,\n} from '@livekit/rtc-node';\nimport {\n AudioSource,\n AudioStream,\n LocalAudioTrack,\n RoomEvent,\n TrackPublishOptions,\n TrackSource,\n} from '@livekit/rtc-node';\nimport { EventEmitter } from 'node:events';\nimport { AudioByteStream } from '../audio.js';\nimport * as llm from '../llm/index.js';\nimport { log } from '../log.js';\nimport { BasicTranscriptionForwarder } from '../transcription.js';\nimport { findMicroTrackId } from '../utils.js';\nimport { AgentPlayout, type PlayoutHandle } from './agent_playout.js';\n\n/**\n * @internal\n * @beta\n */\nexport abstract class RealtimeSession extends EventEmitter {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract conversation: any; // openai.realtime.Conversation\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract inputAudioBuffer: any; // openai.realtime.InputAudioBuffer\n abstract fncCtx: llm.FunctionContext | undefined;\n}\n\n/**\n * @internal\n * @beta\n */\nexport abstract class RealtimeModel {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract session(options: any): RealtimeSession; // openai.realtime.ModelOptions\n abstract close(): Promise<void>;\n abstract sampleRate: number;\n abstract numChannels: number;\n abstract inFrameSize: number;\n abstract outFrameSize: number;\n}\n\nexport type AgentState = 'initializing' | 'thinking' | 'listening' | 'speaking';\nexport const AGENT_STATE_ATTRIBUTE = 'lk.agent.state';\n\n/** @beta */\nexport class MultimodalAgent extends EventEmitter {\n model: RealtimeModel;\n room: Room | null = null;\n linkedParticipant: RemoteParticipant | null = null;\n subscribedTrack: RemoteAudioTrack | null = null;\n readMicroTask: { promise: Promise<void>; cancel: () => void } | null = null;\n\n constructor({\n model,\n chatCtx,\n fncCtx,\n }: {\n model: RealtimeModel;\n chatCtx?: llm.ChatContext;\n fncCtx?: llm.FunctionContext;\n }) {\n super();\n this.model = model;\n this.#chatCtx = chatCtx;\n this.#fncCtx = fncCtx;\n }\n\n #participant: RemoteParticipant | string | null = null;\n #agentPublication: LocalTrackPublication | null = null;\n #localTrackSid: string | null = null;\n #localSource: AudioSource | null = null;\n #agentPlayout: AgentPlayout | null = null;\n #playingHandle: PlayoutHandle | undefined = undefined;\n #logger = log();\n #session: RealtimeSession | null = null;\n #fncCtx: llm.FunctionContext | undefined = undefined;\n #chatCtx: llm.ChatContext | undefined = undefined;\n\n #_started: boolean = false;\n #_pendingFunctionCalls: Set<string> = new Set();\n #_speaking: boolean = false;\n\n get fncCtx(): llm.FunctionContext | undefined {\n return this.#fncCtx;\n }\n\n set fncCtx(ctx: llm.FunctionContext | undefined) {\n this.#fncCtx = ctx;\n if (this.#session) {\n this.#session.fncCtx = ctx;\n }\n }\n\n get #pendingFunctionCalls(): Set<string> {\n return this.#_pendingFunctionCalls;\n }\n\n set #pendingFunctionCalls(calls: Set<string>) {\n this.#_pendingFunctionCalls = calls;\n this.#updateState();\n }\n\n get #speaking(): boolean {\n return this.#_speaking;\n }\n\n set #speaking(isSpeaking: boolean) {\n this.#_speaking = isSpeaking;\n this.#updateState();\n }\n\n get #started(): boolean {\n return this.#_started;\n }\n\n set #started(started: boolean) {\n this.#_started = started;\n this.#updateState();\n }\n\n start(\n room: Room,\n participant: RemoteParticipant | string | null = null,\n ): Promise<RealtimeSession> {\n return new Promise(async (resolve, reject) => {\n if (this.#started) {\n reject(new Error('MultimodalAgent already started'));\n }\n this.#updateState();\n\n room.on(RoomEvent.ParticipantConnected, (participant: RemoteParticipant) => {\n // automatically link to the first participant that connects, if not already linked\n if (this.linkedParticipant) {\n return;\n }\n this.#linkParticipant(participant.identity);\n });\n room.on(\n RoomEvent.TrackPublished,\n (trackPublication: RemoteTrackPublication, participant: RemoteParticipant) => {\n if (\n this.linkedParticipant &&\n participant.identity === this.linkedParticipant.identity &&\n trackPublication.source === TrackSource.SOURCE_MICROPHONE &&\n !trackPublication.subscribed\n ) {\n trackPublication.setSubscribed(true);\n }\n },\n );\n room.on(RoomEvent.TrackSubscribed, this.#handleTrackSubscription.bind(this));\n\n this.room = room;\n this.#participant = participant;\n\n this.#localSource = new AudioSource(this.model.sampleRate, this.model.numChannels);\n this.#agentPlayout = new AgentPlayout(\n this.#localSource,\n this.model.sampleRate,\n this.model.numChannels,\n this.model.inFrameSize,\n this.model.outFrameSize,\n );\n const onPlayoutStarted = () => {\n this.emit('agent_started_speaking');\n this.#speaking = true;\n };\n\n const onPlayoutStopped = (interrupted: boolean) => {\n this.emit('agent_stopped_speaking');\n this.#speaking = false;\n if (this.#playingHandle) {\n let text = this.#playingHandle.transcriptionFwd.text;\n if (interrupted) {\n text += '…';\n }\n const msg = llm.ChatMessage.create({\n role: llm.ChatRole.ASSISTANT,\n text,\n });\n\n if (interrupted) {\n this.emit('agent_speech_interrupted', msg);\n } else {\n this.emit('agent_speech_committed', msg);\n }\n this.#logger.child({ transcription: text, interrupted }).debug('committed agent speech');\n }\n };\n\n this.#agentPlayout.on('playout_started', onPlayoutStarted);\n this.#agentPlayout.on('playout_stopped', onPlayoutStopped);\n\n const track = LocalAudioTrack.createAudioTrack('assistant_voice', this.#localSource);\n const options = new TrackPublishOptions();\n options.source = TrackSource.SOURCE_MICROPHONE;\n this.#agentPublication = (await room.localParticipant?.publishTrack(track, options)) || null;\n if (!this.#agentPublication) {\n this.#logger.error('Failed to publish track');\n reject(new Error('Failed to publish track'));\n return;\n }\n\n await this.#agentPublication.waitForSubscription();\n\n if (participant) {\n if (typeof participant === 'string') {\n this.#linkParticipant(participant);\n } else {\n this.#linkParticipant(participant.identity);\n }\n } else {\n // No participant specified, try to find the first participant in the room\n for (const participant of room.remoteParticipants.values()) {\n this.#linkParticipant(participant.identity);\n break;\n }\n }\n\n this.#session = this.model.session({ fncCtx: this.#fncCtx, chatCtx: this.#chatCtx });\n this.#started = true;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('response_content_added', (message: any) => {\n // openai.realtime.RealtimeContent\n const trFwd = new BasicTranscriptionForwarder(\n this.room!,\n this.room!.localParticipant!.identity,\n this.#getLocalTrackSid()!,\n message.responseId,\n );\n\n const handle = this.#agentPlayout?.play(\n message.itemId,\n message.contentIndex,\n trFwd,\n message.textStream,\n message.audioStream,\n );\n this.#playingHandle = handle;\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('input_speech_committed', (ev: any) => {\n // openai.realtime.InputSpeechCommittedEvent\n const participantIdentity = this.linkedParticipant?.identity;\n const trackSid = this.subscribedTrack?.sid;\n if (participantIdentity && trackSid) {\n this.#publishTranscription(participantIdentity, trackSid, '…', false, ev.itemId);\n } else {\n this.#logger.error('Participant or track not set');\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('input_speech_transcription_completed', (ev: any) => {\n // openai.realtime.InputSpeechTranscriptionCompletedEvent\n const transcription = ev.transcript;\n const participantIdentity = this.linkedParticipant?.identity;\n const trackSid = this.subscribedTrack?.sid;\n if (participantIdentity && trackSid) {\n this.#publishTranscription(participantIdentity, trackSid, transcription, true, ev.itemId);\n } else {\n this.#logger.error('Participant or track not set');\n }\n const userMsg = llm.ChatMessage.create({\n role: llm.ChatRole.USER,\n text: transcription,\n });\n this.emit('user_speech_committed', userMsg);\n this.#logger.child({ transcription }).debug('committed user speech');\n });\n\n this.#session.on('input_speech_started', (ev: any) => {\n if (this.#playingHandle && !this.#playingHandle.done) {\n this.#playingHandle.interrupt();\n\n this.#session!.conversation.item.truncate(\n this.#playingHandle.itemId,\n this.#playingHandle.contentIndex,\n Math.floor((this.#playingHandle.audioSamples / 24000) * 1000),\n );\n\n this.#playingHandle = undefined;\n }\n\n const participantIdentity = this.linkedParticipant?.identity;\n const trackSid = this.subscribedTrack?.sid;\n if (participantIdentity && trackSid) {\n this.#publishTranscription(participantIdentity, trackSid, '…', false, ev.itemId);\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n this.#session.on('input_speech_stopped', (ev: any) => {\n this.emit('user_stopped_speaking');\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('function_call_started', (ev: any) => {\n this.#pendingFunctionCalls.add(ev.callId);\n this.#updateState();\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('function_call_completed', (ev: any) => {\n this.#pendingFunctionCalls.delete(ev.callId);\n this.#updateState();\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('function_call_failed', (ev: any) => {\n this.#pendingFunctionCalls.delete(ev.callId);\n this.#updateState();\n });\n\n resolve(this.#session);\n });\n }\n\n #linkParticipant(participantIdentity: string): void {\n if (!this.room) {\n this.#logger.error('Room is not set');\n return;\n }\n\n this.linkedParticipant = this.room.remoteParticipants.get(participantIdentity) || null;\n if (!this.linkedParticipant) {\n this.#logger.error(`Participant with identity ${participantIdentity} not found`);\n return;\n }\n\n if (this.linkedParticipant.trackPublications.size > 0) {\n this.#subscribeToMicrophone();\n }\n\n // also check if already subscribed\n for (const publication of this.linkedParticipant.trackPublications.values()) {\n if (publication.source === TrackSource.SOURCE_MICROPHONE && publication.track) {\n this.#handleTrackSubscription(publication.track, publication, this.linkedParticipant);\n break;\n }\n }\n }\n\n #subscribeToMicrophone(): void {\n if (!this.linkedParticipant) {\n this.#logger.error('Participant is not set');\n return;\n }\n\n let microphonePublication: RemoteTrackPublication | undefined = undefined;\n for (const publication of this.linkedParticipant.trackPublications.values()) {\n if (publication.source === TrackSource.SOURCE_MICROPHONE) {\n microphonePublication = publication;\n break;\n }\n }\n if (!microphonePublication) {\n return;\n }\n\n if (!microphonePublication.subscribed) {\n microphonePublication.setSubscribed(true);\n }\n }\n\n #handleTrackSubscription(\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ) {\n if (\n publication.source !== TrackSource.SOURCE_MICROPHONE ||\n participant.identity !== this.linkedParticipant?.identity\n ) {\n return;\n }\n const readAudioStreamTask = async (audioStream: AudioStream) => {\n const bstream = new AudioByteStream(\n this.model.sampleRate,\n this.model.numChannels,\n this.model.inFrameSize,\n );\n\n for await (const frame of audioStream) {\n const audioData = frame.data;\n for (const frame of bstream.write(audioData.buffer)) {\n this.#session!.inputAudioBuffer.append(frame);\n }\n }\n };\n this.subscribedTrack = track;\n\n if (this.readMicroTask) {\n this.readMicroTask.cancel();\n }\n\n let cancel: () => void;\n this.readMicroTask = {\n promise: new Promise<void>((resolve, reject) => {\n cancel = () => {\n reject(new Error('Task cancelled'));\n };\n readAudioStreamTask(new AudioStream(track, this.model.sampleRate, this.model.numChannels))\n .then(resolve)\n .catch(reject);\n }),\n cancel: () => cancel(),\n };\n }\n\n #getLocalTrackSid(): string | null {\n if (!this.#localTrackSid && this.room && this.room.localParticipant) {\n this.#localTrackSid = findMicroTrackId(this.room, this.room.localParticipant?.identity);\n }\n return this.#localTrackSid;\n }\n\n #publishTranscription(\n participantIdentity: string,\n trackSid: string,\n text: string,\n isFinal: boolean,\n id: string,\n ): void {\n this.#logger.debug(\n `Publishing transcription ${participantIdentity} ${trackSid} ${text} ${isFinal} ${id}`,\n );\n if (!this.room?.localParticipant) {\n this.#logger.error('Room or local participant not set');\n return;\n }\n\n this.room.localParticipant.publishTranscription({\n participantIdentity,\n trackSid,\n segments: [\n {\n text,\n final: isFinal,\n id,\n startTime: BigInt(0),\n endTime: BigInt(0),\n language: '',\n },\n ],\n });\n }\n\n #updateState() {\n let newState: AgentState = 'initializing';\n if (this.#pendingFunctionCalls.size > 0) {\n newState = 'thinking';\n } else if (this.#speaking) {\n newState = 'speaking';\n } else if (this.#started) {\n newState = 'listening';\n }\n\n this.#setState(newState);\n }\n\n #setState(state: AgentState) {\n if (this.room?.isConnected && this.room.localParticipant) {\n const currentState = this.room.localParticipant.attributes[AGENT_STATE_ATTRIBUTE];\n if (currentState !== state) {\n this.room.localParticipant.setAttributes({\n [AGENT_STATE_ATTRIBUTE]: state,\n });\n this.#logger.debug(`${AGENT_STATE_ATTRIBUTE}: ${currentState} ->${state}`);\n }\n }\n }\n}\n"],"mappings":"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","names":["participant","_a","frame"]}
|
|
1
|
+
{"version":3,"sources":["../../src/multimodal/multimodal_agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type {\n LocalTrackPublication,\n RemoteAudioTrack,\n RemoteParticipant,\n RemoteTrack,\n RemoteTrackPublication,\n Room,\n} from '@livekit/rtc-node';\nimport {\n AudioSource,\n AudioStream,\n LocalAudioTrack,\n RoomEvent,\n TrackPublishOptions,\n TrackSource,\n} from '@livekit/rtc-node';\nimport { EventEmitter } from 'node:events';\nimport { AudioByteStream } from '../audio.js';\nimport * as llm from '../llm/index.js';\nimport { log } from '../log.js';\nimport type { MultimodalLLMMetrics } from '../metrics/base.js';\nimport { BasicTranscriptionForwarder } from '../transcription.js';\nimport { findMicroTrackId } from '../utils.js';\nimport { AgentPlayout, type PlayoutHandle } from './agent_playout.js';\n\n/**\n * @internal\n * @beta\n */\nexport abstract class RealtimeSession extends EventEmitter {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract conversation: any; // openai.realtime.Conversation\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract inputAudioBuffer: any; // openai.realtime.InputAudioBuffer\n abstract fncCtx: llm.FunctionContext | undefined;\n}\n\n/**\n * @internal\n * @beta\n */\nexport abstract class RealtimeModel {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract session(options: any): RealtimeSession; // openai.realtime.ModelOptions\n abstract close(): Promise<void>;\n abstract sampleRate: number;\n abstract numChannels: number;\n abstract inFrameSize: number;\n abstract outFrameSize: number;\n}\n\nexport type AgentState = 'initializing' | 'thinking' | 'listening' | 'speaking';\nexport const AGENT_STATE_ATTRIBUTE = 'lk.agent.state';\n\n/** @beta */\nexport class MultimodalAgent extends EventEmitter {\n model: RealtimeModel;\n room: Room | null = null;\n linkedParticipant: RemoteParticipant | null = null;\n subscribedTrack: RemoteAudioTrack | null = null;\n readMicroTask: Promise<void> | null = null;\n\n constructor({\n model,\n chatCtx,\n fncCtx,\n }: {\n model: RealtimeModel;\n chatCtx?: llm.ChatContext;\n fncCtx?: llm.FunctionContext;\n }) {\n super();\n this.model = model;\n this.#chatCtx = chatCtx;\n this.#fncCtx = fncCtx;\n }\n\n #participant: RemoteParticipant | string | null = null;\n #agentPublication: LocalTrackPublication | null = null;\n #localTrackSid: string | null = null;\n #localSource: AudioSource | null = null;\n #agentPlayout: AgentPlayout | null = null;\n #playingHandle: PlayoutHandle | undefined = undefined;\n #logger = log();\n #session: RealtimeSession | null = null;\n #fncCtx: llm.FunctionContext | undefined = undefined;\n #chatCtx: llm.ChatContext | undefined = undefined;\n\n #_started: boolean = false;\n #_pendingFunctionCalls: Set<string> = new Set();\n #_speaking: boolean = false;\n\n get fncCtx(): llm.FunctionContext | undefined {\n return this.#fncCtx;\n }\n\n set fncCtx(ctx: llm.FunctionContext | undefined) {\n this.#fncCtx = ctx;\n if (this.#session) {\n this.#session.fncCtx = ctx;\n }\n }\n\n get #pendingFunctionCalls(): Set<string> {\n return this.#_pendingFunctionCalls;\n }\n\n set #pendingFunctionCalls(calls: Set<string>) {\n this.#_pendingFunctionCalls = calls;\n this.#updateState();\n }\n\n get #speaking(): boolean {\n return this.#_speaking;\n }\n\n set #speaking(isSpeaking: boolean) {\n this.#_speaking = isSpeaking;\n this.#updateState();\n }\n\n get #started(): boolean {\n return this.#_started;\n }\n\n set #started(started: boolean) {\n this.#_started = started;\n this.#updateState();\n }\n\n start(\n room: Room,\n participant: RemoteParticipant | string | null = null,\n ): Promise<RealtimeSession> {\n return new Promise(async (resolve, reject) => {\n if (this.#started) {\n reject(new Error('MultimodalAgent already started'));\n }\n this.#updateState();\n\n room.on(RoomEvent.ParticipantConnected, (participant: RemoteParticipant) => {\n // automatically link to the first participant that connects, if not already linked\n if (this.linkedParticipant) {\n return;\n }\n this.#linkParticipant(participant.identity);\n });\n room.on(\n RoomEvent.TrackPublished,\n (trackPublication: RemoteTrackPublication, participant: RemoteParticipant) => {\n if (\n this.linkedParticipant &&\n participant.identity === this.linkedParticipant.identity &&\n trackPublication.source === TrackSource.SOURCE_MICROPHONE &&\n !trackPublication.subscribed\n ) {\n trackPublication.setSubscribed(true);\n }\n },\n );\n room.on(RoomEvent.TrackSubscribed, this.#handleTrackSubscription.bind(this));\n\n this.room = room;\n this.#participant = participant;\n\n this.#localSource = new AudioSource(this.model.sampleRate, this.model.numChannels);\n this.#agentPlayout = new AgentPlayout(\n this.#localSource,\n this.model.sampleRate,\n this.model.numChannels,\n this.model.inFrameSize,\n this.model.outFrameSize,\n );\n const onPlayoutStarted = () => {\n this.emit('agent_started_speaking');\n this.#speaking = true;\n };\n\n const onPlayoutStopped = (interrupted: boolean) => {\n this.emit('agent_stopped_speaking');\n this.#speaking = false;\n if (this.#playingHandle) {\n let text = this.#playingHandle.transcriptionFwd.text;\n if (interrupted) {\n text += '…';\n }\n const msg = llm.ChatMessage.create({\n role: llm.ChatRole.ASSISTANT,\n text,\n });\n\n if (interrupted) {\n this.emit('agent_speech_interrupted', msg);\n } else {\n this.emit('agent_speech_committed', msg);\n }\n this.#logger.child({ transcription: text, interrupted }).debug('committed agent speech');\n }\n };\n\n this.#agentPlayout.on('playout_started', onPlayoutStarted);\n this.#agentPlayout.on('playout_stopped', onPlayoutStopped);\n\n const track = LocalAudioTrack.createAudioTrack('assistant_voice', this.#localSource);\n const options = new TrackPublishOptions();\n options.source = TrackSource.SOURCE_MICROPHONE;\n this.#agentPublication = (await room.localParticipant?.publishTrack(track, options)) || null;\n if (!this.#agentPublication) {\n this.#logger.error('Failed to publish track');\n reject(new Error('Failed to publish track'));\n return;\n }\n\n await this.#agentPublication.waitForSubscription();\n\n if (participant) {\n if (typeof participant === 'string') {\n this.#linkParticipant(participant);\n } else {\n this.#linkParticipant(participant.identity);\n }\n } else {\n // No participant specified, try to find the first participant in the room\n for (const participant of room.remoteParticipants.values()) {\n this.#linkParticipant(participant.identity);\n break;\n }\n }\n\n this.#session = this.model.session({ fncCtx: this.#fncCtx, chatCtx: this.#chatCtx });\n this.#started = true;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('response_content_added', (message: any) => {\n // openai.realtime.RealtimeContent\n const trFwd = new BasicTranscriptionForwarder(\n this.room!,\n this.room!.localParticipant!.identity,\n this.#getLocalTrackSid()!,\n message.responseId,\n );\n\n const handle = this.#agentPlayout?.play(\n message.itemId,\n message.contentIndex,\n trFwd,\n message.textStream,\n message.audioStream,\n );\n this.#playingHandle = handle;\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('input_speech_committed', (ev: any) => {\n // openai.realtime.InputSpeechCommittedEvent\n const participantIdentity = this.linkedParticipant?.identity;\n const trackSid = this.subscribedTrack?.sid;\n if (participantIdentity && trackSid) {\n this.#publishTranscription(participantIdentity, trackSid, '…', false, ev.itemId);\n } else {\n this.#logger.error('Participant or track not set');\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('input_speech_transcription_completed', (ev: any) => {\n // openai.realtime.InputSpeechTranscriptionCompletedEvent\n const transcription = ev.transcript;\n const participantIdentity = this.linkedParticipant?.identity;\n const trackSid = this.subscribedTrack?.sid;\n if (participantIdentity && trackSid) {\n this.#publishTranscription(participantIdentity, trackSid, transcription, true, ev.itemId);\n } else {\n this.#logger.error('Participant or track not set');\n }\n const userMsg = llm.ChatMessage.create({\n role: llm.ChatRole.USER,\n text: transcription,\n });\n this.emit('user_speech_committed', userMsg);\n this.#logger.child({ transcription }).debug('committed user speech');\n });\n\n this.#session.on('input_speech_started', (ev: any) => {\n this.emit('user_started_speaking');\n if (this.#playingHandle && !this.#playingHandle.done) {\n this.#playingHandle.interrupt();\n\n this.#session!.conversation.item.truncate(\n this.#playingHandle.itemId,\n this.#playingHandle.contentIndex,\n Math.floor((this.#playingHandle.audioSamples / 24000) * 1000),\n );\n\n this.#playingHandle = undefined;\n }\n\n const participantIdentity = this.linkedParticipant?.identity;\n const trackSid = this.subscribedTrack?.sid;\n if (participantIdentity && trackSid) {\n this.#publishTranscription(participantIdentity, trackSid, '…', false, ev.itemId);\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n this.#session.on('input_speech_stopped', (ev: any) => {\n this.emit('user_stopped_speaking');\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('function_call_started', (ev: any) => {\n this.#pendingFunctionCalls.add(ev.callId);\n this.#updateState();\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('function_call_completed', (ev: any) => {\n this.#pendingFunctionCalls.delete(ev.callId);\n this.#updateState();\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#session.on('function_call_failed', (ev: any) => {\n this.#pendingFunctionCalls.delete(ev.callId);\n this.#updateState();\n });\n\n this.#session.on('metrics_collected', (metrics: MultimodalLLMMetrics) => {\n this.emit('metrics_collected', metrics);\n });\n\n resolve(this.#session);\n });\n }\n\n #linkParticipant(participantIdentity: string): void {\n if (!this.room) {\n this.#logger.error('Room is not set');\n return;\n }\n\n this.linkedParticipant = this.room.remoteParticipants.get(participantIdentity) || null;\n if (!this.linkedParticipant) {\n this.#logger.error(`Participant with identity ${participantIdentity} not found`);\n return;\n }\n\n if (this.linkedParticipant.trackPublications.size > 0) {\n this.#subscribeToMicrophone();\n }\n\n // also check if already subscribed\n for (const publication of this.linkedParticipant.trackPublications.values()) {\n if (publication.source === TrackSource.SOURCE_MICROPHONE && publication.track) {\n this.#handleTrackSubscription(publication.track, publication, this.linkedParticipant);\n break;\n }\n }\n }\n\n #subscribeToMicrophone(): void {\n if (!this.linkedParticipant) {\n this.#logger.error('Participant is not set');\n return;\n }\n\n let microphonePublication: RemoteTrackPublication | undefined = undefined;\n for (const publication of this.linkedParticipant.trackPublications.values()) {\n if (publication.source === TrackSource.SOURCE_MICROPHONE) {\n microphonePublication = publication;\n break;\n }\n }\n if (!microphonePublication) {\n return;\n }\n\n if (!microphonePublication.subscribed) {\n microphonePublication.setSubscribed(true);\n }\n }\n\n #handleTrackSubscription(\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ) {\n if (\n publication.source !== TrackSource.SOURCE_MICROPHONE ||\n participant.identity !== this.linkedParticipant?.identity\n ) {\n return;\n }\n const readAudioStreamTask = async (audioStream: AudioStream) => {\n const bstream = new AudioByteStream(\n this.model.sampleRate,\n this.model.numChannels,\n this.model.inFrameSize,\n );\n\n for await (const frame of audioStream) {\n const audioData = frame.data;\n for (const frame of bstream.write(audioData.buffer)) {\n this.#session!.inputAudioBuffer.append(frame);\n }\n }\n };\n this.subscribedTrack = track;\n\n this.readMicroTask = new Promise<void>((resolve, reject) => {\n readAudioStreamTask(new AudioStream(track, this.model.sampleRate, this.model.numChannels))\n .then(resolve)\n .catch(reject);\n });\n }\n\n #getLocalTrackSid(): string | null {\n if (!this.#localTrackSid && this.room && this.room.localParticipant) {\n this.#localTrackSid = findMicroTrackId(this.room, this.room.localParticipant?.identity);\n }\n return this.#localTrackSid;\n }\n\n #publishTranscription(\n participantIdentity: string,\n trackSid: string,\n text: string,\n isFinal: boolean,\n id: string,\n ): void {\n this.#logger.debug(\n `Publishing transcription ${participantIdentity} ${trackSid} ${text} ${isFinal} ${id}`,\n );\n if (!this.room?.localParticipant) {\n this.#logger.error('Room or local participant not set');\n return;\n }\n\n this.room.localParticipant.publishTranscription({\n participantIdentity,\n trackSid,\n segments: [\n {\n text,\n final: isFinal,\n id,\n startTime: BigInt(0),\n endTime: BigInt(0),\n language: '',\n },\n ],\n });\n }\n\n #updateState() {\n let newState: AgentState = 'initializing';\n if (this.#pendingFunctionCalls.size > 0) {\n newState = 'thinking';\n } else if (this.#speaking) {\n newState = 'speaking';\n } else if (this.#started) {\n newState = 'listening';\n }\n\n this.#setState(newState);\n }\n\n #setState(state: AgentState) {\n if (this.room?.isConnected && this.room.localParticipant) {\n const currentState = this.room.localParticipant.attributes[AGENT_STATE_ATTRIBUTE];\n if (currentState !== state) {\n this.room.localParticipant.setAttributes({\n [AGENT_STATE_ATTRIBUTE]: state,\n });\n this.#logger.debug(`${AGENT_STATE_ATTRIBUTE}: ${currentState} ->${state}`);\n }\n }\n }\n}\n"],"mappings":"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","names":["participant","_a","frame"]}
|
|
@@ -32,10 +32,7 @@ export declare class MultimodalAgent extends EventEmitter {
|
|
|
32
32
|
room: Room | null;
|
|
33
33
|
linkedParticipant: RemoteParticipant | null;
|
|
34
34
|
subscribedTrack: RemoteAudioTrack | null;
|
|
35
|
-
readMicroTask:
|
|
36
|
-
promise: Promise<void>;
|
|
37
|
-
cancel: () => void;
|
|
38
|
-
} | null;
|
|
35
|
+
readMicroTask: Promise<void> | null;
|
|
39
36
|
constructor({ model, chatCtx, fncCtx, }: {
|
|
40
37
|
model: RealtimeModel;
|
|
41
38
|
chatCtx?: llm.ChatContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multimodal_agent.d.ts","sourceRoot":"","sources":["../../src/multimodal/multimodal_agent.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAEV,gBAAgB,EAChB,iBAAiB,EAGjB,IAAI,EACL,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"multimodal_agent.d.ts","sourceRoot":"","sources":["../../src/multimodal/multimodal_agent.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAEV,gBAAgB,EAChB,iBAAiB,EAGjB,IAAI,EACL,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAOvC;;;GAGG;AACH,8BAAsB,eAAgB,SAAQ,YAAY;IAExD,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC;IAE3B,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,eAAe,GAAG,SAAS,CAAC;CAClD;AAED;;;GAGG;AACH,8BAAsB,aAAa;IAEjC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,eAAe;IAC/C,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;AAChF,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AAEtD,YAAY;AACZ,qBAAa,eAAgB,SAAQ,YAAY;;IAC/C,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAQ;IACzB,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IACnD,eAAe,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAChD,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAQ;gBAE/B,EACV,KAAK,EACL,OAAO,EACP,MAAM,GACP,EAAE;QACD,KAAK,EAAE,aAAa,CAAC;QACrB,OAAO,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC;QAC1B,MAAM,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC;KAC9B;IAsBD,IAAI,MAAM,IAAI,GAAG,CAAC,eAAe,GAAG,SAAS,CAE5C;IAED,IAAI,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,eAAe,GAAG,SAAS,EAK9C;IA6BD,KAAK,CACH,IAAI,EAAE,IAAI,EACV,WAAW,GAAE,iBAAiB,GAAG,MAAM,GAAG,IAAW,GACpD,OAAO,CAAC,eAAe,CAAC;CAyV5B"}
|
|
@@ -205,6 +205,7 @@ class MultimodalAgent extends EventEmitter {
|
|
|
205
205
|
});
|
|
206
206
|
this.#session.on("input_speech_started", (ev) => {
|
|
207
207
|
var _a2, _b;
|
|
208
|
+
this.emit("user_started_speaking");
|
|
208
209
|
if (this.#playingHandle && !this.#playingHandle.done) {
|
|
209
210
|
this.#playingHandle.interrupt();
|
|
210
211
|
this.#session.conversation.item.truncate(
|
|
@@ -235,6 +236,9 @@ class MultimodalAgent extends EventEmitter {
|
|
|
235
236
|
this.#pendingFunctionCalls.delete(ev.callId);
|
|
236
237
|
this.#updateState();
|
|
237
238
|
});
|
|
239
|
+
this.#session.on("metrics_collected", (metrics) => {
|
|
240
|
+
this.emit("metrics_collected", metrics);
|
|
241
|
+
});
|
|
238
242
|
resolve(this.#session);
|
|
239
243
|
});
|
|
240
244
|
}
|
|
@@ -296,19 +300,9 @@ class MultimodalAgent extends EventEmitter {
|
|
|
296
300
|
}
|
|
297
301
|
};
|
|
298
302
|
this.subscribedTrack = track;
|
|
299
|
-
|
|
300
|
-
this.
|
|
301
|
-
}
|
|
302
|
-
let cancel;
|
|
303
|
-
this.readMicroTask = {
|
|
304
|
-
promise: new Promise((resolve, reject) => {
|
|
305
|
-
cancel = () => {
|
|
306
|
-
reject(new Error("Task cancelled"));
|
|
307
|
-
};
|
|
308
|
-
readAudioStreamTask(new AudioStream(track, this.model.sampleRate, this.model.numChannels)).then(resolve).catch(reject);
|
|
309
|
-
}),
|
|
310
|
-
cancel: () => cancel()
|
|
311
|
-
};
|
|
303
|
+
this.readMicroTask = new Promise((resolve, reject) => {
|
|
304
|
+
readAudioStreamTask(new AudioStream(track, this.model.sampleRate, this.model.numChannels)).then(resolve).catch(reject);
|
|
305
|
+
});
|
|
312
306
|
}
|
|
313
307
|
#getLocalTrackSid() {
|
|
314
308
|
var _a;
|