### Installing Dependencies (npm) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/cookbook/pocketflow-batch-node/README.md Installs the necessary project dependencies using the npm package manager. ```bash npm install ``` -------------------------------- ### Installing Dependencies (npm) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/cookbook/pocketflow-batch-flow/README.md Installs the project dependencies listed in the package.json file using the npm package manager. ```bash npm install ``` -------------------------------- ### Running the Example (npm) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/cookbook/pocketflow-batch-node/README.md Executes the main script of the PocketFlow BatchNode example project. ```bash npm run main ``` -------------------------------- ### Running the Example (npm) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/cookbook/pocketflow-batch-flow/README.md Executes the main script of the example project, typically defined in the package.json scripts section. ```bash npm run main ``` -------------------------------- ### Run the Parallel Image Processor (Bash) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/cookbook/pocketflow-parallel-batch-flow/README.md These commands install the necessary project dependencies and then start the image processing application. ```bash npm install npm run start ``` -------------------------------- ### Creating and Running a Simple Sequence Flow Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/core_abstraction/flow.md Provides a minimal example demonstrating how to define a simple two-node sequence using 'next()', initialize a Flow with a start node, and run the flow using the 'run()' method with shared context. ```typescript nodeA.next(nodeB); const flow = new Flow(nodeA); flow.run(shared); ``` -------------------------------- ### Complete Node Implementation Example (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/core_abstraction/node.md A comprehensive example demonstrating how to define a custom Node subclass (`SummarizeFile`) with implementations for the `prep`, `exec`, `post`, and `execFallback` methods, showcasing the typical structure and flow of a Node. Includes a type definition for the shared store and example usage. ```TypeScript type SharedStore = { data: string; summary?: string; }; class SummarizeFile extends Node { prep(shared: SharedStore): string { return shared.data; } exec(content: string): string { if (!content) return "Empty file content"; const prompt = `Summarize this text in 10 words: ${content}`; return callLlm(prompt); } execFallback(_: string, error: Error): string { return "There was an error processing your request."; } post(shared: SharedStore, _: string, summary: string): string | undefined { shared.summary = summary; return undefined; // "default" action } } // Example usage const node = new SummarizeFile(3); // maxRetries = 3 const shared: SharedStore = { data: "Long text to summarize..." }; const action = node.run(shared); console.log("Action:", action); console.log("Summary:", shared.summary); ``` -------------------------------- ### Running PocketFlow Application - TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/guide.md Serves as the main entry point for the application. It defines an asynchronous `main` function that initializes the shared state object, calls `createQaFlow` to get the flow instance, runs the flow using `qaFlow.run(shared)`, and finally prints the question and answer stored in the shared state after the flow completes. ```typescript import { createQaFlow } from "./flow"; import { QASharedStore } from "./types"; // Example main function async function main(): Promise { const shared: QASharedStore = { question: undefined, // Will be populated by GetQuestionNode from user input answer: undefined, // Will be populated by AnswerNode }; // Create the flow and run it const qaFlow = createQaFlow(); await qaFlow.run(shared); console.log(`Question: ${shared.question}`); console.log(`Answer: ${shared.answer}`); } // Run the main function main().catch(console.error); ``` -------------------------------- ### Setting up Development Environment - PocketFlow-Typescript - Bash Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/README.md Provides the necessary commands to clone the repository, install project dependencies, and run the test suite for the PocketFlow-Typescript project. ```bash # Clone your forked repository git clone https://github.com/yourusername/PocketFlow-Typescript.git cd PocketFlow-Typescript # Install dependencies npm install # Run tests npm test ``` -------------------------------- ### Install Project Dependencies for Testing Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/README.md Navigates to the project directory and installs all required development and production dependencies listed in the package.json file, necessary before running tests. ```bash npm install ``` -------------------------------- ### Install PocketFlow.js via npm Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/README.md Installs the PocketFlow.js library globally or locally using the npm package manager, making it available for use in your project. ```bash npm install pocketflow ``` -------------------------------- ### Defining and Initializing Shared Store (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/guide.md This code defines a TypeScript interface for a `SharedStore` object, which is used for inter-node communication in PocketFlow. It also provides an example initialization of a `shared` object conforming to this interface, demonstrating how user context and results can be structured. This store acts as a central data repository for the flow. ```TypeScript interface SharedStore { user: { id: string; context: { weather: { temp: number; condition: string }; location: string; }; }; results: Record; } const shared: SharedStore = { user: { id: "user123", context: { weather: { temp: 72, condition: "sunny" }, location: "San Francisco", }, }, results: {}, // Empty object to store outputs }; ``` -------------------------------- ### Installing Dependencies - Bash Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/CONTRIBUTING.md Installs all necessary project dependencies listed in the package.json file using npm. ```Bash npm install ``` -------------------------------- ### Install Mermaid Library (Bash) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md Provides commands to install the Mermaid JavaScript library using npm, yarn, or pnpm package managers. This is a prerequisite for using Mermaid in a project. ```bash npm install mermaid # or yarn add mermaid # or pnpm add mermaid ``` -------------------------------- ### Example Product Structure YAML Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/design_pattern/structure.md Demonstrates a simple YAML structure for representing product information, including name, price, and a multi-line description using the literal block scalar. ```yaml product: name: Widget Pro price: 199.99 description: | A high-quality widget designed for professionals. Recommended for advanced users. ``` -------------------------------- ### Shared Store Example with Nodes and Flow Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/core_abstraction/communication.md Illustrates how nodes read from and write to the Shared Store within `prep` and `post` methods, and how a Flow is constructed and run using the Shared Store. ```typescript interface SharedStore { data: string; summary: string; } class LoadData extends Node { async post( shared: SharedStore, prepRes: unknown, execRes: unknown ): Promise { // We write data to shared store shared.data = "Some text content"; return "default"; } } class Summarize extends Node { async prep(shared: SharedStore): Promise { // We read data from shared store return shared.data; } async exec(prepRes: unknown): Promise { // Call LLM to summarize const prompt = `Summarize: ${prepRes}`; const summary = await callLlm(prompt); return summary; } async post( shared: SharedStore, prepRes: unknown, execRes: unknown ): Promise { // We write summary to shared store shared.summary = execRes as string; return "default"; } } const loadData = new LoadData(); const summarize = new Summarize(); loadData.next(summarize); const flow = new Flow(loadData); const shared: SharedStore = { data: "", summary: "" }; flow.run(shared); ``` -------------------------------- ### Example Flow with Custom Nodes and Stack Inspection (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md Provides a full example demonstrating the creation and linking of various custom nodes and flows, including a node (`EvaluateModelNode`) that utilizes the `getNodeCallStack` function to print the node call stack during its execution. ```typescript import { BaseNode, BatchNode, Node, Flow } from "../src/index"; class DataPrepBatchNode extends BatchNode { prep(shared: any): any[] { return []; } } class ValidateDataNode extends Node {} class FeatureExtractionNode extends Node {} class TrainModelNode extends Node {} class EvaluateModelNode extends Node { prep(shared: any): void { const stack = getNodeCallStack(); console.log("Call stack:", stack); } } class ModelFlow extends Flow {} class DataScienceFlow extends Flow {} const featureNode = new FeatureExtractionNode(); const trainNode = new TrainModelNode(); const evaluateNode = new EvaluateModelNode(); featureNode.next(trainNode); trainNode.next(evaluateNode); const modelFlow = new ModelFlow(featureNode); const dataPrepNode = new DataPrepBatchNode(); const validateNode = new ValidateDataNode(); dataPrepNode.next(validateNode); validateNode.next(modelFlow); const dataScienceFlow = new DataScienceFlow(dataPrepNode); dataScienceFlow.run({}); ``` -------------------------------- ### Using FAISS for Vector Search in TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/vector.md Demonstrates how to initialize a FAISS index using `faiss-node`, add random vectors, and perform a basic search. Requires the `faiss-node` library installed. ```typescript import { IndexFlatL2 } from "faiss-node"; // Dimensionality of embeddings const dimension = 128; // Create a flat L2 index const index = new IndexFlatL2(dimension); // Create random vectors (using standard JS arrays) const data: number[] = []; for (let i = 0; i < 1000; i++) { for (let j = 0; j < dimension; j++) { data.push(Math.random()); } } // Add vectors to the index for (let i = 0; i < 1000; i++) { const vector = data.slice(i * dimension, (i + 1) * dimension); index.add(vector); } // Query const query = Array(dimension) .fill(0) .map(() => Math.random()); const results = index.search(query, 5); console.log("Distances:", results.distances); console.log("Neighbors:", results.labels); ``` -------------------------------- ### Implementing PocketFlow Nodes - TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/guide.md Implements two PocketFlow nodes, `GetQuestionNode` and `AnswerNode`, which extend the base `Node` class. `GetQuestionNode` interacts with the user to get input, while `AnswerNode` uses a utility function (`callLlm`) to process the question and stores the result in the shared state. These nodes define the core logic steps within the flow. ```typescript import { Node } from "pocketflow"; import { callLlm } from "./utils/callLlm"; import { QASharedStore } from "./types"; import PromptSync from "prompt-sync"; const prompt = PromptSync(); export class GetQuestionNode extends Node { async exec(): Promise { // Get question directly from user input const userQuestion = prompt("Enter your question: ") || ""; return userQuestion; } async post( shared: QASharedStore, _: unknown, execRes: string ): Promise { // Store the user's question shared.question = execRes; return "default"; // Go to the next node } } export class AnswerNode extends Node { async prep(shared: QASharedStore): Promise { // Read question from shared return shared.question || ""; } async exec(question: string): Promise { // Call LLM to get the answer return await callLlm(question); } async post( shared: QASharedStore, _: unknown, execRes: string ): Promise { // Store the answer in shared shared.answer = execRes; return undefined; } } ``` -------------------------------- ### Calling OpenAI LLM in TypeScript Utility Function Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/guide.md Implements a utility function `callLlm` in TypeScript to interact with the OpenAI API. It takes a prompt string, uses the `gpt-4o` model, and initiates a chat completion request, serving as an example of an external tool integration. ```typescript // src/utils/callLlm.ts import { OpenAI } from "openai"; export async function callLlm(prompt: string): Promise { const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); const response = await client.chat.completions.create({ model: "gpt-4o", messages: [{ role: "user", content: prompt }], }); ``` -------------------------------- ### Outlining AI System Flow with Mermaid Diagram Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/guide.md Illustrates a simple flowchart using Mermaid syntax to visualize the high-level steps and branching logic within an AI system's process flow, demonstrating the structure derived during the flow design phase. ```mermaid flowchart LR start[Start] --> batch[Batch] batch --> check[Check] check -->|OK| process check -->|Error| fix[Fix] fix --> check subgraph process[Process] step1[Step 1] --> step2[Step 2] end process --> endNode[End] ``` -------------------------------- ### Example Summary Structure YAML Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/design_pattern/structure.md Shows a YAML structure for representing a list of summary points using a sequence (array) under a 'summary' key. ```yaml summary: - This product is easy to use. - It is cost-effective. - Suitable for all skill levels. ``` -------------------------------- ### Calling Azure OpenAI LLM in TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/llm.md Provides an example of using the 'openai' library configured for Azure OpenAI. It requires an API key, API version, and endpoint URL. It sends a user prompt to a specified deployment model. ```TypeScript import { AzureOpenAI } from "openai"; async function callLlm(prompt: string): Promise { const client = new AzureOpenAI({ apiKey: "YOUR_API_KEY_HERE", azure: { apiVersion: "2023-05-15", endpoint: "https://.openai.azure.com/" } }); const r = await client.chat.completions.create({ model: "", messages: [{ role: "user", content: prompt }] }); return r.choices[0].message.content || ""; } ``` -------------------------------- ### Performing SerpApi Search with SDK (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/websearch.md Defines a TypeScript interface `SerpApiResult` for the expected response structure from SerpApi. It also defines an asynchronous function `serpApiSearch` to perform a search using the SerpApi SDK, taking query, API key, and optional location, number of results, and start index. The example usage demonstrates calling the function and logging the total results and organic search results. ```typescript // Using the official SerpApi SDK import { getJson } from "serpapi"; interface SerpApiResult { search_metadata: { id: string; status: string; json_endpoint: string; created_at: string; processed_at: string; google_url: string; raw_html_file: string; total_time_taken: number; }; search_parameters: { engine: string; q: string; location_requested: string; location_used: string; google_domain: string; hl: string; gl: string; device: string; }; search_information: { organic_results_state: string; query_displayed: string; total_results: number; time_taken_displayed: number; }; organic_results: Array<{ position: number; title: string; link: string; displayed_link: string; snippet: string; snippet_highlighted_words: string[]; sitelinks?: any; about_this_result?: any; cached_page_link?: string; related_pages_link?: string; }>; related_questions?: any[]; related_searches?: any[]; pagination?: any; knowledge_graph?: any; answer_box?: any; } /** * Perform a search using the SerpApi SDK */ async function serpApiSearch( query: string, apiKey: string, location: string = "United States", num: number = 10, start: number = 0 ): Promise { try { // Make the search request using the SDK return (await getJson({ engine: "google", api_key: apiKey, q: query, location, num, start, })) as SerpApiResult; } catch (error) { console.error("Error performing SerpApi search:", error); throw error; } } // Example usage const SERPAPI_KEY = "YOUR_SERPAPI_KEY"; serpApiSearch("electric vehicles", SERPAPI_KEY) .then((response) => { console.log(`Total Results: ${response.search_information.total_results}`); console.log("Organic Results:"); response.organic_results.forEach((result, index) => { console.log(`${index + 1}. ${result.title}`); console.log(` URL: ${result.link}`); console.log(` ${result.snippet}`); console.log("---"); }); if (response.pagination) { console.log("Pagination available for more results"); } }) .catch((error) => { console.error("Search failed:", error); }); ``` -------------------------------- ### Example PocketFlow Graph Definition for Mermaid (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md Demonstrates how to define a complex PocketFlow graph using custom Node and Flow classes and then uses the `buildMermaid` function to generate the corresponding Mermaid syntax. ```typescript import { BaseNode, BatchNode, Node, Flow } from "../src/index"; class DataPrepBatchNode extends BatchNode { prep(shared: any): any[] { return []; } } class ValidateDataNode extends Node {} class FeatureExtractionNode extends Node {} class TrainModelNode extends Node {} class EvaluateModelNode extends Node {} class ModelFlow extends Flow {} class DataScienceFlow extends Flow {} const featureNode = new FeatureExtractionNode(); const trainNode = new TrainModelNode(); const evaluateNode = new EvaluateModelNode(); featureNode.next(trainNode); trainNode.next(evaluateNode); const modelFlow = new ModelFlow(featureNode); const dataPrepNode = new DataPrepBatchNode(); const validateNode = new ValidateDataNode(); dataPrepNode.next(validateNode); validateNode.next(modelFlow); const dataScienceFlow = new DataScienceFlow(dataPrepNode); const result = buildMermaid(dataScienceFlow); ``` -------------------------------- ### Creating PocketFlow Sequence - TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/guide.md Defines a function, `createQaFlow`, that constructs a PocketFlow `Flow` instance. It instantiates the previously defined nodes (`GetQuestionNode`, `AnswerNode`) and connects them sequentially using the `.next()` method, establishing the execution path for the question-answering process. ```typescript import { Flow } from "pocketflow"; import { GetQuestionNode, AnswerNode } from "./nodes"; import { QASharedStore } from "./types"; export function createQaFlow(): Flow { // Create nodes const getQuestionNode = new GetQuestionNode(); const answerNode = new AnswerNode(); // Connect nodes in sequence getQuestionNode.next(answerNode); // Create flow starting with input node return new Flow(getQuestionNode); } ``` -------------------------------- ### Params Example with Node and Flow Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/core_abstraction/communication.md Demonstrates using immutable parameters (`_params`) within a node and how parameters are set on both nodes and flows, showing flow parameters override node parameters. Includes necessary interface definitions. ```typescript interface SharedStore { data: Record; summary: Record; } interface SummarizeParams { filename: string; } // 1) Create a Node that uses params class SummarizeFile extends Node { async prep(shared: SharedStore): Promise { // Access the node's param const filename = this._params.filename; return shared.data[filename] || ""; } async exec(prepRes: unknown): Promise { const prompt = `Summarize: ${prepRes}`; return await callLlm(prompt); } async post( shared: SharedStore, prepRes: unknown, execRes: unknown ): Promise { const filename = this._params.filename; shared.summary[filename] = execRes as string; return "default"; } } // 2) Set params const node = new SummarizeFile(); // 3) Set Node params directly (for testing) node.setParams({ filename: "doc1.txt" }); node.run(shared); // 4) Create Flow const flow = new Flow(node); // 5) Set Flow params (overwrites node params) flow.setParams({ filename: "doc2.txt" }); flow.run(shared); // The node summarizes doc2, not doc1 ``` -------------------------------- ### Enable 'debug' Logging via Environment Variable (Bash) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md Shows examples of how to enable or filter logging output from the 'debug' library by setting the `DEBUG` environment variable when running a Node.js application. ```bash # Enable all flow debugging DEBUG=flow:* node your-app.js # Enable only specific parts DEBUG=flow:prep,flow:post node your-app.js ``` -------------------------------- ### Defining Branching and Looping Flow Connections Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/core_abstraction/flow.md Illustrates how to define transitions using 'on()' and 'next()' to create branching and looping logic, using an expense approval flow example with different actions leading to different paths or loops. ```typescript // Define the flow connections review.on("approved", payment); // If approved, process payment review.on("needs_revision", revise); // If needs changes, go to revision review.on("rejected", finish); // If rejected, finish the process revise.next(review); // After revision, go back for another review payment.next(finish); // After payment, finish the process const flow = new Flow(review); ``` -------------------------------- ### Running the Offline RAG Flow - TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/design_pattern/rag.md Provides a simple example of how to initialize the shared state with input files and execute the defined offline RAG flow to process and index the documents. ```typescript const shared = { files: ["doc1.txt", "doc2.txt"], // any text files }; await offlineFlow.run(shared); ``` -------------------------------- ### Generated Mermaid Diagram for Data Science Flow Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md The Mermaid syntax output generated by the `buildMermaid` function for the example Data Science Flow graph, suitable for rendering a hierarchical visualization. ```mermaid graph LR subgraph sub_flow_N1[DataScienceFlow] N2['DataPrepBatchNode'] N3['ValidateDataNode'] N2 --> N3 N3 --> N4 subgraph sub_flow_N5[ModelFlow] N4['FeatureExtractionNode'] N6['TrainModelNode'] N4 --> N6 N7['EvaluateModelNode'] N6 --> N7 end end ``` -------------------------------- ### Initializing Chroma Client and Performing Operations in TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/vector.md This snippet illustrates how to connect to a Chroma server, create or get a collection, add data with embeddings and metadata, and perform a vector query using the ChromaDB client for TypeScript. ```typescript import { ChromaClient, Collection } from "chromadb"; const init = async () => { const client = new ChromaClient({ path: "http://localhost:8000", // Default path if using chroma server }); // Create or get collection const collection: Collection = await client.createCollection({ name: "my_collection", // Optional metadata metadata: { description: "My test collection" }, }); // Add vectors await collection.add({ ids: ["id1", "id2"], embeddings: [ [0.1, 0.2, 0.3], [0.2, 0.2, 0.2], ], metadatas: [{ doc: "text1" }, { doc: "text2" }], }); // Query const result = await collection.query({ queryEmbeddings: [[0.15, 0.25, 0.3]], nResults: 2, }); console.log(result); }; init(); ``` -------------------------------- ### Initialize Game State and Hinter Queue - TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/design_pattern/multi_agent.md Logs the list of forbidden words to the console and pushes an initial empty string onto the shared hinter queue to signal the start of the hint generation process. ```TypeScript console.log(`Forbidden words: ${shared.forbiddenWords.join(", ")}`); // Initialize by sending empty guess to hinter shared.hinterQueue.push(""); ``` -------------------------------- ### Render Mermaid Diagram in Browser (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md Provides a TypeScript example showing how to use `mermaid.render` in a web browser environment. It takes a generated diagram definition string and renders it as SVG into a specified DOM element. ```typescript // In a web context const element = document.querySelector("#diagram"); mermaid.render("diagram-id", diagramDefinition, (svgCode) => { element.innerHTML = svgCode; }); ``` -------------------------------- ### Implementing Search Agent with PocketFlow Nodes (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/design_pattern/agent.md Provides a complete example of a Search Agent implemented using PocketFlow's Node and Flow abstractions. It defines a shared state interface and three Node classes: DecideAction (determines whether to search or answer), SearchWeb (performs the search), and DirectAnswer (generates the final answer). It demonstrates how to connect these nodes to create a flow, including a loop for iterative searching, and how to run the flow with initial input. ```TypeScript interface SharedState { query?: string; context?: Array<{ term: string; result: string }>; search_term?: string; answer?: string; } class DecideAction extends Node { async prep(shared: SharedState): Promise<[string, string]> { const context = shared.context ? JSON.stringify(shared.context) : "No previous search"; return [shared.query || "", context]; } async exec([query, context]: [string, string]): Promise { const prompt = ` Given input: ${query} Previous search results: ${context} Should I: 1) Search web for more info 2) Answer with current knowledge Output in yaml: ```yaml action: search/answer reason: why this action search_term: search phrase if action is search ````; const resp = await callLlm(prompt); const yamlStr = resp.split("```yaml")[1].split("```")[0].trim(); return yaml.load(yamlStr); } async post( shared: SharedState, _: [string, string], result: any ): Promise { if (result.action === "search") { shared.search_term = result.search_term; } return result.action; } } class SearchWeb extends Node { async prep(shared: SharedState): Promise { return shared.search_term || ""; } async exec(searchTerm: string): Promise { return await searchWeb(searchTerm); } async post(shared: SharedState, _: string, execRes: string): Promise { shared.context = [ ...(shared.context || []), { term: shared.search_term || "", result: execRes }, ]; return "decide"; } } class DirectAnswer extends Node { async prep(shared: SharedState): Promise<[string, string]> { return [ shared.query || "", shared.context ? JSON.stringify(shared.context) : "", ]; } async exec([query, context]: [string, string]): Promise { return await callLlm(`Context: ${context}\nAnswer: ${query}`); } async post( shared: SharedState, _: [string, string], execRes: string ): Promise { shared.answer = execRes; return undefined; } } // Connect nodes const decide = new DecideAction(); const search = new SearchWeb(); const answer = new DirectAnswer(); decide.on("search", search); decide.on("answer", answer); search.on("decide", decide); // Loop back const flow = new Flow(decide); await flow.run({ query: "Who won the Nobel Prize in Physics 2024?" }); ``` -------------------------------- ### Performing Brave Search with SDK (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/websearch.md Defines an asynchronous function `braveSearchWithSDK` to perform a web search using the Brave Search SDK. It takes the search query, API key, and optional count and offset parameters. The example usage demonstrates calling the function and logging the web results and potential automatic summarization. ```typescript // Using brave-search TypeScript SDK import { BraveSearch } from "brave-search"; /** * Perform a Brave Search using the brave-search SDK */ async function braveSearchWithSDK( query: string, apiKey: string, count: number = 10, offset: number = 0 ) { // Initialize the Brave Search client const braveClient = new BraveSearch(apiKey); try { // Make the search request const results = await braveClient.search({ q: query, count, offset, }); return results; } catch (error) { console.error("Error performing Brave search:", error); throw error; } } // Example usage const BRAVE_API_TOKEN = "YOUR_BRAVE_API_TOKEN"; braveSearchWithSDK("renewable energy", BRAVE_API_TOKEN) .then((results) => { console.log("Search Results:"); // Access the web results if (results.web && results.web.results) { results.web.results.forEach((result, index) => { console.log(`${index + 1}. ${result.title}`); console.log(` URL: ${result.url}`); console.log(` ${result.description}`); console.log("---"); }); } // Check if automatic summarization is available (Pro plan feature) if (results.goggles) { console.log("Automatic Summarization:"); console.log(results.goggles.content); } }) .catch((error) => { console.error("Search failed:", error); }); ``` -------------------------------- ### Building an Order Processing Pipeline with Nested Flows (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/core_abstraction/flow.md Provides a practical example of structuring a complex process like order processing into distinct, nested flows (payment, inventory, shipping) and connecting them sequentially within a master pipeline. ```typescript // Payment processing sub-flow validatePayment.next(processPayment).next(paymentConfirmation); const paymentFlow = new Flow(validatePayment); // Inventory sub-flow checkStock.next(reserveItems).next(updateInventory); const inventoryFlow = new Flow(checkStock); // Shipping sub-flow createLabel.next(assignCarrier).next(schedulePickup); const shippingFlow = new Flow(createLabel); // Connect the flows into a main order pipeline paymentFlow.next(inventoryFlow).next(shippingFlow); // Create the master flow const orderPipeline = new Flow(paymentFlow); // Run the entire pipeline orderPipeline.run(sharedData); ``` -------------------------------- ### Generate Mermaid Diagram from PocketFlow Graph (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md Provides a custom function `buildMermaid` that recursively traverses a PocketFlow graph (starting from a BaseNode), assigns unique IDs to nodes, handles Flow nodes as subgraphs, and generates a string formatted for Mermaid visualization. ```typescript import { BaseNode, Flow } from "../src/index"; type NodeIds = Map; function buildMermaid(start: BaseNode): string { const ids: NodeIds = new Map(); const visited: Set = new Set(); const lines: string[] = ["graph LR"]; let ctr = 1; function getId(node: BaseNode): string { if (ids.has(node)) { return ids.get(node)!; } const id = `N${ctr++}`; ids.set(node, id); return id; } function link(a: string, b: string): void { lines.push(` ${a} --> ${b}`); } function walk(node: BaseNode, parent?: string): void { if (visited.has(node)) { if (parent) link(parent, getId(node)); return; } visited.add(node); if (node instanceof Flow) { if (node.start && parent) { link(parent, getId(node.start)); } lines.push( `\n subgraph sub_flow_${getId(node)}[${node.constructor.name}]` ); if (node.start) { walk(node.start); } // Get all successors from the node's internal map const successors = Array.from((node as any)._successors.entries()); for (const [_, nextNode] of successors) { if (node.start) { walk(nextNode, getId(node.start)); } else if (parent) { link(parent, getId(nextNode)); } else { walk(nextNode); } } lines.push(" end\n"); } else { const nodeId = getId(node); lines.push(` ${nodeId}['${node.constructor.name}']`); if (parent) { link(parent, nodeId); } // Get all successors from the node's internal map const successors = Array.from((node as any)._successors.entries()); for (const [_, nextNode] of successors) { walk(nextNode, nodeId); } Kristin } } walk(start); return lines.join("\n"); } ``` -------------------------------- ### Returning LLM Response Content (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/guide.md This snippet demonstrates how to extract the content from the first message choice in an LLM response object, providing a default empty string if the content is null or undefined. It's typically used to get the generated text from an LLM call. ```TypeScript return response.choices[0].message.content || ""; ``` -------------------------------- ### Create New PocketFlow Project Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/README.md Uses the npx command runner to execute the create-pocketflow package, which scaffolds a new project directory with a basic PocketFlow structure. ```bash npx create-pocketflow ``` -------------------------------- ### Instantiating Node with Retries and Wait (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/core_abstraction/node.md Demonstrates creating an instance of a Node subclass, specifying the maximum number of retries and the waiting time between retries for the `exec` step. ```TypeScript const myNode = new SummarizeFile(3, 10); // maxRetries = 3, wait = 10 seconds ``` -------------------------------- ### Getting Embeddings with Jina (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/embedding.md Explains how to get text embeddings from the Jina AI API using an HTTP POST request with Axios. It constructs the API URL, sets authorization headers with a token, prepares the request payload with the model and input text, sends the request, and extracts the embedding from the JSON response. Requires axios. ```typescript import axios from "axios"; async function getEmbedding(text: string) { const url = "https://api.jina.ai/v1/embeddings"; const headers = { Authorization: `Bearer YOUR_JINA_TOKEN`, "Content-Type": "application/json", }; const payload = { model: "jina-embeddings-v3", input: [text], normalized: true, }; const response = await axios.post(url, payload, { headers }); const embedding = response.data.data[0].embedding; console.log(embedding); return embedding; } // Usage getEmbedding("Hello world"); ``` -------------------------------- ### Implement Debugging with 'debug' Library (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/viz.md Demonstrates how to integrate the 'debug' library into a custom node by overriding the `prep`, `exec`, and `post` methods to log entry and exit points with context. ```typescript import debug from "debug"; // npm install debug import { BaseNode } from "../src/index"; // Create debuggers for different aspects of your application const prepDebug = debug("flow:prep"); const execDebug = debug("flow:exec"); const postDebug = debug("flow:post"); class DebuggableNode extends BaseNode { async prep(shared: any): Promise { prepDebug(`${this.constructor.name} prep started with shared:`, shared); const result = await super.prep(shared); prepDebug(`${this.constructor.name} prep completed with result:`, result); return result; } async exec(prepRes: any): Promise { execDebug(`${this.constructor.name} exec started with:`, prepRes); const result = await super.exec(prepRes); execDebug(`${this.constructor.name} exec completed with:`, result); return result; } async post( shared: any, prepRes: any, execRes: any ): Promise { postDebug(`${this.constructor.name} post started`); const result = await super.post(shared, prepRes, execRes); postDebug(`${this.constructor.name} post completed with action:`, result); return result; } } ``` -------------------------------- ### JSON Dialogue Escaping Example Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/design_pattern/structure.md Illustrates how multi-line strings and special characters like double quotes and newlines must be explicitly escaped within a JSON string value. ```json { "dialogue": "Alice said: \"Hello Bob.\nHow are you?\nI am good.\"" } ``` -------------------------------- ### Initializing Weaviate Client and Performing Operations in TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/vector.md This snippet demonstrates how to connect to a Weaviate instance, create a schema, add data with a vector, and perform a vector search using the Weaviate client library for TypeScript. ```typescript import weaviate from "weaviate-client"; const init = async () => { // Connect to Weaviate const client = weaviate.client({ scheme: "https", host: "YOUR-WEAVIATE-CLOUD-ENDPOINT", }); // Create schema const schema = { classes: [ { class: "Article", vectorizer: "none", }, ], }; await client.schema.create(schema); // Add data await client.data .creator() .withClassName("Article") .withProperties({ title: "Hello World", content: "Weaviate vector search", }) .withVector(Array(128).fill(0.1)) .do(); // Query const result = await client.graphql .get() .withClassName("Article") .withFields(["title", "content"]) .withNearVector({ vector: Array(128).fill(0.15), }) .withLimit(3) .do(); console.log(result); }; init(); ``` -------------------------------- ### Generating Speech with ElevenLabs in TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/text_to_speech.md Illustrates how to use the elevenlabs SDK to generate speech from text. It shows how to initialize the client with an API key, specify a voice ID and text, configure voice settings (stability, similarity boost), and save the resulting audio buffer to a file. Requires the elevenlabs and fs modules. ```TypeScript import { ElevenLabs } from "elevenlabs"; import { writeFileSync } from "fs"; async function synthesizeText() { // Initialize the ElevenLabs client const eleven = new ElevenLabs({ apiKey: "ELEVENLABS_KEY", }); try { // Generate speech const voiceId = "ELEVENLABS_VOICE_ID"; const text = "Hello from ElevenLabs!"; // Generate audio const audioResponse = await eleven.generate({ voice: voiceId, text: text, model_id: "eleven_monolingual_v1", voice_settings: { stability: 0.75, similarity_boost: 0.75, }, }); // Convert to buffer and save to file const audioBuffer = Buffer.from(await audioResponse.arrayBuffer()); writeFileSync("elevenlabs.mp3", audioBuffer); console.log("Audio content written to file: elevenlabs.mp3"); } catch (error) { console.error("Error:", error); } } synthesizeText(); ``` -------------------------------- ### Create Feature Branch (Git) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/README.md Creates a new Git branch named 'feature/amazing-feature' and immediately switches to it, isolating development for a new feature. ```bash git checkout -b feature/amazing-feature ``` -------------------------------- ### Run Project Tests Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/README.md Executes the predefined test script within the project's package.json file, running the automated test suite to verify functionality. ```bash npm test ``` -------------------------------- ### Handling Chat History in LLM Wrapper (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/llm.md Demonstrates how to modify the LLM wrapper function to accept an array of messages representing the conversation history, allowing for multi-turn interactions. Uses the OpenAI library as an example. ```TypeScript interface Message { role: "user" | "assistant" | "system"; content: string; } async function callLlm(messages: Message[]): Promise { const client = new OpenAI({ apiKey: "YOUR_API_KEY_HERE" }); const r = await client.chat.completions.create({ model: "gpt-4o", messages: messages, }); return r.choices[0].message.content || ""; } ``` -------------------------------- ### YAML Dialogue Literal Block Example Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/design_pattern/structure.md Shows how YAML can represent multi-line strings more easily than JSON using the literal block scalar (|), avoiding the need for explicit newline escaping within the string value itself. ```yaml dialogue: | Alice said: "Hello Bob. How are you. I am good." ``` -------------------------------- ### Using Qdrant for Vector Search in TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/vector.md Illustrates how to initialize the Qdrant client, create or recreate a collection, insert points with vectors and payload, and perform a vector search. Requires the `@qdrant/js-client-rest` library and Qdrant cloud endpoint/API key. ```typescript import { QdrantClient } from "@qdrant/js-client-rest"; const init = async () => { const client = new QdrantClient({ url: "https://YOUR-QDRANT-CLOUD-ENDPOINT", apiKey: "YOUR_API_KEY", }); const collectionName = "my_collection"; // Create or recreate collection await client.recreateCollection(collectionName, { vectors: { size: 128, distance: "Cosine", }, }); // Insert points await client.upsert(collectionName, { wait: true, points: [ { id: "1", vector: Array(128).fill(0.1), payload: { type: "doc1" }, }, { id: "2", vector: Array(128).fill(0.2), payload: { type: "doc2" }, }, ], }); // Search const searchResult = await client.search(collectionName, { vector: Array(128).fill(0.15), limit: 2, }); console.log(searchResult); }; init(); ``` -------------------------------- ### Generating Embeddings with Google Vertex AI (TypeScript) Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/embedding.md Illustrates how to get text embeddings from Google Cloud's Vertex AI using the TypeScript client library. Requires initializing with your GCP project ID and location. ```typescript import { VertexAI } from "@google-cloud/vertexai"; // Initialize Vertex with your Google Cloud project and location const vertex = new VertexAI({ project: "YOUR_GCP_PROJECT_ID", location: "us-central1", }); // Access embeddings model const model = vertex.preview.getTextEmbeddingModel("textembedding-gecko@001"); async function getEmbedding(text: string) { const response = await model.getEmbeddings({ texts: [text], }); const embedding = response.embeddings[0].values; console.log(embedding); return embedding; } // Usage getEmbedding("Hello world"); ``` -------------------------------- ### Initializing Milvus Client and Performing Operations in TypeScript Source: https://github.com/the-pocket/pocketflow-typescript/blob/main/docs/utility_function/vector.md This snippet shows how to connect to a Milvus instance, create a collection with a vector field, insert data, create an index, load the collection into memory, and perform a vector search using the Milvus SDK for Node.js. ```typescript import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node"; const init = async () => { // Connect to Milvus const client = new MilvusClient("localhost:19530"); // Wait for connection to be established await client.connectPromise; const collectionName = "MyCollection"; // Create collection await client.createCollection({ collection_name: collectionName, fields: [ { name: "id", data_type: DataType.Int64, is_primary_key: true, autoID: true, }, { name: "embedding", data_type: DataType.FloatVector, dim: 128, }, ], }); // Create random vectors const vectors = []; for (let i = 0; i < 10; i++) { vectors.push( Array(128) .fill(0) .map(() => Math.random()) ); } // Insert data await client.insert({ collection_name: collectionName, fields_data: vectors.map((vector) => ({ embedding: vector, })), }); // Create index await client.createIndex({ collection_name: collectionName, field_name: "embedding", extra_params: { index_type: "IVF_FLAT", metric_type: "L2", params: JSON.stringify({ nlist: 128 }), }, }); // Load collection to memory await client.loadCollection({ collection_name: collectionName, }); // Search const searchResult = await client.search({ collection_name: collectionName, vector: Array(128) .fill(0) .map(() => Math.random()), search_params: { anns_field: "embedding", topk: 3, metric_type: "L2", params: JSON.stringify({ nprobe: 10 }), }, }); console.log(searchResult); }; init(); ```