Files
open-gsio/workers/site/workflows/preprocessing/webOperator.ts
geoffsee 33679583af init
2025-05-22 23:14:01 -04:00

101 lines
2.6 KiB
TypeScript

import { WorkflowOperator } from "manifold-workflow-engine";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";
const QuerySchema = z.object({
query: z.string(), // No min/max constraints in the schema
});
export function createSearchWebhookOperator({
eventHost,
streamId,
openai,
messages,
}) {
return new WorkflowOperator("web-search", async (state: any) => {
const { latestUserMessage } = state;
const websearchWebhookEndpoint = "/api/webhooks";
const resource = "web-search";
const input = await getQueryFromContext({
openai,
messages,
latestUserMessage,
});
// process webhooks
const eventSource = new URL(eventHost);
const url = `${eventSource}api/webhooks`;
const stream = {
id: crypto.randomUUID(),
parent: streamId,
resource,
payload: input,
};
const createStreamResponse = await fetch(`${eventSource}api/webhooks`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
id: stream.id,
parent: streamId,
resource: "web-search",
payload: {
input,
},
}),
});
const raw = await createStreamResponse.text();
const { stream_url } = JSON.parse(raw);
const surl = eventHost + stream_url;
const webhook = { url: surl, id: stream.id, resource };
return {
...state,
webhook,
latestUserMessage: "", // unset to break out of loop
latestAiMessage: "", // unset to break out of loop
};
});
}
async function getQueryFromContext({ messages, openai, latestUserMessage }) {
const systemMessage = {
role: "system",
content: `Analyze the latest message in the conversation and generate a JSON object with a single implied question for a web search. The JSON should be structured as follows:
{
"query": "the question that needs a web search"
}
## Example
{
"query": "What was the score of the last Buffalo Sabres hockey game?"
}
Focus on the most recent message to determine the query. Output only the JSON object without any additional text.`,
};
const conversation = messages.map((m) => ({
role: m.role,
content: m.content,
}));
conversation.push({ role: "user", content: `${latestUserMessage}` });
const m = [systemMessage, ...conversation];
const completion = await openai.beta.chat.completions.parse({
model: "gpt-4o-mini",
messages: m,
temperature: 0,
response_format: zodResponseFormat(QuerySchema, "query"),
});
const { query } = completion.choices[0].message.parsed;
return query;
}