From 5fa980de5eec8f428584ca02760fdf2fa41f1295 Mon Sep 17 00:00:00 2001 From: leehuwuj Date: Fri, 25 Oct 2024 10:38:07 +0700 Subject: [PATCH 1/9] add financial report use case for TS --- helpers/typescript.ts | 28 ++- questions/simple.ts | 30 ++-- .../typescript/blog}/agents.ts | 0 .../typescript/blog}/factory.ts | 0 .../typescript/blog}/tools.ts | 0 .../typescript/financial_report/agents.ts | 65 +++++++ .../typescript/financial_report/factory.ts | 159 ++++++++++++++++++ .../typescript/financial_report/tools.ts | 86 ++++++++++ templates/types/streaming/nextjs/package.json | 3 +- 9 files changed, 351 insertions(+), 20 deletions(-) rename templates/components/{multiagent/typescript/workflow => agents/typescript/blog}/agents.ts (100%) rename templates/components/{multiagent/typescript/workflow => agents/typescript/blog}/factory.ts (100%) rename templates/components/{multiagent/typescript/workflow => agents/typescript/blog}/tools.ts (100%) create mode 100644 templates/components/agents/typescript/financial_report/agents.ts create mode 100644 templates/components/agents/typescript/financial_report/factory.ts create mode 100644 templates/components/agents/typescript/financial_report/tools.ts diff --git a/helpers/typescript.ts b/helpers/typescript.ts index f4d42cf96..da6bd62cb 100644 --- a/helpers/typescript.ts +++ b/helpers/typescript.ts @@ -1,7 +1,7 @@ import fs from "fs/promises"; import os from "os"; import path from "path"; -import { bold, cyan, yellow } from "picocolors"; +import { bold, cyan, red, yellow } from "picocolors"; import { assetRelocator, copy } from "../helpers/copy"; import { callPackageManager } from "../helpers/install"; import { templatesDir } from "./dir"; @@ -26,6 +26,7 @@ export const installTSTemplate = async ({ tools, dataSources, useLlamaParse, + agents, }: InstallTemplateArgs & { backend: boolean }) => { console.log(bold(`Using ${packageManager}.`)); @@ -132,6 +133,31 @@ export const installTSTemplate = async ({ cwd: path.join(multiagentPath, "workflow"), }); + // Copy agents use case code for multiagent template + if (agents) { + console.log("\nCopying agent:", agents, "\n"); + + const agentsCodePath = path.join( + compPath, + "agents", + "typescript", + agents, + ); + + await copy("**", path.join(root, relativeEngineDestPath, "workflow"), { + parents: true, + cwd: agentsCodePath, + rename: assetRelocator, + }); + } else { + console.log( + red( + "There is no agent selected for multi-agent template. Please pick an agent to use via --agents flag.", + ), + ); + process.exit(1); + } + if (framework === "nextjs") { // patch route.ts file await copy("**", path.join(root, relativeEngineDestPath), { diff --git a/questions/simple.ts b/questions/simple.ts index 195e30d8c..4888c9856 100644 --- a/questions/simple.ts +++ b/questions/simple.ts @@ -47,23 +47,19 @@ export const askSimpleQuestions = async ( let useLlamaCloud = false; if (appType !== "extractor") { - // Default financial report agent use case only supports Python - // TODO: Add support for Typescript frameworks - if (appType !== "financial_report_agent") { - const { language: newLanguage } = await prompts( - { - type: "select", - name: "language", - message: "What language do you want to use?", - choices: [ - { title: "Python (FastAPI)", value: "fastapi" }, - { title: "Typescript (NextJS)", value: "nextjs" }, - ], - }, - questionHandlers, - ); - language = newLanguage; - } + const { language: newLanguage } = await prompts( + { + type: "select", + name: "language", + message: "What language do you want to use?", + choices: [ + { title: "Python (FastAPI)", value: "fastapi" }, + { title: "Typescript (NextJS)", value: "nextjs" }, + ], + }, + questionHandlers, + ); + language = newLanguage; const { useLlamaCloud: newUseLlamaCloud } = await prompts( { diff --git a/templates/components/multiagent/typescript/workflow/agents.ts b/templates/components/agents/typescript/blog/agents.ts similarity index 100% rename from templates/components/multiagent/typescript/workflow/agents.ts rename to templates/components/agents/typescript/blog/agents.ts diff --git a/templates/components/multiagent/typescript/workflow/factory.ts b/templates/components/agents/typescript/blog/factory.ts similarity index 100% rename from templates/components/multiagent/typescript/workflow/factory.ts rename to templates/components/agents/typescript/blog/factory.ts diff --git a/templates/components/multiagent/typescript/workflow/tools.ts b/templates/components/agents/typescript/blog/tools.ts similarity index 100% rename from templates/components/multiagent/typescript/workflow/tools.ts rename to templates/components/agents/typescript/blog/tools.ts diff --git a/templates/components/agents/typescript/financial_report/agents.ts b/templates/components/agents/typescript/financial_report/agents.ts new file mode 100644 index 000000000..101e074d5 --- /dev/null +++ b/templates/components/agents/typescript/financial_report/agents.ts @@ -0,0 +1,65 @@ +import { ChatMessage } from "llamaindex"; +import { FunctionCallingAgent } from "./single-agent"; +import { getQueryEngineTools, lookupTools } from "./tools"; + +export const createResearcher = async ( + chatHistory: ChatMessage[], + params?: any, +) => { + const queryEngineTools = await getQueryEngineTools(params); + + if (!queryEngineTools) { + throw new Error("Query engine tool not found"); + } + + return new FunctionCallingAgent({ + name: "researcher", + tools: queryEngineTools, + systemPrompt: `You are a researcher agent. You are responsible for retrieving information from the corpus. +## Instructions: ++ Don't synthesize the information, just return the whole retrieved information. ++ Don't need to retrieve the information that is already provided in the chat history and response with: "There is no new information, please reuse the information from the conversation." +`, + chatHistory, + }); +}; + +export const createAnalyst = async (chatHistory: ChatMessage[]) => { + let systemPrompt = `You are an expert in analyzing financial data. +You are given a task and a set of financial data to analyze. Your task is to analyze the financial data and return a report. +Your response should include a detailed analysis of the financial data, including any trends, patterns, or insights that you find. +Construct the analysis in a textual format like tables would be great! +Don't need to synthesize the data, just analyze and provide your findings. +Always use the provided information, don't make up any information yourself.`; + const tools = await lookupTools(["interpreter"]); + if (tools.length > 0) { + systemPrompt = `${systemPrompt} +You are able to visualize the financial data using code interpreter tool. +It's very useful to create and include visualizations to the report. Never include any code into the report, just the visualization.`; + } + return new FunctionCallingAgent({ + name: "analyst", + tools: tools, + chatHistory, + }); +}; + +export const createReporter = async (chatHistory: ChatMessage[]) => { + const tools = await lookupTools(["document_generator"]); + let systemPrompt = `You are a report generation assistant tasked with producing a well-formatted report given parsed context. +Given a comprehensive analysis of the user request, your task is to synthesize the information and return a well-formatted report. + +## Instructions +You are responsible for representing the analysis in a well-formatted report. If tables or visualizations are provided, add them to the most relevant sections. +Finally, the report should be presented in markdown format.`; + if (tools.length > 0) { + systemPrompt = `${systemPrompt}. +You are also able to generate an HTML file of the report.`; + } + return new FunctionCallingAgent({ + name: "reporter", + tools: tools, + systemPrompt: systemPrompt, + chatHistory, + }); +}; diff --git a/templates/components/agents/typescript/financial_report/factory.ts b/templates/components/agents/typescript/financial_report/factory.ts new file mode 100644 index 000000000..ea530969c --- /dev/null +++ b/templates/components/agents/typescript/financial_report/factory.ts @@ -0,0 +1,159 @@ +import { + Context, + StartEvent, + StopEvent, + Workflow, + WorkflowEvent, +} from "@llamaindex/core/workflow"; +import { Message } from "ai"; +import { ChatMessage, ChatResponseChunk, Settings } from "llamaindex"; +import { getAnnotations } from "../llamaindex/streaming/annotations"; +import { createAnalyst, createReporter, createResearcher } from "./agents"; +import { AgentInput, AgentRunEvent } from "./type"; + +const TIMEOUT = 360 * 1000; +const MAX_ATTEMPTS = 2; + +class ResearchEvent extends WorkflowEvent<{ input: string }> {} +class AnalyzeEvent extends WorkflowEvent<{ input: string }> {} +class ReportEvent extends WorkflowEvent<{ input: string }> {} + +const prepareChatHistory = (chatHistory: Message[]): ChatMessage[] => { + // By default, the chat history only contains the assistant and user messages + // all the agents messages are stored in annotation data which is not visible to the LLM + + const MAX_AGENT_MESSAGES = 10; + const agentAnnotations = getAnnotations<{ agent: string; text: string }>( + chatHistory, + { role: "assistant", type: "agent" }, + ).slice(-MAX_AGENT_MESSAGES); + + const agentMessages = agentAnnotations + .map( + (annotation) => + `\n<${annotation.data.agent}>\n${annotation.data.text}\n`, + ) + .join("\n"); + + const agentContent = agentMessages + ? "Here is the previous conversation of agents:\n" + agentMessages + : ""; + + if (agentContent) { + const agentMessage: ChatMessage = { + role: "assistant", + content: agentContent, + }; + return [ + ...chatHistory.slice(0, -1), + agentMessage, + chatHistory.slice(-1)[0], + ] as ChatMessage[]; + } + return chatHistory as ChatMessage[]; +}; + +export const createWorkflow = (messages: Message[], params?: any) => { + const chatHistoryWithAgentMessages = prepareChatHistory(messages); + const runAgent = async ( + context: Context, + agent: Workflow, + input: AgentInput, + ) => { + const run = agent.run(new StartEvent({ input })); + for await (const event of agent.streamEvents()) { + if (event.data instanceof AgentRunEvent) { + context.writeEventToStream(event.data); + } + } + return await run; + }; + + const start = async (context: Context, ev: StartEvent) => { + context.set("task", ev.data.input); + + const chatHistoryStr = chatHistoryWithAgentMessages + .map((msg) => `${msg.role}: ${msg.content}`) + .join("\n"); + + // Decision-making process + const decision = await decideWorkflow(ev.data.input, chatHistoryStr); + + if (decision !== "publish") { + return new ResearchEvent({ + input: `Research for this task: ${ev.data.input}`, + }); + } else { + return new ReportEvent({ + input: `Publish content based on the chat history\n${chatHistoryStr}\n\n and task: ${ev.data.input}`, + }); + } + }; + + const decideWorkflow = async (task: string, chatHistoryStr: string) => { + const llm = Settings.llm; + + const prompt = `You are an expert in decision-making, helping people write and publish blog posts. +If the user is asking for a file or to publish content, respond with 'publish'. +If the user requests to write or update a blog post, respond with 'not_publish'. + +Here is the chat history: +${chatHistoryStr} + +The current user request is: +${task} + +Given the chat history and the new user request, decide whether to publish based on existing information. +Decision (respond with either 'not_publish' or 'publish'):`; + + const output = await llm.complete({ prompt: prompt }); + const decision = output.text.trim().toLowerCase(); + return decision === "publish" ? "publish" : "research"; + }; + + const research = async (context: Context, ev: ResearchEvent) => { + const researcher = await createResearcher( + chatHistoryWithAgentMessages, + params, + ); + const researchRes = await runAgent(context, researcher, { + message: ev.data.input, + }); + const researchResult = researchRes.data.result; + return new AnalyzeEvent({ + input: `Write a blog post given this task: ${context.get("task")} using this research content: ${researchResult}`, + }); + }; + + const analyze = async (context: Context, ev: AnalyzeEvent) => { + const analyst = await createAnalyst(chatHistoryWithAgentMessages); + const analyzeRes = await runAgent(context, analyst, { + message: ev.data.input, + }); + return new ReportEvent({ + input: `Publish content based on the chat history\n${analyzeRes.data.result}\n\n and task: ${ev.data.input}`, + }); + }; + + const report = async (context: Context, ev: ReportEvent) => { + const reporter = await createReporter(chatHistoryWithAgentMessages); + + const reportResult = await runAgent(context, reporter, { + message: `${ev.data.input}`, + streaming: true, + }); + return reportResult as unknown as StopEvent< + AsyncGenerator + >; + }; + + const workflow = new Workflow({ timeout: TIMEOUT, validate: true }); + workflow.addStep(StartEvent, start, { + outputs: [ResearchEvent, ReportEvent], + }); + workflow.addStep(ResearchEvent, research, { outputs: AnalyzeEvent }); + workflow.addStep(AnalyzeEvent, analyze, { outputs: ReportEvent }); + workflow.addStep(ReportEvent, report, { outputs: StopEvent }); + + return workflow; +}; diff --git a/templates/components/agents/typescript/financial_report/tools.ts b/templates/components/agents/typescript/financial_report/tools.ts new file mode 100644 index 000000000..3d979a77a --- /dev/null +++ b/templates/components/agents/typescript/financial_report/tools.ts @@ -0,0 +1,86 @@ +import fs from "fs/promises"; +import { BaseToolWithCall, LlamaCloudIndex, QueryEngineTool } from "llamaindex"; +import path from "path"; +import { getDataSource } from "../engine"; +import { createTools } from "../engine/tools/index"; + +export const getQueryEngineTools = async ( + params?: any, +): Promise => { + const topK = process.env.TOP_K ? parseInt(process.env.TOP_K) : undefined; + + const index = await getDataSource(params); + if (!index) { + return null; + } + // index is LlamaCloudIndex use two query engine tools + if (index instanceof LlamaCloudIndex) { + return [ + new QueryEngineTool({ + queryEngine: index.asQueryEngine({ + similarityTopK: topK, + retrieval_mode: "files_via_content", + }), + metadata: { + name: "document_retriever", + description: `Document retriever that retrieves entire documents from the corpus. + ONLY use for research questions that may require searching over entire research reports. + Will be slower and more expensive than chunk-level retrieval but may be necessary.`, + }, + }), + new QueryEngineTool({ + queryEngine: index.asQueryEngine({ + similarityTopK: topK, + retrieval_mode: "chunks", + }), + metadata: { + name: "chunk_retriever", + description: `Retrieves a small set of relevant document chunks from the corpus. + Use for research questions that want to look up specific facts from the knowledge corpus, + and need entire documents.`, + }, + }), + ]; + } else { + return [ + new QueryEngineTool({ + queryEngine: (index as any).asQueryEngine({ + similarityTopK: topK, + }), + metadata: { + name: "retriever", + description: `Use this tool to retrieve information about the text corpus from the index.`, + }, + }), + ]; + } +}; + +export const getAvailableTools = async () => { + const configFile = path.join("config", "tools.json"); + let toolConfig: any; + const tools: BaseToolWithCall[] = []; + try { + toolConfig = JSON.parse(await fs.readFile(configFile, "utf8")); + } catch (e) { + console.info(`Could not read ${configFile} file. Using no tools.`); + } + if (toolConfig) { + tools.push(...(await createTools(toolConfig))); + } + const queryEngineTools = await getQueryEngineTools(); + if (queryEngineTools) { + tools.push(...queryEngineTools); + } + + return tools; +}; + +export const lookupTools = async ( + toolNames: string[], +): Promise => { + const availableTools = await getAvailableTools(); + return availableTools.filter((tool) => + toolNames.includes(tool.metadata.name), + ); +}; diff --git a/templates/types/streaming/nextjs/package.json b/templates/types/streaming/nextjs/package.json index 4153d7416..11063e1ff 100644 --- a/templates/types/streaming/nextjs/package.json +++ b/templates/types/streaming/nextjs/package.json @@ -12,7 +12,6 @@ "dependencies": { "@apidevtools/swagger-parser": "^10.1.0", "@e2b/code-interpreter": "0.0.9-beta.3", - "@llamaindex/core": "^0.2.6", "@llamaindex/pdf-viewer": "^1.1.3", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-hover-card": "^1.0.7", @@ -27,7 +26,7 @@ "duck-duck-scrape": "^2.2.5", "formdata-node": "^6.0.3", "got": "^14.4.1", - "llamaindex": "0.6.22", + "llamaindex": "0.7.7", "lucide-react": "^0.294.0", "next": "^14.2.4", "react": "^18.2.0", From 752f6ac355ce2158fe7fbeb6f8de25481c2dd3f3 Mon Sep 17 00:00:00 2001 From: Huu Le <39040748+leehuwuj@users.noreply.github.com> Date: Fri, 25 Oct 2024 11:47:08 +0700 Subject: [PATCH 2/9] Update templates/types/streaming/nextjs/package.json --- templates/types/streaming/nextjs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/types/streaming/nextjs/package.json b/templates/types/streaming/nextjs/package.json index 11063e1ff..090cfc31c 100644 --- a/templates/types/streaming/nextjs/package.json +++ b/templates/types/streaming/nextjs/package.json @@ -26,7 +26,7 @@ "duck-duck-scrape": "^2.2.5", "formdata-node": "^6.0.3", "got": "^14.4.1", - "llamaindex": "0.7.7", + "llamaindex": "0.7.10", "lucide-react": "^0.294.0", "next": "^14.2.4", "react": "^18.2.0", From a377482c7bfbb56da88cb5d8dc08fcc348568a11 Mon Sep 17 00:00:00 2001 From: leehuwuj Date: Fri, 25 Oct 2024 14:35:34 +0700 Subject: [PATCH 3/9] add changeset --- .changeset/little-jars-vanish.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/little-jars-vanish.md diff --git a/.changeset/little-jars-vanish.md b/.changeset/little-jars-vanish.md new file mode 100644 index 000000000..70159fa1a --- /dev/null +++ b/.changeset/little-jars-vanish.md @@ -0,0 +1,5 @@ +--- +"create-llama": patch +--- + +Add multi-agent financial report for Typescript From 2479a77f85460e2c7ba6ab3ebeceb135fb2137f3 Mon Sep 17 00:00:00 2001 From: leehuwuj Date: Fri, 25 Oct 2024 14:38:28 +0700 Subject: [PATCH 4/9] bump llamaindex for expressjs --- templates/types/streaming/express/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/types/streaming/express/package.json b/templates/types/streaming/express/package.json index ef5ae0bde..8d59ae7a8 100644 --- a/templates/types/streaming/express/package.json +++ b/templates/types/streaming/express/package.json @@ -15,13 +15,12 @@ "dev": "concurrently \"tsup index.ts --format esm --dts --watch\" \"nodemon --watch dist/index.js\"" }, "dependencies": { - "@llamaindex/core": "^0.2.6", "ai": "3.3.42", "cors": "^2.8.5", "dotenv": "^16.3.1", "duck-duck-scrape": "^2.2.5", "express": "^4.18.2", - "llamaindex": "0.6.22", + "llamaindex": "0.7.10", "pdf2json": "3.0.5", "ajv": "^8.12.0", "@e2b/code-interpreter": "0.0.9-beta.3", From 762ccc1b8200e03dabd814f1b748a5fc73b1ae64 Mon Sep 17 00:00:00 2001 From: Huu Le <39040748+leehuwuj@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:56:16 +0700 Subject: [PATCH 5/9] Update templates/components/agents/typescript/financial_report/agents.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../components/agents/typescript/financial_report/agents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/components/agents/typescript/financial_report/agents.ts b/templates/components/agents/typescript/financial_report/agents.ts index 101e074d5..13cf3cbd9 100644 --- a/templates/components/agents/typescript/financial_report/agents.ts +++ b/templates/components/agents/typescript/financial_report/agents.ts @@ -18,7 +18,7 @@ export const createResearcher = async ( systemPrompt: `You are a researcher agent. You are responsible for retrieving information from the corpus. ## Instructions: + Don't synthesize the information, just return the whole retrieved information. -+ Don't need to retrieve the information that is already provided in the chat history and response with: "There is no new information, please reuse the information from the conversation." ++ Don't need to retrieve the information that is already provided in the chat history and respond with: "There is no new information, please reuse the information from the conversation." `, chatHistory, }); From 70f23c71d416af4e3d65e3ac2f392646711343dc Mon Sep 17 00:00:00 2001 From: Huu Le <39040748+leehuwuj@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:56:28 +0700 Subject: [PATCH 6/9] Update templates/components/agents/typescript/financial_report/agents.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../components/agents/typescript/financial_report/agents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/components/agents/typescript/financial_report/agents.ts b/templates/components/agents/typescript/financial_report/agents.ts index 13cf3cbd9..f9b59e45a 100644 --- a/templates/components/agents/typescript/financial_report/agents.ts +++ b/templates/components/agents/typescript/financial_report/agents.ts @@ -28,7 +28,7 @@ export const createAnalyst = async (chatHistory: ChatMessage[]) => { let systemPrompt = `You are an expert in analyzing financial data. You are given a task and a set of financial data to analyze. Your task is to analyze the financial data and return a report. Your response should include a detailed analysis of the financial data, including any trends, patterns, or insights that you find. -Construct the analysis in a textual format like tables would be great! +Construct the analysis in textual format; including tables would be great! Don't need to synthesize the data, just analyze and provide your findings. Always use the provided information, don't make up any information yourself.`; const tools = await lookupTools(["interpreter"]); From 4f7cfa3567dd25126a711db1a164b73db6f82b5d Mon Sep 17 00:00:00 2001 From: Huu Le <39040748+leehuwuj@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:56:36 +0700 Subject: [PATCH 7/9] Update templates/components/agents/typescript/financial_report/agents.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../components/agents/typescript/financial_report/agents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/components/agents/typescript/financial_report/agents.ts b/templates/components/agents/typescript/financial_report/agents.ts index f9b59e45a..ca86aa5ff 100644 --- a/templates/components/agents/typescript/financial_report/agents.ts +++ b/templates/components/agents/typescript/financial_report/agents.ts @@ -35,7 +35,7 @@ Always use the provided information, don't make up any information yourself.`; if (tools.length > 0) { systemPrompt = `${systemPrompt} You are able to visualize the financial data using code interpreter tool. -It's very useful to create and include visualizations to the report. Never include any code into the report, just the visualization.`; +It's very useful to create and include visualizations in the report. Never include any code in the report, just the visualization.`; } return new FunctionCallingAgent({ name: "analyst", From cc9960464548ec41cfc684eed03e1f5f32633eca Mon Sep 17 00:00:00 2001 From: leehuwuj Date: Fri, 25 Oct 2024 15:54:14 +0700 Subject: [PATCH 8/9] update error log for tool call --- .../components/multiagent/typescript/workflow/single-agent.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/components/multiagent/typescript/workflow/single-agent.ts b/templates/components/multiagent/typescript/workflow/single-agent.ts index 5344f1089..c32ad82fd 100644 --- a/templates/components/multiagent/typescript/workflow/single-agent.ts +++ b/templates/components/multiagent/typescript/workflow/single-agent.ts @@ -182,7 +182,9 @@ export class FunctionCallingAgent extends Workflow { // TODO: make logger optional in callTool in framework const toolOutput = await callTool(targetTool, call, { log: () => {}, - error: console.error.bind(console), + error: (...args: unknown[]) => { + console.error(`[Tool ${call.name} Error]:`, ...args); + }, warn: () => {}, }); toolMsgs.push({ From e470a34eca62684e0f2e89fa4fa8ce197d6f604d Mon Sep 17 00:00:00 2001 From: Marcus Schiesser Date: Fri, 25 Oct 2024 16:44:23 +0700 Subject: [PATCH 9/9] Update .changeset/little-jars-vanish.md --- .changeset/little-jars-vanish.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/little-jars-vanish.md b/.changeset/little-jars-vanish.md index 70159fa1a..e9fe18ff8 100644 --- a/.changeset/little-jars-vanish.md +++ b/.changeset/little-jars-vanish.md @@ -2,4 +2,4 @@ "create-llama": patch --- -Add multi-agent financial report for Typescript +Add multi-agent financial report for Typescript (and update LITS to 0.7.10)