Skip to content

Commit f928b0e

Browse files
committed
Slight tweaks and improvements
1 parent 3896ca8 commit f928b0e

File tree

5 files changed

+32
-121
lines changed

5 files changed

+32
-121
lines changed

README.md

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Trigger.dev Realtime Demo
1+
## Trigger.dev Realtime streams Demo
22

33
This demo shows off a variety of features of [Trigger.dev Realtime](https://trigger.dev/docs/realtime)
44

@@ -16,7 +16,23 @@ npm run dev
1616
npm run dev:trigger # Run this in a separate terminal
1717
```
1818

19-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
19+
Open [http://localhost:3000/weather](http://localhost:3000/weather) with your browser to see the result.
20+
21+
## Realtime + ai SDK + streams
22+
23+
<video
24+
src="https://content.trigger.dev/realtime-streams-demo.mp4"
25+
preload="auto"
26+
controls={true}
27+
loop
28+
muted
29+
autoPlay={true}
30+
width="100%"
31+
height="100%"
32+
/>
33+
34+
- View the Trigger.dev task code in the [src/trigger/ai.ts](src/trigger/ai.ts) file.
35+
- View the frontend code in the [src/app/weather/page.tsx](src/app/weather/page.tsx) file and the [src/components/GetStreamingWeatherButton.tsx](src/components/GetStreamingWeatherButton.tsx) file.
2036

2137
## Learn More
2238

src/app/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import RunButton from "@/components/RunButton";
22
import BatchRunButton from "@/components/BatchRunButton";
33
import TriggerButton from "@/components/TriggerButton";
4-
import TriggerButtonWithStreaming from "@/components/TriggerButtonWithStreaming";
4+
import GetStreamingWeatherButton from "@/components/GetStreamingWeatherButton";
55
import { ImageUploadDropzone } from "@/components/ImageUploadButton";
66
import { auth } from "@trigger.dev/sdk/v3";
77

@@ -36,7 +36,7 @@ export default async function Home() {
3636
<RunButton />
3737
<BatchRunButton />
3838
<TriggerButton accessToken={publicAccessToken} />
39-
<TriggerButtonWithStreaming accessToken={publicAccessToken} />
39+
<GetStreamingWeatherButton accessToken={publicAccessToken} />
4040
</div>
4141
</main>
4242
);

src/app/weather/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import TriggerButtonWithStreaming from "@/components/TriggerButtonWithStreaming";
1+
import GetStreamingWeatherButton from "@/components/GetStreamingWeatherButton";
22
import { auth } from "@trigger.dev/sdk/v3";
33

44
export default async function WeatherPage() {
@@ -13,7 +13,7 @@ export default async function WeatherPage() {
1313
return (
1414
<main className="grid grid-rows-[1fr_auto] min-h-screen items-center justify-center w-full bg-gray-900">
1515
<div className="flex flex-col space-y-8">
16-
<TriggerButtonWithStreaming accessToken={publicAccessToken} />
16+
<GetStreamingWeatherButton accessToken={publicAccessToken} />
1717
</div>
1818
</main>
1919
);

src/components/TriggerButtonWithStreaming.tsx renamed to src/components/GetStreamingWeatherButton.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { Button } from "@/components/ui/button";
4-
import type { STREAMS, openaiStreaming } from "@/trigger/ai";
4+
import type { STREAMS, aiWeather } from "@/trigger/ai";
55
import { useRealtimeTaskTriggerWithStreams } from "@trigger.dev/react-hooks";
66
import { useCallback, useState } from "react";
77
import {
@@ -14,17 +14,17 @@ import {
1414
} from "./ui/dialog";
1515
import { Card, CardContent, CardFooter } from "./ui/card";
1616

17-
export default function TriggerButton({
17+
export default function GetStreamingWeather({
1818
accessToken,
1919
}: {
2020
accessToken: string;
2121
}) {
2222
const [isOpen, setIsOpen] = useState(false);
2323

2424
const { submit, isLoading, run, streams } = useRealtimeTaskTriggerWithStreams<
25-
typeof openaiStreaming,
25+
typeof aiWeather,
2626
STREAMS
27-
>("openai-streaming", {
27+
>("ai-weather", {
2828
accessToken,
2929
baseURL: process.env.NEXT_PUBLIC_TRIGGER_API_URL,
3030
experimental_throttleInMs: 100,

src/trigger/ai.ts

+6-111
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,12 @@
11
import { openai } from "@ai-sdk/openai";
2-
import {
3-
logger,
4-
metadata,
5-
runs,
6-
schemaTask,
7-
task,
8-
toolTask,
9-
wait,
10-
} from "@trigger.dev/sdk/v3";
11-
import { streamText, type TextStreamPart, tool } from "ai";
12-
import { setTimeout } from "node:timers/promises";
2+
import { logger, metadata, schemaTask, toolTask } from "@trigger.dev/sdk/v3";
3+
import { streamText, type TextStreamPart } from "ai";
134
import { z } from "zod";
145

156
export type STREAMS = {
167
openai: TextStreamPart<{ getWeather: typeof weatherTask.tool }>;
178
};
189

19-
export const openaiConsumer = schemaTask({
20-
id: "openai-consumer",
21-
schema: z.object({
22-
model: z.string().default("gpt-3.5-turbo"),
23-
prompt: z.string().default("Hello, how are you?"),
24-
}),
25-
run: async ({ model, prompt }) => {
26-
const handle = await openaiStreaming.trigger({ model, prompt });
27-
28-
let openaiCompletion = "";
29-
30-
for await (const part of runs
31-
.subscribeToRun(handle)
32-
.withStreams<STREAMS>()) {
33-
switch (part.type) {
34-
case "run": {
35-
logger.info("Received run chunk", { run: part.run });
36-
break;
37-
}
38-
case "openai": {
39-
logger.info("Received OpenAI chunk", {
40-
chunk: part.chunk,
41-
run: part.run,
42-
});
43-
44-
switch (part.chunk.type) {
45-
case "text-delta": {
46-
openaiCompletion += part.chunk.textDelta;
47-
break;
48-
}
49-
case "tool-call": {
50-
switch (part.chunk.toolName) {
51-
case "getWeather": {
52-
console.log("Calling getWeather tool with args", {
53-
args: part.chunk.args,
54-
});
55-
}
56-
}
57-
break;
58-
}
59-
case "tool-result": {
60-
switch (part.chunk.toolName) {
61-
case "getWeather": {
62-
console.log("Received getWeather tool result", {
63-
result: part.chunk.result,
64-
});
65-
}
66-
}
67-
break;
68-
}
69-
}
70-
}
71-
}
72-
}
73-
74-
return { openaiCompletion };
75-
},
76-
});
77-
78-
export const waitUntilExamples = task({
79-
id: "wait-until-examples",
80-
run: async () => {
81-
await setTimeout(30_000);
82-
},
83-
});
84-
8510
export const weatherTask = toolTask({
8611
id: "weather",
8712
description: "Get the weather for a location",
@@ -97,11 +22,11 @@ export const weatherTask = toolTask({
9722
},
9823
});
9924

100-
export const openaiStreaming = schemaTask({
101-
id: "openai-streaming",
102-
description: "Stream data from OpenAI to get the weather",
25+
export const aiWeather = schemaTask({
26+
id: "ai-weather",
27+
description: "Send the fullStream from the ai SDK to the metadata system",
10328
schema: z.object({
104-
model: z.string().default("chatgpt-4o-latest"),
29+
model: z.string().default("gpt-4o-mini"),
10530
prompt: z.string().default("Hello, how are you?"),
10631
}),
10732
run: async ({ model, prompt }) => {
@@ -131,33 +56,3 @@ export const openaiStreaming = schemaTask({
13156
return { text };
13257
},
13358
});
134-
135-
export const openaiO1Model = schemaTask({
136-
id: "openai-o1-model",
137-
description: "Stream data from OpenAI to get the weather",
138-
schema: z.object({
139-
model: z.string().default("o1-preview"),
140-
prompt: z.string().default("Hello, how are you?"),
141-
}),
142-
run: async ({ model, prompt }) => {
143-
logger.info("Running OpenAI model", { model, prompt });
144-
145-
const result = await streamText({
146-
model: openai(model),
147-
prompt,
148-
experimental_continueSteps: true,
149-
});
150-
151-
const stream = await metadata.stream("openai", result.textStream);
152-
153-
let text = "";
154-
155-
for await (const chunk of stream) {
156-
logger.log("Received chunk", { chunk });
157-
158-
text += chunk;
159-
}
160-
161-
return { text };
162-
},
163-
});

0 commit comments

Comments
 (0)