2025-03-05 15:09:10 +01:00
|
|
|
import { StockbrokerState, StockbrokerUpdate } from "../types";
|
2025-02-27 15:41:47 -08:00
|
|
|
import { ChatOpenAI } from "@langchain/openai";
|
|
|
|
|
import { typedUi } from "@langchain/langgraph-sdk/react-ui/server";
|
|
|
|
|
import type ComponentMap from "../../uis/index";
|
|
|
|
|
import { z } from "zod";
|
|
|
|
|
import { LangGraphRunnableConfig } from "@langchain/langgraph";
|
|
|
|
|
import { findToolCall } from "../../find-tool-call";
|
|
|
|
|
|
|
|
|
|
const llm = new ChatOpenAI({ model: "gpt-4o-mini", temperature: 0 });
|
|
|
|
|
|
|
|
|
|
const getStockPriceSchema = z.object({
|
|
|
|
|
ticker: z.string().describe("The ticker symbol of the company"),
|
|
|
|
|
});
|
|
|
|
|
const getPortfolioSchema = z.object({
|
|
|
|
|
get_portfolio: z.boolean().describe("Should be true."),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const STOCKBROKER_TOOLS = [
|
|
|
|
|
{
|
|
|
|
|
name: "stock-price",
|
|
|
|
|
description: "A tool to get the stock price of a company",
|
|
|
|
|
schema: getStockPriceSchema,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "portfolio",
|
|
|
|
|
description:
|
|
|
|
|
"A tool to get the user's portfolio details. Only call this tool if the user requests their portfolio details.",
|
|
|
|
|
schema: getPortfolioSchema,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export async function callTools(
|
|
|
|
|
state: StockbrokerState,
|
|
|
|
|
config: LangGraphRunnableConfig,
|
2025-03-05 15:09:10 +01:00
|
|
|
): Promise<StockbrokerUpdate> {
|
2025-02-27 15:41:47 -08:00
|
|
|
const ui = typedUi<typeof ComponentMap>(config);
|
|
|
|
|
|
|
|
|
|
const message = await llm.bindTools(STOCKBROKER_TOOLS).invoke([
|
|
|
|
|
{
|
|
|
|
|
role: "system",
|
|
|
|
|
content:
|
|
|
|
|
"You are a stockbroker agent that uses tools to get the stock price of a company",
|
|
|
|
|
},
|
|
|
|
|
...state.messages,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const stockbrokerToolCall = message.tool_calls?.find(
|
|
|
|
|
findToolCall("stock-price")<typeof getStockPriceSchema>,
|
|
|
|
|
);
|
|
|
|
|
const portfolioToolCall = message.tool_calls?.find(
|
|
|
|
|
findToolCall("portfolio")<typeof getStockPriceSchema>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (stockbrokerToolCall) {
|
|
|
|
|
const instruction = `The stock price of ${
|
|
|
|
|
stockbrokerToolCall.args.ticker
|
|
|
|
|
} is ${Math.random() * 100}`;
|
|
|
|
|
|
|
|
|
|
ui.write("stock-price", { instruction, logo: "hey" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (portfolioToolCall) {
|
|
|
|
|
ui.write("portfolio", {});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
2025-02-28 14:15:37 -08:00
|
|
|
messages: [message],
|
2025-03-05 15:09:10 +01:00
|
|
|
ui: ui.collect,
|
2025-02-27 15:41:47 -08:00
|
|
|
timestamp: Date.now(),
|
|
|
|
|
};
|
|
|
|
|
}
|