From c48f03edc557ff1ad1bd087923b984dcd5f4513a Mon Sep 17 00:00:00 2001 From: Ayush Thakur Date: Wed, 16 Oct 2024 01:41:48 +0530 Subject: [PATCH 1/2] Updated the README.md (#664) Have updated the whole `README.md` file and refined it ---- > [!IMPORTANT] > Refines `README.md` and `docs/README.md` with formatting improvements and content reorganization for clarity and consistency. > > - **Formatting**: > - Remove unnecessary whitespace in `README.md` and `docs/README.md`. > - Update markdown syntax for better readability and consistency. > - **Content Reorganization**: > - Reorganize sections for clarity and improved flow. > - Ensure consistent formatting and structure across both `README.md` files. > > This description was created by [Ellipsis](https://www.ellipsis.dev?ref=julep-ai%2Fjulep&utm_source=github&utm_medium=referral) for a9b38e273402b1e1f8bf43515748a9a4819f0ef5. It will automatically update as commits are pushed. --- README.md | 911 ++++++++++++++++++++++++++++++------------------- docs/README.md | 213 ++++++------ 2 files changed, 667 insertions(+), 457 deletions(-) diff --git a/README.md b/README.md index 42e93f685..a9d75d8a4 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ LinkedIn

-

NPM Version   @@ -26,11 +25,11 @@ GitHub License

-***** +--- > [!NOTE] -> πŸ‘¨β€πŸ’» Here for the devfest.ai event ? Join our [Discord](https://discord.com/invite/JTSBGRZrzj) and check out the details below. -> +> πŸ‘¨β€πŸ’» Here for the devfest.ai event? Join our [Discord](https://discord.com/invite/JTSBGRZrzj) and check out the details below. +> > Get your API key [here](https://dashboard-dev.julep.ai).
@@ -95,12 +94,6 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! πŸ—“ - [Built-in `integration`s](#built-in-integrations) - [Direct `api_call`s](#direct-api_calls) - [Integrations](#integrations) - - [Brave Search](#brave-search) - - [BrowserBase](#browserbase) - - [Email](#email) - - [Spider](#spider) - - [Weather](#weather) - - [Wikipedia](#wikipedia) - [Other Features](#other-features) - [Adding Tools to Agents](#adding-tools-to-agents) - [Managing Sessions and Users](#managing-sessions-and-users) @@ -121,6 +114,7 @@ Julep enables the creation of multi-step tasks incorporating decision-making, lo While many AI applications are limited to simple, linear chains of prompts and API calls with minimal branching, Julep is built to handle more complex scenarios. It supports: + - Intricate, multi-step processes - Dynamic decision-making - Parallel execution @@ -128,14 +122,27 @@ It supports: > [!TIP] > Imagine you want to build an AI agent that can do more than just answer simple questionsβ€”it needs to handle complex tasks, remember past interactions, and maybe even use other tools or APIs. That's where Julep comes in. +## Key Features + +1. 🧠 **Persistent AI Agents**: Remember context and information over long-term interactions. +2. πŸ’Ύ **Stateful Sessions**: Keep track of past interactions for personalized responses. +3. πŸ”„ **Multi-Step Tasks**: Build complex, multi-step processes with loops and decision-making. +4. ⏳ **Task Management**: Handle long-running tasks that can run indefinitely. +5. πŸ› οΈ **Built-in Tools**: Use built-in tools and external APIs in your tasks. +6. πŸ”§ **Self-Healing**: Julep will automatically retry failed steps, resend messages, and generally keep your tasks running smoothly. +7. πŸ“š **RAG**: Use Julep's document store to build a system for retrieving and using your own data. + +Julep is ideal for applications that require AI use cases beyond simple prompt-response models. + ## Quick Example Imagine a Research AI agent that can do the following: - 1. Take a topic, - 2. Come up with 100 search queries for that topic, - 3. Perform those web searches in parallel, - 4. Summarize the results, - 5. Send the summary to Discord + +1. Take a topic, +2. Come up with 100 search queries for that topic, +3. Perform those web searches in parallel, +4. Summarize the results, +5. Send the summary to Discord In Julep, this would be a single task under 80 lines of code and run fully managed all on its own. All of the steps are executed on Julep's own servers and you don't need to lift a finger. Here's a working example: @@ -152,20 +159,20 @@ input_schema: # Define the tools that the agent can use tools: -- name: web_search - type: integration - integration: - provider: brave - setup: - api_key: "YOUR_BRAVE_API_KEY" - -- name: discord_webhook - type: api_call - api_call: - url: "YOUR_DISCORD_WEBHOOK_URL" - method: POST - headers: - Content-Type: application/json + - name: web_search + type: integration + integration: + provider: brave + setup: + api_key: "YOUR_BRAVE_API_KEY" + + - name: discord_webhook + type: api_call + api_call: + url: "YOUR_DISCORD_WEBHOOK_URL" + method: POST + headers: + Content-Type: application/json # Special variables: # - inputs: for accessing the input to the task @@ -174,101 +181,51 @@ tools: # Define the main workflow main: -- prompt: - - role: system - content: >- - You are a research assistant. - Generate 100 diverse search queries related to the topic: - {{inputs[0].topic}} + - prompt: + - role: system + content: >- + You are a research assistant. + Generate 100 diverse search queries related to the topic: + {{inputs[0].topic}} - Write one query per line. - unwrap: true + Write one query per line. + unwrap: true -# Evaluate the search queries using a simple python expression -- evaluate: - search_queries: "_.split('\n')" + # Evaluate the search queries using a simple python expression + - evaluate: + search_queries: "_.split('\n')" -# Run the web search in parallel for each query -- over: "_.search_queries" - map: - tool: web_search - arguments: - query: "_" - parallelism: 100 + # Run the web search in parallel for each query + - over: "_.search_queries" + map: + tool: web_search + arguments: + query: "_" + parallelism: 100 -# Collect the results from the web search -- evaluate: - results: "'\n'.join([item.result for item in _])" + # Collect the results from the web search + - evaluate: + results: "'\n'.join([item.result for item in _])" -# Summarize the results -- prompt: - - role: system - content: > - You are a research summarizer. Create a comprehensive summary of the following research results on the topic {{inputs[0].topic}}. - The summary should be well-structured, informative, and highlight key findings and insights: - {{_.results}} - unwrap: true + # Summarize the results + - prompt: + - role: system + content: > + You are a research summarizer. Create a comprehensive summary of the following research results on the topic {{inputs[0].topic}}. + The summary should be well-structured, informative, and highlight key findings and insights: + {{_.results}} + unwrap: true -# Send the summary to Discord -- tool: discord_webhook - arguments: - content: > - **Research Summary for {{inputs[0].topic}}** + # Send the summary to Discord + - tool: discord_webhook + arguments: + content: > + **Research Summary for {{inputs[0].topic}}** - {{_}} + {{_}} ``` -> [!TIP] -> Julep is really useful when you want to build AI agents that can maintain context and state over long-term interactions. It's great for designing complex, multi-step workflows and integrating various tools and APIs directly into your agent's processes. -> -> In this example, Julep will automatically manage parallel executions, retry failed steps, resend API requests, and keep the tasks running reliably until completion. - -## Key Features - -1. 🧠 **Persistent AI Agents**: Remember context and information over long-term interactions. -2. πŸ’Ύ **Stateful Sessions**: Keep track of past interactions for personalized responses. -3. πŸ”„ **Multi-Step Tasks**: Build complex, multi-step processes with loops and decision-making. -4. ⏳ **Task Management**: Handle long-running tasks that can run indefinitely. -5. πŸ› οΈ **Built-in Tools**: Use built-in tools and external APIs in your tasks. -6. πŸ”§ **Self-Healing**: Julep will automatically retry failed steps, resend messages, and generally keep your tasks running smoothly. -7. πŸ“š **RAG**: Use Julep's document store to build a system for retrieving and using your own data. - -Julep is ideal for applications that require AI use cases beyond simple prompt-response models. - -## Why Julep vs. LangChain? - -### Different Use Cases - -Think of LangChain and Julep as tools with different focuses within the AI development stack. - -LangChain is great for creating sequences of prompts and managing interactions with AI models. It has a large ecosystem with lots of pre-built integrations, which makes it convenient if you want to get something up and running quickly. LangChain fits well with simple use cases that involve a linear chain of prompts and API calls. - -Julep, on the other hand, is more about building persistent AI agents that can remember things over long-term interactions. It shines when you need complex tasks that involve multiple steps, decision-making, and integration with various tools or APIs directly within the agent's process. It's designed from the ground up to manage persistent sessions and complex tasks. - -Use Julep if you imagine building a complex AI assistant that needs to: - -- Keep track of user interactions over days or weeks. -- Perform scheduled tasks, like sending daily summaries or monitoring data sources. -- Make decisions based on prior interactions or stored data. -- Interact with multiple external services as part of its task. - -Then Julep provides the infrastructure to support all that without you having to build it from scratch. - -### Different Form Factor - -Julep is a **platform** that includes a language for describing tasks, a server for running those tasks, and an SDK for interacting with the platform. To build something with Julep, you write a description of the task in `YAML`, and then run the task in the cloud. - -Julep is built for heavy-lifting, multi-step, and long-running tasks and there's no limit to how complex the task can be. - -LangChain is a **library** that includes a few tools and a framework for building linear chains of prompts and tools. To build something with LangChain, you typically write Python code that configures and runs the model chains you want to use. - -LangChain might be sufficient and quicker to implement for simple use cases that involve a linear chain of prompts and API calls. - -### In Summary - -Use LangChain when you need to manage AI model interactions and prompt sequences in a stateless or short-term context. - -Choose Julep when you need a robust framework for stateful agents with advanced task capabilities, persistent sessions, and complex task management. +In this example, Julep will automatically manage parallel executions, retry failed steps, resend API requests, and keep the tasks running reliably until completion. ## Installation @@ -418,25 +375,24 @@ while (message := input("Enter a message: ")) != "quit": print(response) ``` -> [!TIP] -> You can find the full python example [here](example.py). - +You can find the full python example [here](example.py). ## Node.js Quick Start 🟩 ### Step 1: Create an Agent ```javascript -import { Julep } from '@julep/sdk'; -import yaml from 'js-yaml'; +import { Julep } from "@julep/sdk"; +import yaml from "js-yaml"; -const client = new Julep({ apiKey: 'your_julep_api_key' }); +const client = new Julep({ apiKey: "your_julep_api_key" }); async function createAgent() { const agent = await client.agents.create({ name: "Storytelling Agent", model: "gpt-4", - about: "You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", + about: + "You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", }); // πŸ› οΈ Add an image generation tool (DALLΒ·E) to the agent @@ -516,11 +472,13 @@ async function createTask(agent) { ```javascript async function executeTask(task) { const execution = await client.executions.create(task.id, { - input: { idea: "A cat who learns to fly" } + input: { idea: "A cat who learns to fly" }, }); // πŸŽ‰ Watch as the story and comic panels are generated - for await (const transition of client.executions.transitions.stream(execution.id)) { + for await (const transition of client.executions.transitions.stream( + execution.id + )) { console.log(transition); } @@ -539,12 +497,12 @@ async function chatWithAgent(agent) { // πŸ’¬ Send messages to the agent const rl = readline.createInterface({ input: process.stdin, - output: process.stdout + output: process.stdout, }); const chat = async () => { rl.question("Enter a message (or 'quit' to exit): ", async (message) => { - if (message.toLowerCase() === 'quit') { + if (message.toLowerCase() === "quit") { rl.close(); return; } @@ -570,8 +528,7 @@ async function runExample() { runExample().catch(console.error); ``` -> [!TIP] -> You can find the full Node.js example [here](example.js). +You can find the full Node.js example [here](example.js). ## Components @@ -590,10 +547,12 @@ Julep is made up of the following components: Think of Julep as a platform that combines both client-side and server-side components to help you build advanced AI agents. Here's how to visualize it: 1. **Your Application Code:** - - You use the Julep SDK in your application to define agents, tasks, and workflows. + + - You can use the Julep SDK in your application to define agents, tasks, and workflows. - The SDK provides functions and classes that make it easy to set up and manage these components. 2. **Julep Backend Service:** + - The SDK communicates with the Julep backend over the network. - The backend handles execution of tasks, maintains session state, stores documents, and orchestrates workflows. @@ -601,11 +560,6 @@ Think of Julep as a platform that combines both client-side and server-side comp - Within your workflows, you can integrate external tools and services. - The backend facilitates these integrations, so your agents can, for example, perform web searches, access databases, or call third-party APIs. -In simpler terms: -- Julep is a platform for building stateful AI agents. -- You use the SDK (like a toolkit) in your code to define what your agents do. -- The backend service (which you can think of as the engine) runs these definitions, manages state, and handles complexity. - ## Concepts Julep is built on several key technical components that work together to create powerful AI workflows: @@ -636,7 +590,7 @@ graph TD - **Documents**: Text or data objects associated with agents or users, vectorized and stored for semantic search and retrieval. - **Executions**: Instances of tasks that have been initiated with specific inputs, with their own lifecycle and state machine. -For a more detailed explanation of these concepts and their interactions, please refer to our [Concepts Documentation](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md). +For a more detailed explanation, refer to our [Concepts Documentation](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md). ## Understanding Tasks @@ -648,138 +602,328 @@ Tasks are the core of Julep's workflow system. They allow you to define complex, ### Types of Workflow Steps -Tasks in Julep can include various types of steps, allowing you to create complex and powerful workflows. Here's an overview of the available step types, organized by category: +Tasks in Julep can include various types of steps, allowing you to create complex and powerful workflows. Here's an overview of the available step types: #### Common Steps -1. **Prompt**: Send a message to the AI model and receive a response. - ```yaml - - prompt: "Analyze the following data: {{data}}" - ``` - -2. **Tool Call**: Execute an integrated tool or API. - ```yaml - - tool: web_search - arguments: - query: "Latest AI developments" - ``` - -3. **Evaluate**: Perform calculations or manipulate data. - ```yaml - - evaluate: - average_score: "sum(scores) / len(scores)" - ``` - -4. **Wait for Input**: Pause workflow until input is received. - ```yaml - - wait_for_input: - info: - message: "Please provide additional information." - ``` - -5. **Log**: Log a specified value or message. - ```yaml - - log: "Processing completed for item {{item_id}}" - ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name About Syntax
Prompt +Send a message to the AI model and receive a response + + + +```yaml +- prompt: "Analyze the following data: {{data}}" +``` + +
Tool Call +Execute an integrated tool or API + + + +```yaml +- tool: web_search + arguments: + query: "Latest AI developments" +``` + +
Evaluate +Perform calculations or manipulate data + + + +```yaml +- evaluate: + average_score: "sum(scores) / len(scores)" +``` + +
Wait for Input +Pause workflow until input is received + + + +```yaml +- wait_for_input: + info: + message: "Please provide additional information." +``` + +
Log +Log a specified value or message + + + +```yaml +- log: "Processing completed for item {{item_id}}" +``` + +
#### Key-Value Steps -6. **Get**: Retrieve a value from a key-value store. - ```yaml - - get: "user_preference" - ``` + + + + + + + + + + + + + + + + +
Name About Syntax
Get +Retrieve a value from a key-value store + + + +```yaml +- get: "user_preference" +``` + +
Set +Assign a value to a key in a key-value store + + + +```yaml +- set: + user_preference: "dark_mode" +``` -7. **Set**: Assign a value to a key in a key-value store. - ```yaml - - set: - user_preference: "dark_mode" - ``` +
#### Iteration Steps -8. **Foreach**: Iterate over a collection and perform steps for each item. - ```yaml - - foreach: - in: "data_list" - do: - - log: "Processing item {{_}}" - ``` - -9. **Map-Reduce**: Map over a collection and reduce the results. - ```yaml - - map_reduce: - over: "numbers" - map: - - evaluate: - squared: "_ ** 2" - reduce: "sum(results)" - ``` - -10. **Parallel**: Run multiple steps in parallel. - ```yaml - - parallel: - - tool: web_search - arguments: - query: "AI news" - - tool: weather_check - arguments: - location: "New York" - ``` + + + + + + + + + + + + + + + + + + + + + + +
Name About Syntax
Foreach +Iterate over a collection and perform steps for each item + + + +```yaml +- foreach: + in: "data_list" + do: + - log: "Processing item {{_}}" +``` + +
Map-Reduce +Map over a collection and reduce the results + + + +```yaml +- map_reduce: + over: "numbers" + map: + - evaluate: + squared: "_ ** 2" + reduce: "sum(results)" +``` + +
Parallel +Run multiple steps in parallel + + + +```yaml +- parallel: + - tool: web_search + arguments: + query: "AI news" + - tool: weather_check + arguments: + location: "New York" +``` + +
#### Conditional Steps -11. **If-Else**: Conditional execution of steps. - ```yaml - - if: "score > 0.8" + + + + + + + + + + + + + + + + +
Name About Syntax
If-Else +Conditional execution of steps + + + +```yaml +- if: "score > 0.8" + then: + - log: "High score achieved" + else: + - log: "Score needs improvement" +``` + +
Switch +Execute steps based on multiple conditions + + + +```yaml +- switch: + - case: "category == 'A'" + then: + - log: "Category A processing" + - case: "category == 'B'" + then: + - log: "Category B processing" + - case: "_" # Default case then: - - log: "High score achieved" - else: - - log: "Score needs improvement" - ``` - -12. **Switch**: Execute steps based on multiple conditions. - ```yaml - - switch: - - case: "category == 'A'" - then: - - log: "Category A processing" - - case: "category == 'B'" - then: - - log: "Category B processing" - - case: "_" # Default case - then: - - log: "Unknown category" - ``` + - log: "Unknown category" +``` + +
#### Other Control Flow -13. **Sleep**: Pause the workflow for a specified duration. - ```yaml - - sleep: - seconds: 30 - ``` - -14. **Return**: Return a value from the workflow. - ```yaml - - return: - result: "Task completed successfully" - ``` - -15. **Yield**: Run a subworkflow and await its completion. - ```yaml - - yield: - workflow: "data_processing_subflow" - arguments: - input_data: "{{raw_data}}" - ``` + + + + + + + -Each step type serves a specific purpose in building sophisticated AI workflows. This categorization helps in understanding the various control flows and operations available in Julep tasks. + + + + + + + + + + + + + + + + + + + + + +
Name About Syntax
Sleep +Pause the workflow for a specified duration -16. **Error**: Handle errors by specifying an error message. - ```yaml - - error: "Invalid input provided" - ``` + + +```yaml +- sleep: + seconds: 30 +``` + +
Return +Return a value from the workflow + + +```yaml +- return: + result: "Task completed successfully" +``` + +
Yield +Run a subworkflow and await its completion + + + +```yaml +- yield: + workflow: "data_processing_subflow" + arguments: + input_data: "{{raw_data}}" +``` + +
Error +Handle errors by specifying an error message + + + +```yaml +- error: "Invalid input provided" +``` + +
+ +Each step type serves a specific purpose in building sophisticated AI workflows. This categorization helps in understanding the various control flows and operations available in Julep tasks. ## Tool Types @@ -789,204 +933,253 @@ Unlike agent frameworks, julep is a _backend_ that manages agent execution. Clie Tools in julep can be one of: -### User-defined `function`s +### User-defined `functions` -These are function signatures that you can give the model to choose from, similar to how [openai]'s function-calling works. An example: +These are function signatures that you can give the model to choose from, similar to how [openai]'s function-calling works. An example: -```yaml - name: Example system tool task - description: List agents using system call +```yaml +name: Example system tool task +description: List agents using system call - tools: - - name: send_notification - description: Send a notification to the user - type: function - function: - parameters: - type: object - properties: - text: - type: string - description: Content of the notification +tools: + - name: send_notification + description: Send a notification to the user + type: function + function: + parameters: + type: object + properties: + text: + type: string + description: Content of the notification - main: - - tool: send_notification - arguments: - content: hi +main: + - tool: send_notification + arguments: + content: hi ``` - - Whenever julep encounters a _user-defined function_, it pauses, giving control back to the client and waits for the client to run the function call and give the results back to julep. + +Whenever julep encounters a _user-defined function_, it pauses, giving control back to the client and waits for the client to run the function call and give the results back to julep. > [!TIP] > **Example cookbook**: [cookbooks/13-Error_Handling_and_Recovery.py](https://github.com/julep-ai/julep/blob/dev/cookbooks/13-Error_Handling_and_Recovery.py) ### `system` tools + Built-in tools that can be used to call the julep APIs themselves, like triggering a task execution, appending to a metadata field, etc. -`system` tools are built into the backend. They get executed automatically when needed. They do _not_ require any action from the client-side. - +`system` tools are built into the backend. They get executed automatically when needed. They do _not_ require any action from the client-side. + For example, - - ```yaml - name: Example system tool task - description: List agents using system call - - tools: - - name: list_agents - description: List all agents - type: system - system: - resource: agent - operation: list - main: - - tool: list_agents - arguments: - limit: 10 - ``` + +```yaml +name: Example system tool task +description: List agents using system call + +tools: + - name: list_agents + description: List all agents + type: system + system: + resource: agent + operation: list +main: + - tool: list_agents + arguments: + limit: 10 +``` > [!TIP] > **Example cookbook**: [cookbooks/10-Document_Management_and_Search.py](https://github.com/julep-ai/julep/blob/dev/cookbooks/10-Document_Management_and_Search.py) - -### Built-in `integration`s + +### Built-in `integrations` + Julep comes with a number of built-in integrations (as described in the section below). `integration` tools are directly executed on the julep backend. Any additional parameters needed by them at runtime can be set in the agent/session/user's `metadata` fields. > [!TIP] > **Example cookbook**: [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) julep backend ships with integrated third party tools from the following providers: -- [composio](https://composio.dev) \*\* -- [anon](https://anon.com) \*\* -- [langchain toolkits](https://python.langchain.com/v0.2/docs/integrations/toolkits/). Support for _Github, Gitlab, Gmail, Jira, MultiOn, Slack_ toolkits is planned. -\*\* Since _composio_ and _anon_ are third-party providers, their tools require setting up account linking. +- [composio](https://composio.dev) +- [anon](https://anon.com) +- [langchain toolkits](https://python.langchain.com/v0.2/docs/integrations/toolkits/) + +Support for _Github, Gitlab, Gmail, Jira, MultiOn, Slack_ toolkits is planned. +Since _composio_ and _anon_ are third-party providers, their tools require setting up account linking. -### Direct `api_call`s +### Direct `api_calls` julep can also directly make api calls during workflow executions as tool calls. Same as `integration`s, additional runtime parameters are loaded from `metadata` fields. - -For example, - - ```yaml - name: Example api_call task - tools: - - type: api_call - name: hello - api_call: - method: GET - url: https://httpbin.org/get - main: - - tool: hello - arguments: - params: - test: _.input - ``` + +For example, + +```yaml +name: Example api_call task +tools: + - type: api_call + name: hello + api_call: + method: GET + url: https://httpbin.org/get +main: + - tool: hello + arguments: + params: + test: _.input +``` ## Integrations Julep supports various integrations that extend the capabilities of your AI agents. Here's a list of available integrations and their supported arguments: -### Brave Search + + + + + + + + + + + + + + + + + + + + + + -### Weather + + + + + + + + + + + + + + + +
Brave Search ```yaml setup: - api_key: string # The API key for Brave Search + api_key: string # The API key for Brave Search arguments: - query: string # The search query for searching with Brave + query: string # The search query for searching with Brave output: - result: string # The result of the Brave Search + result: string # The result of the Brave Search ``` -> [!TIP] -> **Example cookbook**: [cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + -### BrowserBase +**Example cookbook**: [cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + +
BrowserBase ```yaml setup: - api_key: string # The API key for BrowserBase - project_id: string # The project ID for BrowserBase - session_id: string # (Optional) The session ID for BrowserBase + api_key: string # The API key for BrowserBase + project_id: string # The project ID for BrowserBase + session_id: string # (Optional) The session ID for BrowserBase arguments: - urls: list[string] # The URLs for loading with BrowserBase + urls: list[string] # The URLs for loading with BrowserBase output: - documents: list # The documents loaded from the URLs + documents: list # The documents loaded from the URLs ``` -### Email +
Email ```yaml setup: - host: string # The host of the email server - port: integer # The port of the email server - user: string # The username of the email server - password: string # The password of the email server + host: string # The host of the email server + port: integer # The port of the email server + user: string # The username of the email server + password: string # The password of the email server arguments: - to: string # The email address to send the email to - from: string # The email address to send the email from - subject: string # The subject of the email - body: string # The body of the email + to: string # The email address to send the email to + from: string # The email address to send the email from + subject: string # The subject of the email + body: string # The body of the email output: - success: boolean # Whether the email was sent successfully + success: boolean # Whether the email was sent successfully ``` -> [!TIP] -> **Example cookbook**: [cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + -### Spider +**Example cookbook**: [cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + +
Spider ```yaml setup: - spider_api_key: string # The API key for Spider + spider_api_key: string # The API key for Spider arguments: - url: string # The URL for which to fetch data - mode: string # The type of crawlers (default: "scrape") - params: dict # (Optional) The parameters for the Spider API + url: string # The URL for which to fetch data + mode: string # The type of crawlers (default: "scrape") + params: dict # (Optional) The parameters for the Spider API output: - documents: list # The documents returned from the spider + documents: list # The documents returned from the spider ``` -> [!TIP] -> **Example cookbook**: [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + + +**Example cookbook**: [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + +
Weather ```yaml setup: - openweathermap_api_key: string # The API key for OpenWeatherMap + openweathermap_api_key: string # The API key for OpenWeatherMap arguments: - location: string # The location for which to fetch weather data + location: string # The location for which to fetch weather data output: - result: string # The weather data for the specified location + result: string # The weather data for the specified location ``` -> [!TIP] -> **Example cookbook**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + -### Wikipedia +**Example cookbook**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + +
Wikipedia ```yaml arguments: - query: string # The search query string - load_max_docs: integer # Maximum number of documents to load (default: 2) + query: string # The search query string + load_max_docs: integer # Maximum number of documents to load (default: 2) output: - documents: list # The documents returned from the Wikipedia search + documents: list # The documents returned from the Wikipedia search ``` -> [!TIP] -> **Example cookbook**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + -These integrations can be used within your tasks to extend the capabilities of your AI agents. For more detailed information on how to use these integrations in your workflows, please refer to our [Integrations Documentation](https://docs.julep.ai/integrations). +**Example cookbook**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + +
+ +For more details, refer to our [Integrations Documentation](https://docs.julep.ai/integrations). ## Other Features @@ -1054,9 +1247,11 @@ results = client.agents.docs.search( ## Local Quickstart **Requirements**: + - latest docker compose installed **Steps**: + 1. `git clone https://github.com/julep-ai/julep.git` 2. `cd julep` 3. `docker volume create cozo_backup` @@ -1077,10 +1272,8 @@ Explore our comprehensive API documentation to learn more about agents, tasks, a - [Tasks API](https://api.julep.ai/api/docs#tag/tasks) - [Executions API](https://api.julep.ai/api/docs#tag/executions) -
Back to Top
- diff --git a/docs/README.md b/docs/README.md index 5359f6c38..8a994860c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,7 +15,6 @@ LinkedIn

-

NPM Version   @@ -26,7 +25,7 @@ GitHub License

-***** +--- > [!NOTE] > πŸ‘¨β€πŸ’» Here for the devfest.ai event? Join our [Discord](https://discord.com/invite/JTSBGRZrzj) and check out the details below. @@ -125,6 +124,7 @@ Julep enables the creation of multi-step tasks incorporating decision-making, lo While many AI applications are limited to simple, linear chains of prompts and API calls with minimal branching, Julep is built to handle more complex scenarios. It supports: + - Intricate, multi-step processes - Dynamic decision-making - Parallel execution @@ -135,11 +135,12 @@ It supports: ## Quick Example Imagine a Research AI agent that can do the following: - 1. Take a topic, - 2. Come up with 100 search queries for that topic, - 3. Perform those web searches in parallel, - 4. Summarize the results, - 5. Send the summary to Discord + +1. Take a topic, +2. Come up with 100 search queries for that topic, +3. Perform those web searches in parallel, +4. Summarize the results, +5. Send the summary to Discord In Julep, this would be a single task under 80 lines of code and run fully managed all on its own. All of the steps are executed on Julep's own servers and you don't need to lift a finger. Here's a working example: @@ -156,20 +157,20 @@ input_schema: # Define the tools that the agent can use tools: -- name: web_search - type: integration - integration: - provider: brave - setup: - api_key: "YOUR_BRAVE_API_KEY" - -- name: discord_webhook - type: api_call - api_call: - url: "YOUR_DISCORD_WEBHOOK_URL" - method: POST - headers: - Content-Type: application/json + - name: web_search + type: integration + integration: + provider: brave + setup: + api_key: "YOUR_BRAVE_API_KEY" + + - name: discord_webhook + type: api_call + api_call: + url: "YOUR_DISCORD_WEBHOOK_URL" + method: POST + headers: + Content-Type: application/json # Special variables: # - inputs: for accessing the input to the task @@ -178,48 +179,48 @@ tools: # Define the main workflow main: -- prompt: - - role: system - content: >- - You are a research assistant. - Generate 100 diverse search queries related to the topic: - {{inputs[0].topic}} - - Write one query per line. - unwrap: true - -# Evaluate the search queries using a simple python expression -- evaluate: - search_queries: "_.split('\n')" - -# Run the web search in parallel for each query -- over: "_.search_queries" - map: - tool: web_search - arguments: - query: "_" - parallelism: 100 + - prompt: + - role: system + content: >- + You are a research assistant. + Generate 100 diverse search queries related to the topic: + {{inputs[0].topic}} + + Write one query per line. + unwrap: true -# Collect the results from the web search -- evaluate: - results: "'\n'.join([item.result for item in _])" + # Evaluate the search queries using a simple python expression + - evaluate: + search_queries: "_.split('\n')" + + # Run the web search in parallel for each query + - over: "_.search_queries" + map: + tool: web_search + arguments: + query: "_" + parallelism: 100 + + # Collect the results from the web search + - evaluate: + results: "'\n'.join([item.result for item in _])" + + # Summarize the results + - prompt: + - role: system + content: > + You are a research summarizer. Create a comprehensive summary of the following research results on the topic {{inputs[0].topic}}. + The summary should be well-structured, informative, and highlight key findings and insights: + {{_.results}} + unwrap: true -# Summarize the results -- prompt: - - role: system + # Send the summary to Discord + - tool: discord_webhook + arguments: content: > - You are a research summarizer. Create a comprehensive summary of the following research results on the topic {{inputs[0].topic}}. - The summary should be well-structured, informative, and highlight key findings and insights: - {{_.results}} - unwrap: true - -# Send the summary to Discord -- tool: discord_webhook - arguments: - content: > - **Research Summary for {{inputs[0].topic}}** - - {{_}} + **Research Summary for {{inputs[0].topic}}** + + {{_}} ``` > [!TIP] @@ -425,22 +426,22 @@ while (message := input("Enter a message: ")) != "quit": > [!TIP] > You can find the full python example [here](example.py). - ## Node.js Quick Start 🟩 ### Step 1: Create an Agent ```javascript -import { Julep } from '@julep/sdk'; -import yaml from 'js-yaml'; +import { Julep } from "@julep/sdk"; +import yaml from "js-yaml"; -const client = new Julep({ apiKey: 'your_julep_api_key' }); +const client = new Julep({ apiKey: "your_julep_api_key" }); async function createAgent() { const agent = await client.agents.create({ name: "Storytelling Agent", model: "gpt-4", - about: "You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", + about: + "You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", }); // πŸ› οΈ Add an image generation tool (DALLΒ·E) to the agent @@ -520,11 +521,13 @@ async function createTask(agent) { ```javascript async function executeTask(task) { const execution = await client.executions.create(task.id, { - input: { idea: "A cat who learns to fly" } + input: { idea: "A cat who learns to fly" }, }); // πŸŽ‰ Watch as the story and comic panels are generated - for await (const transition of client.executions.transitions.stream(execution.id)) { + for await (const transition of client.executions.transitions.stream( + execution.id + )) { console.log(transition); } @@ -543,12 +546,12 @@ async function chatWithAgent(agent) { // πŸ’¬ Send messages to the agent const rl = readline.createInterface({ input: process.stdin, - output: process.stdout + output: process.stdout, }); const chat = async () => { rl.question("Enter a message (or 'quit' to exit): ", async (message) => { - if (message.toLowerCase() === 'quit') { + if (message.toLowerCase() === "quit") { rl.close(); return; } @@ -594,10 +597,12 @@ Julep is made up of the following components: Think of Julep as a platform that combines both client-side and server-side components to help you build advanced AI agents. Here's how to visualize it: 1. **Your Application Code:** + - You use the Julep SDK in your application to define agents, tasks, and workflows. - The SDK provides functions and classes that make it easy to set up and manage these components. 2. **Julep Backend Service:** + - The SDK communicates with the Julep backend over the network. - The backend handles execution of tasks, maintains session state, stores documents, and orchestrates workflows. @@ -606,6 +611,7 @@ Think of Julep as a platform that combines both client-side and server-side comp - The backend facilitates these integrations, so your agents can, for example, perform web searches, access databases, or call third-party APIs. In simpler terms: + - Julep is a platform for building stateful AI agents. - You use the SDK (like a toolkit) in your code to define what your agents do. - The backend service (which you can think of as the engine) runs these definitions, manages state, and handles complexity. @@ -657,11 +663,13 @@ Tasks in Julep can include various types of steps, allowing you to create comple #### Common Steps 1. **Prompt**: Send a message to the AI model and receive a response. + ```yaml - prompt: "Analyze the following data: {{data}}" ``` 2. **Tool Call**: Execute an integrated tool or API. + ```yaml - tool: web_search arguments: @@ -669,12 +677,14 @@ Tasks in Julep can include various types of steps, allowing you to create comple ``` 3. **Evaluate**: Perform calculations or manipulate data. + ```yaml - evaluate: average_score: "sum(scores) / len(scores)" ``` 4. **Wait for Input**: Pause workflow until input is received. + ```yaml - wait_for_input: info: @@ -689,6 +699,7 @@ Tasks in Julep can include various types of steps, allowing you to create comple #### Key-Value Steps 6. **Get**: Retrieve a value from a key-value store. + ```yaml - get: "user_preference" ``` @@ -702,6 +713,7 @@ Tasks in Julep can include various types of steps, allowing you to create comple #### Iteration Steps 8. **Foreach**: Iterate over a collection and perform steps for each item. + ```yaml - foreach: in: "data_list" @@ -710,6 +722,7 @@ Tasks in Julep can include various types of steps, allowing you to create comple ``` 9. **Map-Reduce**: Map over a collection and reduce the results. + ```yaml - map_reduce: over: "numbers" @@ -733,6 +746,7 @@ Tasks in Julep can include various types of steps, allowing you to create comple #### Conditional Steps 11. **If-Else**: Conditional execution of steps. + ```yaml - if: "score > 0.8" then: @@ -750,7 +764,7 @@ Tasks in Julep can include various types of steps, allowing you to create comple - case: "category == 'B'" then: - log: "Category B processing" - - case: "_" # Default case + - case: "_" # Default case then: - log: "Unknown category" ``` @@ -758,18 +772,21 @@ Tasks in Julep can include various types of steps, allowing you to create comple #### Other Control Flow 13. **Sleep**: Pause the workflow for a specified duration. + ```yaml - sleep: seconds: 30 ``` 14. **Return**: Return a value from the workflow. + ```yaml - return: result: "Task completed successfully" ``` 15. **Yield**: Run a subworkflow and await its completion. + ```yaml - yield: workflow: "data_processing_subflow" @@ -857,86 +874,86 @@ Julep supports various integrations that extend the capabilities of your AI agen ```yaml setup: - api_key: string # The API key for Brave Search + api_key: string # The API key for Brave Search arguments: - query: string # The search query for searching with Brave + query: string # The search query for searching with Brave output: - result: string # The result of the Brave Search + result: string # The result of the Brave Search ``` ### BrowserBase ```yaml setup: - api_key: string # The API key for BrowserBase - project_id: string # The project ID for BrowserBase - session_id: string # (Optional) The session ID for BrowserBase + api_key: string # The API key for BrowserBase + project_id: string # The project ID for BrowserBase + session_id: string # (Optional) The session ID for BrowserBase arguments: - urls: list[string] # The URLs for loading with BrowserBase + urls: list[string] # The URLs for loading with BrowserBase output: - documents: list # The documents loaded from the URLs + documents: list # The documents loaded from the URLs ``` ### Email ```yaml setup: - host: string # The host of the email server - port: integer # The port of the email server - user: string # The username of the email server - password: string # The password of the email server + host: string # The host of the email server + port: integer # The port of the email server + user: string # The username of the email server + password: string # The password of the email server arguments: - to: string # The email address to send the email to - from: string # The email address to send the email from - subject: string # The subject of the email - body: string # The body of the email + to: string # The email address to send the email to + from: string # The email address to send the email from + subject: string # The subject of the email + body: string # The body of the email output: - success: boolean # Whether the email was sent successfully + success: boolean # Whether the email was sent successfully ``` ### Spider ```yaml setup: - spider_api_key: string # The API key for Spider + spider_api_key: string # The API key for Spider arguments: - url: string # The URL for which to fetch data - mode: string # The type of crawlers (default: "scrape") - params: dict # (Optional) The parameters for the Spider API + url: string # The URL for which to fetch data + mode: string # The type of crawlers (default: "scrape") + params: dict # (Optional) The parameters for the Spider API output: - documents: list # The documents returned from the spider + documents: list # The documents returned from the spider ``` ### Weather ```yaml setup: - openweathermap_api_key: string # The API key for OpenWeatherMap + openweathermap_api_key: string # The API key for OpenWeatherMap arguments: - location: string # The location for which to fetch weather data + location: string # The location for which to fetch weather data output: - result: string # The weather data for the specified location + result: string # The weather data for the specified location ``` ### Wikipedia ```yaml arguments: - query: string # The search query string - load_max_docs: integer # Maximum number of documents to load (default: 2) + query: string # The search query string + load_max_docs: integer # Maximum number of documents to load (default: 2) output: - documents: list # The documents returned from the Wikipedia search + documents: list # The documents returned from the Wikipedia search ``` These integrations can be used within your tasks to extend the capabilities of your AI agents. For more detailed information on how to use these integrations in your workflows, please refer to our [Integrations Documentation](https://docs.julep.ai/integrations). From 4bab852bcd03363e61971d05c36cec8f5de59b2d Mon Sep 17 00:00:00 2001 From: Mayur Kawale <122032765+Mefisto04@users.noreply.github.com> Date: Wed, 16 Oct 2024 01:48:13 +0530 Subject: [PATCH 2/2] Add E-commerce Order Processing Workflow Cookbook (#650) **Overview:** This pull request introduces a new cookbook titled `01-E-commerce_Order_Processing_Workflow.ipynb`. It provides a comprehensive guide for automating the order processing system, which includes handling order placements, inventory checks, payment processing, and shipment tracking. **Key Features:** - **Introduction:** An overview explaining the purpose of the cookbook. - **Installation Section:** Instructions for installing the Julep client to facilitate the order processing workflow. - **Structured Sections:** - **Creating an Agent:** Steps to create a Julep agent for handling user interactions. - **Defining a Task:** Guidance on how to define tasks for order placement and inventory management. - **Creating Executions:** Detailed instructions on how to create and manage executions for order processing. - **Code Quality:** - The code is well-commented, follows PEP 8 style guidelines, and uses meaningful variable names. - Error handling is implemented gracefully to ensure a robust execution flow. **Documentation:** - Each step is explained clearly, assuming the reader is new to Julep. - Links to relevant Julep documentation are included for further reference. **Testing:** - The notebook has been thoroughly tested in Google Colab to ensure it runs without errors. - Sample outputs are included to demonstrate the functionality of the order processing workflow. ---- > [!IMPORTANT] > Adds a Jupyter notebook for automating e-commerce order processing with tasks for order placement, inventory checking, payment processing, and shipment tracking. > > - **New Feature**: > - Adds `01-E-commerce_Order_Processing_Workflow.ipynb` for automating e-commerce order processing. > - Includes tasks for order placement, inventory checking, payment processing, and shipment tracking. > - **Code Structure**: > - Uses `uuid` for task and agent identification. > - Implements tasks using `yaml.safe_load` for task definitions. > - Functions `place_order`, `check_inventory`, `process_payment`, and `track_shipment` handle respective tasks. > - **Testing and Documentation**: > - Tested in Google Colab with sample outputs. > - Well-commented code with PEP 8 compliance. > > This description was created by [Ellipsis](https://www.ellipsis.dev?ref=julep-ai%2Fjulep&utm_source=github&utm_medium=referral) for c067fde169fa439682a744d367d590c300e37b7b. It will automatically update as commits are pushed. --------- Co-authored-by: Diwank Singh Tomer Co-authored-by: creatorrr --- README.md | 12 +- ...E_commerce_Order_Processing_Workflow.ipynb | 381 ++++++++++++++++++ .../e_commerce_order_processing_workflow.py | 238 +++++++++++ 3 files changed, 623 insertions(+), 8 deletions(-) create mode 100644 cookbooks/E_commerce_Order_Processing_Workflow.ipynb create mode 100644 cookbooks/e_commerce_order_processing_workflow.py diff --git a/README.md b/README.md index a9d75d8a4..563330bc0 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,8 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! πŸ—“

πŸ“– Table of Contents

- [Introduction](#introduction) -- [Quick Example](#quick-example) - [Key Features](#key-features) -- [Why Julep vs. LangChain?](#why-julep-vs-langchain) - - [Different Use Cases](#different-use-cases) - - [Different Form Factor](#different-form-factor) - - [In Summary](#in-summary) +- [Quick Example](#quick-example) - [Installation](#installation) - [Python Quick Start 🐍](#python-quick-start-) - [Step 1: Create an Agent](#step-1-create-an-agent) @@ -89,10 +85,10 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! πŸ—“ - [Understanding Tasks](#understanding-tasks) - [Types of Workflow Steps](#types-of-workflow-steps) - [Tool Types](#tool-types) - - [User-defined `function`s](#user-defined-functions) + - [User-defined `functions`](#user-defined-functions) - [`system` tools](#system-tools) - - [Built-in `integration`s](#built-in-integrations) - - [Direct `api_call`s](#direct-api_calls) + - [Built-in `integrations`](#built-in-integrations) + - [Direct `api_calls`](#direct-api_calls) - [Integrations](#integrations) - [Other Features](#other-features) - [Adding Tools to Agents](#adding-tools-to-agents) diff --git a/cookbooks/E_commerce_Order_Processing_Workflow.ipynb b/cookbooks/E_commerce_Order_Processing_Workflow.ipynb new file mode 100644 index 000000000..bf4e741ca --- /dev/null +++ b/cookbooks/E_commerce_Order_Processing_Workflow.ipynb @@ -0,0 +1,381 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "code", + "source": [ + "import uuid\n", + "import yaml\n", + "import time\n", + "from julep import Client" + ], + "metadata": { + "id": "QIJXVEzBYrRv" + }, + "execution_count": 3, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "AGENT_UUID = uuid.uuid4()\n", + "ORDER_PLACEMENT_TASK_UUID = uuid.uuid4()\n", + "INVENTORY_CHECK_TASK_UUID = uuid.uuid4()\n", + "PAYMENT_PROCESSING_TASK_UUID = uuid.uuid4()\n", + "SHIPMENT_TRACKING_TASK_UUID = uuid.uuid4()" + ], + "metadata": { + "id": "tCqfsDHuYu4V" + }, + "execution_count": 4, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "api_key = \"\" # Your API key here\n", + "client = Client(api_key=api_key, environment=\"dev\")" + ], + "metadata": { + "id": "mSBH1k6OYxUW" + }, + "execution_count": 5, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "agent = client.agents.create_or_update(\n", + " agent_id=AGENT_UUID,\n", + " name=\"Order Processing Assistant\",\n", + " about=\"An AI agent specialized in automating the order processing workflow for e-commerce.\",\n", + " model=\"gpt-4o\",\n", + ")" + ], + "metadata": { + "id": "loTLYbQ8Y1i5" + }, + "execution_count": 6, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "order_placement_task_def = yaml.safe_load(\"\"\"\n", + "name: Order Placement\n", + "\n", + "input_schema:\n", + " type: object\n", + " properties:\n", + " user_id:\n", + " type: string\n", + " order_details:\n", + " type: object\n", + " properties:\n", + " item_id:\n", + " type: integer\n", + " quantity:\n", + " type: integer\n", + "\n", + "main:\n", + "- prompt:\n", + " - role: system\n", + " content: >-\n", + " You are an order placement assistant. Process the following order:\n", + " User ID: {{inputs[0].user_id}}\n", + " Order Details: {{inputs[0].order_details}}\n", + "\n", + " Confirm the order placement and return the order ID.\n", + " unwrap: true\n", + "\n", + "- evaluate:\n", + " order_id: _.uuid()\n", + "\n", + "- return:\n", + " order_id: _\n", + "\"\"\")" + ], + "metadata": { + "id": "UDsmzc_pY4Dx" + }, + "execution_count": 7, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "order_placement_task = client.tasks.create_or_update(\n", + " task_id=ORDER_PLACEMENT_TASK_UUID,\n", + " agent_id=AGENT_UUID,\n", + " **order_placement_task_def\n", + ")\n" + ], + "metadata": { + "id": "cc76A2UxY-Z7" + }, + "execution_count": 8, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "inventory_check_task_def = yaml.safe_load(\"\"\"\n", + "name: Inventory Check\n", + "\n", + "input_schema:\n", + " type: object\n", + " properties:\n", + " item_id:\n", + " type: integer\n", + " quantity:\n", + " type: integer\n", + "\n", + "main:\n", + "- prompt:\n", + " - role: system\n", + " content: >-\n", + " You are an inventory checker. Check the availability of the following item:\n", + " Item ID: {{inputs[0].item_id}}\n", + " Quantity Requested: {{inputs[0].quantity}}\n", + "\n", + " Return true if available, otherwise return false.\n", + " unwrap: true\n", + "\"\"\")\n", + "\n" + ], + "metadata": { + "id": "uCdVhA98ZBPB" + }, + "execution_count": 9, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "inventory_check_task = client.tasks.create_or_update(\n", + " task_id=INVENTORY_CHECK_TASK_UUID,\n", + " agent_id=AGENT_UUID,\n", + " **inventory_check_task_def\n", + ")\n" + ], + "metadata": { + "id": "ZICp9jXiZEgO" + }, + "execution_count": 10, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "payment_processing_task_def = yaml.safe_load(\"\"\"\n", + "name: Payment Processing\n", + "\n", + "input_schema:\n", + " type: object\n", + " properties:\n", + " user_id:\n", + " type: string\n", + " order_id:\n", + " type: string\n", + " amount:\n", + " type: number\n", + "\n", + "main:\n", + "- prompt:\n", + " - role: system\n", + " content: >-\n", + " You are a payment processor. Process payment for the following order:\n", + " User ID: {{inputs[0].user_id}}\n", + " Order ID: {{inputs[0].order_id}}\n", + " Amount: {{inputs[0].amount}}\n", + "\n", + " Confirm payment status (success or failure).\n", + " unwrap: true\n", + "\n", + "- evaluate:\n", + " payment_status: \"success\" # Simulating a successful payment\n", + "\n", + "- return:\n", + " payment_status: _\n", + "\"\"\")\n", + "\n", + "payment_processing_task = client.tasks.create_or_update(\n", + " task_id=PAYMENT_PROCESSING_TASK_UUID,\n", + " agent_id=AGENT_UUID,\n", + " **payment_processing_task_def\n", + ")\n", + "\n", + "shipment_tracking_task_def = yaml.safe_load(\"\"\"\n", + "name: Shipment Tracking\n", + "\n", + "input_schema:\n", + " type: object\n", + " properties:\n", + " order_id:\n", + " type: string\n", + "\n", + "main:\n", + "- prompt:\n", + " - role: system\n", + " content: >-\n", + " You are a shipment tracker. Track the shipment for the following order:\n", + " Order ID: {{inputs[0].order_id}}\n", + "\n", + " Return the current status of the shipment.\n", + " unwrap: true\n", + "\"\"\")\n" + ], + "metadata": { + "id": "lr0M9XWKZG9N" + }, + "execution_count": 11, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "shipment_tracking_task = client.tasks.create_or_update(\n", + " task_id=SHIPMENT_TRACKING_TASK_UUID,\n", + " agent_id=AGENT_UUID,\n", + " **shipment_tracking_task_def\n", + ")" + ], + "metadata": { + "id": "-k0Wl-o8ZJw7" + }, + "execution_count": 12, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def place_order(user_id, item_id, quantity):\n", + " execution = client.executions.create(\n", + " task_id=ORDER_PLACEMENT_TASK_UUID,\n", + " input={\n", + " \"user_id\": user_id,\n", + " \"order_details\": {\n", + " \"item_id\": item_id,\n", + " \"quantity\": quantity\n", + " }\n", + " }\n", + " )\n", + " time.sleep(2)\n", + " result = client.executions.get(execution.id)\n", + " output = client.executions.transitions.list(execution_id=result.id).items[0].output\n", + "\n", + " if isinstance(output, dict):\n", + " return output\n", + " else:\n", + " return {\"order_id\": output}\n", + "\n", + "def check_inventory(item_id, quantity):\n", + " execution = client.executions.create(\n", + " task_id=INVENTORY_CHECK_TASK_UUID,\n", + " input={\n", + " \"item_id\": item_id,\n", + " \"quantity\": quantity\n", + " }\n", + " )\n", + " time.sleep(2)\n", + " result = client.executions.get(execution.id)\n", + " return client.executions.transitions.list(execution_id=result.id).items[0].output\n", + "\n", + "def process_payment(user_id, order_id, amount):\n", + " execution = client.executions.create(\n", + " task_id=PAYMENT_PROCESSING_TASK_UUID,\n", + " input={\n", + " \"user_id\": user_id,\n", + " \"order_id\": order_id,\n", + " \"amount\": amount\n", + " }\n", + " )\n", + " time.sleep(2)\n", + " result = client.executions.get(execution.id)\n", + " return client.executions.transitions.list(execution_id=result.id).items[0].output\n", + "\n", + "def track_shipment(order_id):\n", + " execution = client.executions.create(\n", + " task_id=SHIPMENT_TRACKING_TASK_UUID,\n", + " input={\n", + " \"order_id\": order_id\n", + " }\n", + " )\n", + " time.sleep(2)\n", + " result = client.executions.get(execution.id)\n", + " return client.executions.transitions.list(execution_id=result.id).items[0].output\n" + ], + "metadata": { + "id": "6iM6NqwlZMTD" + }, + "execution_count": 16, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "print(\"Demonstrating E-commerce Order Processing Workflow:\")\n", + "\n", + "user_id = \"user123\"\n", + "item_id = 1\n", + "quantity = 2\n", + "amount = 49.99\n", + "\n", + "is_available = check_inventory(item_id, quantity)\n", + "if is_available:\n", + " print(f\"Inventory Check: Item {item_id} is available.\")\n", + " order_result = place_order(user_id, item_id, quantity)\n", + " print(f\"Order Result: {order_result}\")\n", + " payment_result = process_payment(user_id, order_result[\"order_id\"], amount)\n", + " print(f\"Payment Status: {payment_result}\")\n", + " shipment_result = track_shipment(order_result[\"order_id\"])\n", + " print(f\"Shipment Status: {shipment_result}\")\n", + "else:\n", + " print(f\"Inventory Check: Item {item_id} is not available.\")\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "FTDf1VaMZQ3f", + "outputId": "a358feb6-2630-4a2c-d423-16d7f2937c07" + }, + "execution_count": 17, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Demonstrating E-commerce Order Processing Workflow:\n", + "Inventory Check: Item 1 is available.\n", + "Order Result: {'order_id': 'Order confirmed for User ID: user123. The order details are as follows: Item ID: 1, Quantity: 2. Your order ID is ORD456789.'}\n", + "Payment Status: Payment processed successfully for Order ID: ORD456789. The payment amount of $49.99 has been confirmed.\n", + "Shipment Status: The current status of the shipment for Order ID ORD456789 is \"In Transit.\" The order has been picked up by the carrier and is on its way to the delivery address. Estimated delivery is within 3-5 business days.\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "0NaRffiYZXGf" + }, + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/cookbooks/e_commerce_order_processing_workflow.py b/cookbooks/e_commerce_order_processing_workflow.py new file mode 100644 index 000000000..e8db94556 --- /dev/null +++ b/cookbooks/e_commerce_order_processing_workflow.py @@ -0,0 +1,238 @@ +# -*- coding: utf-8 -*- +"""E-commerce_Order_Processing_Workflow.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1mP-uZV8-wMMJA0eDcF5TH6C82ZOup055 +""" + +import uuid +import yaml +import time +from julep import Client + +AGENT_UUID = uuid.uuid4() +ORDER_PLACEMENT_TASK_UUID = uuid.uuid4() +INVENTORY_CHECK_TASK_UUID = uuid.uuid4() +PAYMENT_PROCESSING_TASK_UUID = uuid.uuid4() +SHIPMENT_TRACKING_TASK_UUID = uuid.uuid4() + +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name="Order Processing Assistant", + about="An AI agent specialized in automating the order processing workflow for e-commerce.", + model="gpt-4o", +) + +order_placement_task_def = yaml.safe_load(""" +name: Order Placement + +input_schema: + type: object + properties: + user_id: + type: string + order_details: + type: object + properties: + item_id: + type: integer + quantity: + type: integer + +main: +- prompt: + - role: system + content: >- + You are an order placement assistant. Process the following order: + User ID: {{inputs[0].user_id}} + Order Details: {{inputs[0].order_details}} + + Confirm the order placement and return the order ID. + unwrap: true + +- evaluate: + order_id: _.uuid() + +- return: + order_id: _ +""") + +order_placement_task = client.tasks.create_or_update( + task_id=ORDER_PLACEMENT_TASK_UUID, + agent_id=AGENT_UUID, + **order_placement_task_def +) + +inventory_check_task_def = yaml.safe_load(""" +name: Inventory Check + +input_schema: + type: object + properties: + item_id: + type: integer + quantity: + type: integer + +main: +- prompt: + - role: system + content: >- + You are an inventory checker. Check the availability of the following item: + Item ID: {{inputs[0].item_id}} + Quantity Requested: {{inputs[0].quantity}} + + Return true if available, otherwise return false. + unwrap: true +""") + +inventory_check_task = client.tasks.create_or_update( + task_id=INVENTORY_CHECK_TASK_UUID, + agent_id=AGENT_UUID, + **inventory_check_task_def +) + +payment_processing_task_def = yaml.safe_load(""" +name: Payment Processing + +input_schema: + type: object + properties: + user_id: + type: string + order_id: + type: string + amount: + type: number + +main: +- prompt: + - role: system + content: >- + You are a payment processor. Process payment for the following order: + User ID: {{inputs[0].user_id}} + Order ID: {{inputs[0].order_id}} + Amount: {{inputs[0].amount}} + + Confirm payment status (success or failure). + unwrap: true + +- evaluate: + payment_status: "success" # Simulating a successful payment + +- return: + payment_status: _ +""") + +payment_processing_task = client.tasks.create_or_update( + task_id=PAYMENT_PROCESSING_TASK_UUID, + agent_id=AGENT_UUID, + **payment_processing_task_def +) + +shipment_tracking_task_def = yaml.safe_load(""" +name: Shipment Tracking + +input_schema: + type: object + properties: + order_id: + type: string + +main: +- prompt: + - role: system + content: >- + You are a shipment tracker. Track the shipment for the following order: + Order ID: {{inputs[0].order_id}} + + Return the current status of the shipment. + unwrap: true +""") + +shipment_tracking_task = client.tasks.create_or_update( + task_id=SHIPMENT_TRACKING_TASK_UUID, + agent_id=AGENT_UUID, + **shipment_tracking_task_def +) + +def place_order(user_id, item_id, quantity): + execution = client.executions.create( + task_id=ORDER_PLACEMENT_TASK_UUID, + input={ + "user_id": user_id, + "order_details": { + "item_id": item_id, + "quantity": quantity + } + } + ) + time.sleep(2) + result = client.executions.get(execution.id) + output = client.executions.transitions.list(execution_id=result.id).items[0].output + + if isinstance(output, dict): + return output + else: + return {"order_id": output} + +def check_inventory(item_id, quantity): + execution = client.executions.create( + task_id=INVENTORY_CHECK_TASK_UUID, + input={ + "item_id": item_id, + "quantity": quantity + } + ) + time.sleep(2) + result = client.executions.get(execution.id) + return client.executions.transitions.list(execution_id=result.id).items[0].output + +def process_payment(user_id, order_id, amount): + execution = client.executions.create( + task_id=PAYMENT_PROCESSING_TASK_UUID, + input={ + "user_id": user_id, + "order_id": order_id, + "amount": amount + } + ) + time.sleep(2) + result = client.executions.get(execution.id) + return client.executions.transitions.list(execution_id=result.id).items[0].output + +def track_shipment(order_id): + execution = client.executions.create( + task_id=SHIPMENT_TRACKING_TASK_UUID, + input={ + "order_id": order_id + } + ) + time.sleep(2) + result = client.executions.get(execution.id) + return client.executions.transitions.list(execution_id=result.id).items[0].output + +print("Demonstrating E-commerce Order Processing Workflow:") + +user_id = "user123" +item_id = 1 +quantity = 2 +amount = 49.99 + +is_available = check_inventory(item_id, quantity) +if is_available: + print(f"Inventory Check: Item {item_id} is available.") + order_result = place_order(user_id, item_id, quantity) + print(f"Order Result: {order_result}") + payment_result = process_payment(user_id, order_result["order_id"], amount) + print(f"Payment Status: {payment_result}") + shipment_result = track_shipment(order_result["order_id"]) + print(f"Shipment Status: {shipment_result}") +else: + print(f"Inventory Check: Item {item_id} is not available.") +