-
Notifications
You must be signed in to change notification settings - Fork 214
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
I am creating new app with aws ecs
I tried run app as start and special room
Relevant log output
file:///app/node_modules/.pnpm/@livekit+agents@1.0.27_@livekit[email protected][email protected]/node_modules/@livekit/agents/dist/ipc/supervised_proc.js:114
throw err;
Error: runner initialization timed out
at Timeout.onTimeout (file:///app/node_modules/.pnpm/@livekit[email protected]@livekit[email protected][email protected]/node_modules/@livekit/agents/dist/ipc/supervised_proc.js:112:19)
at listOnTimeout (node:internal/timers:588:17)
at process.processTimers (node:internal/timers:523:7)
Describe your environment
aws ecs ec2 container
Minimal reproducible example
agent.ts
import {
type JobContext,
type JobProcess,
cli,
defineAgent,
voice,
metrics,
ServerOptions,
} from '@livekit/agents';
import { type Room } from '@livekit/rtc-node';
import dotenv from 'dotenv';
import * as deepgram from '@livekit/agents-plugin-deepgram';
import * as livekit from '@livekit/agents-plugin-livekit';
import * as openai from '@livekit/agents-plugin-openai';
import * as silero from '@livekit/agents-plugin-silero';
import { fileURLToPath } from 'node:url';
import { RoomAgentDispatch, RoomConfiguration } from '@livekit/protocol';
import { AccessToken } from 'livekit-server-sdk';
dotenv.config();
export class RealtimeAgent extends voice.Agent {
override async onEnter(): Promise<void> {
await this.session.say("Hello, how can I help you today?", {
allowInterruptions: false,
});
return Promise.resolve();
}
static create({
room,
}: {
room: Room;
}) {
return new RealtimeAgent({
instructions: 'You are a helpful agent. Your name is Mario. You can check the weather forecast, search information in the knowledge base and transfer to human.',
});
}
}
async function createTokenWithAgentDispatch(roomName: string, agentName: string) {
const at = new AccessToken();
at.identity = 'my-participant';
at.addGrant({ roomJoin: true, room: roomName });
at.roomConfig = new RoomConfiguration({
agents: [
new RoomAgentDispatch({
agentName: agentName,
metadata: '{"user_id": "12345"}',
}),
],
});
return await at.toJwt();
}
export default defineAgent({
prewarm: async (proc: JobProcess) => {
console.log('Starting VAD model prewarm...');
const startTime = Date.now();
try {
proc.userData.vad = await Promise.race([
silero.VAD.load(),
new Promise((_, reject) => setTimeout(() => reject(new Error('VAD load timed out')), 5000))
]);
const loadTime = Date.now() - startTime;
console.log(`VAD model loaded in ${loadTime}ms`);
} catch (e) {
console.error('Failed to prewarm VAD model:', e);
// Fallback or let it fail, but don't hang
throw e;
}
},
entry: async (ctx: JobContext) => {
await createTokenWithAgentDispatch(ctx.room.name!, 'realtime-voice-agent');
const session = new voice.AgentSession({
// vad: ctx.proc.userData.vad! as silero.VAD,
stt: new deepgram.STT(),
tts: new deepgram.TTS(),
llm: new openai.LLM(),
// to use realtime model, replace the stt, llm, tts and vad with the following
// llm: new openai.realtime.RealtimeModel(),
userData: {},
turnDetection: new livekit.turnDetector.MultilingualModel(),
});
const usageCollector = new metrics.UsageCollector();
session.on(voice.AgentSessionEventTypes.MetricsCollected, (ev) => {
metrics.logMetrics(ev.metrics);
usageCollector.collect(ev.metrics);
});
const logUsage = async () => {
const summary = usageCollector.getSummary();
console.log(`Usage: ${JSON.stringify(summary)}`);
};
ctx.addShutdownCallback(logUsage);
console.log({ ctx, session })
await session.start({
agent: RealtimeAgent.create({ room: ctx.room }),
room: ctx.room,
});
session.on(voice.AgentSessionEventTypes.MetricsCollected, (ev) => {
metrics.logMetrics(ev.metrics);
usageCollector.collect(ev.metrics);
});
const participant = await ctx.waitForParticipant();
console.log('participant joined: ', participant.identity);
// session.on()
},
});
cli.runApp(new ServerOptions({
agent: fileURLToPath(import.meta.url),
agentName: 'realtime-voice-agent',
logLevel: 'debug',
production: process.env.NODE_ENV === 'production',
apiKey: process.env.LIVEKIT_API_KEY as string,
apiSecret: process.env.LIVEKIT_API_SECRET as string,
wsURL: process.env.LIVEKIT_URL as string,
host: '0.0.0.0',
port: 3001,
initializeProcessTimeout: 120_000,
}));Dockerfile
ARG NODE_VERSION=22
ARG PLATFORM=linux/amd64
FROM --platform=${PLATFORM} node:${NODE_VERSION}-slim AS base
WORKDIR /app
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y ca-certificates libgomp1 && \
rm -rf /var/lib/apt/lists/* && \
npm i -g corepack@latest && \
corepack enable
COPY ./package.json ./pnpm-lock.yaml ./pnpm-workspace.yaml ./tsconfig.json ./.npmrc ./
COPY ./packages/agent ./packages/agent
# Install the project dependencies
RUN pnpm install --frozen-lockfile --filter realtime-voice-agent && \
pnpm --filter realtime-voice-agent -r build && \
pnpm deploy --filter realtime-voice-agent --prod packages/agent/deploy && \
cd packages/agent/deploy
FROM --platform=${PLATFORM} node:${NODE_VERSION}-slim AS app
LABEL project="realtime-voice-agent"
WORKDIR /app
# Create a non-privileged user that the app will run under
# See https://docs.docker.com/develop/develop-images/dockerfile_best_practices/#user
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/app" \
--shell "/sbin/nologin" \
--uid "${UID}" \
appuser
# Set proper permissions
RUN chown -R appuser:appuser /app
COPY --from=base /app/packages/agent/deploy .
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y ca-certificates libgomp1 tini && \
rm -rf /var/lib/apt/lists/* && \
chown -R appuser:appuser /app
USER appuser
RUN node dist/agent.js download-files
ENTRYPOINT ["/bin/sh", "./docker-entrypoint.sh"]
Additional information
No response
umstek
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working