diff --git a/.env.example b/.env.example index 8e5392a0d..e0cfd5c05 100644 --- a/.env.example +++ b/.env.example @@ -61,6 +61,7 @@ LITELLM_REDIS_PASSWORD= # INTEGRATION_SERVICE_URL=http://integrations:8000 # USE_BLOB_STORE_FOR_TEMPORAL=false # BLOB_STORE_CUTOFF_KB=1024 +# BLOB_STORE_BUCKET=agents-api # Memory Store # ----------- diff --git a/README-CN.md b/README-CN.md index be9d94a75..09832121a 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,6 +1,6 @@ [English](README.md) | [中文翻译](README-CN.md) | [日本語翻訳](README-JA.md) | [French](README-FR.md) -
+
julep
@@ -15,7 +15,6 @@ LinkedIn

-

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

-***** +--- > [!注意] > 👨‍💻 来参加 devfest.ai 活动了吗?加入我们的 [Discord](https://discord.com/invite/JTSBGRZrzj) 并查看以下详细信息。 -> -> 从 [此处](https://dashboard-dev.julep.ai) 获取您的 API 密钥。 +> +> 从[此处](https://dashboard-dev.julep.ai)获取您的 API 密钥。
🌟 贡献者和 DevFest.AI 参与者(点击展开) @@ -64,38 +63,44 @@
-

📖 Table of Contents

- -- [为什么选择 Julep 而不是 LangChain?](#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9-julep-%E8%80%8C%E4%B8%8D%E6%98%AF-langchain) - - [不同的用例](#%E4%B8%8D%E5%90%8C%E7%9A%84%E7%94%A8%E4%BE%8B) - - [不同的外形尺寸](#%E4%B8%8D%E5%90%8C%E7%9A%84%E5%A4%96%E5%BD%A2%E5%B0%BA%E5%AF%B8) -- [Python 快速入门🐍](#python-%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8) - - [步骤 1:创建代理](#%E6%AD%A5%E9%AA%A4-1%E5%88%9B%E5%BB%BA%E4%BB%A3%E7%90%86) - - [步骤 2:创建一个生成故事和漫画的任务](#%E6%AD%A5%E9%AA%A4-2%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%94%9F%E6%88%90%E6%95%85%E4%BA%8B%E5%92%8C%E6%BC%AB%E7%94%BB%E7%9A%84%E4%BB%BB%E5%8A%A1) - - [步骤 3:执行任务](#%E6%AD%A5%E9%AA%A4-3%E6%89%A7%E8%A1%8C%E4%BB%BB%E5%8A%A1) - - [步骤 4:与代理聊天](#%E6%AD%A5%E9%AA%A4-4%E4%B8%8E%E4%BB%A3%E7%90%86%E8%81%8A%E5%A4%A9) -- [Node.js 快速入门 🟩](#nodejs-%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8-) - - [步骤 1:创建代理](#%E6%AD%A5%E9%AA%A4-1%E5%88%9B%E5%BB%BA%E4%BB%A3%E7%90%86-1) - - [步骤 2:创建一个生成故事和漫画的任务](#%E6%AD%A5%E9%AA%A4-2%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%94%9F%E6%88%90%E6%95%85%E4%BA%8B%E5%92%8C%E6%BC%AB%E7%94%BB%E7%9A%84%E4%BB%BB%E5%8A%A1-1) - - [步骤 3:执行任务](#%E6%AD%A5%E9%AA%A4-3%E6%89%A7%E8%A1%8C%E4%BB%BB%E5%8A%A1-1) - - [步骤 4:与代理聊天](#%E6%AD%A5%E9%AA%A4-4%E4%B8%8E%E4%BB%A3%E7%90%86%E8%81%8A%E5%A4%A9-1) - - [心智模型](#%E5%BF%83%E6%99%BA%E6%A8%A1%E5%9E%8B) -- [概念](#%E6%A6%82%E5%BF%B5) -- [理解任务](#%E7%90%86%E8%A7%A3%E4%BB%BB%E5%8A%A1) - - [工作流步骤的类型](#%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AD%A5%E9%AA%A4%E7%9A%84%E7%B1%BB%E5%9E%8B) -- [工具类型](#%E5%B7%A5%E5%85%B7%E7%B1%BB%E5%9E%8B) - - [用户定义的函数](#%E7%94%A8%E6%88%B7%E5%AE%9A%E4%B9%89%E7%9A%84%E5%87%BD%E6%95%B0) - - [`系统` 工具](#%E7%B3%BB%E7%BB%9F-%E5%B7%A5%E5%85%B7) - - [内置“集成”](#%E5%86%85%E7%BD%AE%E9%9B%86%E6%88%90) - - [直接 `api_call`](#%E7%9B%B4%E6%8E%A5-api_call) -- [集成](#%E9%9B%86%E6%88%90) - - [勇敢搜索](#%E5%8B%87%E6%95%A2%E6%90%9C%E7%B4%A2) - - [浏览器基础](#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%9F%BA%E7%A1%80) - - [向代理添加工具](#%E5%90%91%E4%BB%A3%E7%90%86%E6%B7%BB%E5%8A%A0%E5%B7%A5%E5%85%B7) - - [管理会话和用户](#%E7%AE%A1%E7%90%86%E4%BC%9A%E8%AF%9D%E5%92%8C%E7%94%A8%E6%88%B7) - - [文档集成与搜索](#%E6%96%87%E6%A1%A3%E9%9B%86%E6%88%90%E4%B8%8E%E6%90%9C%E7%B4%A2) -- [本地快速启动](#%E6%9C%AC%E5%9C%B0%E5%BF%AB%E9%80%9F%E5%90%AF%E5%8A%A8) -- [SDK 参考](#sdk-%E5%8F%82%E8%80%83) +

📖 目录

+ +- [简介](#introduction) +- [主要特点](#key-features) +- [快速示例](#quick-example) +- [安装](#安装) +- [Python 快速入门 🐍](#python-quick-start-) +- [步骤 1:创建代理](#step-1-create-an-agent) +- [步骤 2:创建一个生成故事和漫画的任务](#step-2-create-a-task-that-generates-a-story-and-comic-strip) +- [步骤 3:执行任务](#step-3-execute-the-task) +- [步骤 4:与代理聊天](#step-4-chat-with-the-agent) +- [Node.js 快速入门🟩](#nodejs-quick-start-) +- [步骤 1:创建代理](#step-1-create-an-agent-1) +- [步骤 2:创建一个生成故事和漫画的任务](#step-2-create-a-task-that-generates-a-story-and-comic-strip-1) +- [步骤 3:执行任务](#step-3-execute-the-task-1) +- [步骤 4:与代理聊天](#step-4-chat-with-the-agent-1) +- [组件](#components) +- [心智模型](#mental-model) +- [概念](#concepts) +- [理解任务](#understanding-tasks) +- [工作流步骤的类型](#types-of-workflow-steps) +- [工具类型](#tool-types) +- [用户定义的`函数`](#user-defined-functions) +- [`系统` 工具](#system-tools) +- [内置 `integrations`](#built-in-integrations) +-[直接`api_calls`](#direct-api_calls) +- [集成](#integrations) +- [其他功能](#other-features) +- [向代理添加工具](#adding-tools-to-agents) +- [管理会话和用户](#managing-sessions-and-users) +- [文档集成与搜索](#document-integration-and-search) +- [本地快速启动](#local-quickstart) +- [SDK 参考](#sdk-reference) +- [API 参考](#api-reference) +- [为什么 Julep 与 LangChain?](#why-julep-vs-langchain) +- [不同用例](#different-use-cases) +- [不同的外形尺寸](#different-form-factor) +- [总结](#in-summary)
@@ -109,6 +114,7 @@ Julep 支持创建多步骤任务,包括决策、循环、并行处理以及 虽然许多人工智能应用程序仅限于简单、线性的提示链和 API 调用,并且分支很少,但 Julep 可以处理更复杂的场景。 它支持: + - 复杂、多步骤的流程 - 动态决策 - 并行执行 @@ -116,9 +122,22 @@ Julep 支持创建多步骤任务,包括决策、循环、并行处理以及 > [!提示] > 想象一下,您想要构建一个 AI 代理,它不仅可以回答简单的问题,还可以处理复杂的任务,记住过去的交互,甚至可能使用其他工具或 API。这就是 Julep 的作用所在。 +## 主要特点 + +1. 🧠 **持久 AI 代理**:在长期交互​​中记住上下文和信息。 +2. 💾 **状态会话**:跟踪过去的互动以获得个性化回应。 +3. 🔄 **多步骤任务**:使用循环和决策构建复杂的多步骤流程。 +4. ⏳ **任务管理**:处理可以无限期运行的长时间运行的任务。 +5.🛠️**内置工具**:在您的任务中使用内置工具和外部 API。 +6. 🔧 **自我修复**:Julep 将自动重试失败的步骤、重新发送消息,并确保您的任务顺利运行。 +7. 📚 **RAG**:使用 Julep 的文档存储构建一个用于检索和使用您自己的数据的系统。 + +Julep 非常适合需要超越简单的提示响应模型的 AI 用例的应用程序。 + 快速示例 想象一下一个可以执行以下操作的研究 AI 代理: + 1. 选择一个主题, 2. 针对该主题提出 100 个搜索查询, 3. 同时进行网页搜索, @@ -140,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 @@ -162,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}}** - {{_}} + {{_}} ``` -> [!提示] -> 当您想要构建能够在长期交互​​中保持上下文和状态的 AI 代理时,Julep 非常有用。它非常适合设计复杂的多步骤工作流程,并将各种工具和 API 直接集成到代理的流程中。 -> -> 在此示例中,Julep 将自动管理并行执行,重试失败的步骤,重新发送 API 请求,并保持任务可靠运行直至完成。 - -主要特点 - -1. 🧠 **持久 AI 代理**:在长期交互​​中记住背景和信息。 -2. 💾 **状态会话**:跟踪过去的互动以获得个性化回应。 -3. 🔄 **多步骤任务**:使用循环和决策构建复杂的多步骤流程。 -4. ⏳ **任务管理**:处理可以无限期运行的长时间运行的任务。 -5.🛠️**内置工具**:在您的任务中使用内置工具和外部 API。 -6. 🔧 **自我修复**:Julep 将自动重试失败的步骤、重新发送消息,并确保您的任务顺利运行。 -7. 📚 **RAG**:使用 Julep 的文档存储构建一个用于检索和使用您自己的数据的系统。 - -Julep 非常适合需要超越简单的提示响应模型的 AI 用例的应用程序。 - -## 为什么选择 Julep 而不是 LangChain? - -### 不同的用例 - -可以将 LangChain 和 Julep 视为 AI 开发堆栈中具有不同重点的工具。 - -LangChain 非常适合创建提示序列和管理与 AI 模型的交互。它拥有庞大的生态系统,包含大量预构建的集成,如果您想快速启动和运行某些功能,这会非常方便。LangChain 非常适合涉及线性提示链和 API 调用的简单用例。 - -另一方面,Julep 更注重构建持久的 AI 代理,这些代理可以在长期交互​​中记住事物。当您需要涉及多个步骤、决策以及在代理流程中直接与各种工具或 API 集成的复杂任务时,它会大放异彩。它从头开始设计,以管理持久会话和复杂任务。 - -如果您想构建一个需要执行以下操作的复杂 AI 助手,请使用 Julep: - -- 跟踪几天或几周内的用户互动。 -- 执行计划任务,例如发送每日摘要或监控数据源。 -- 根据之前的互动或存储的数据做出决策。 -- 作为其任务的一部分,与多个外部服务进行交互。 - -然后 Julep 提供支持所有这些的基础设施,而无需您从头开始构建。 - -### 不同的外形尺寸 - -Julep 是一个**平台**,其中包括用于描述任务的语言、用于运行这些任务的服务器以及用于与平台交互的 SDK。要使用 Julep 构建某些东西,您需要在“YAML”中编写任务描述,然后在云中运行该任务。 - -Julep 专为繁重、多步骤和长时间运行的任务而设计,并且对任务的复杂程度没有限制。 - -LangChain 是一个**库**,其中包含一些工具和一个用于构建线性提示和工具链的框架。要使用 LangChain 构建某些东西,您通常需要编写 Python 代码来配置和运行要使用的模型链。 - -对于涉及线性提示和 API 调用链的简单用例,LangChain 可能足够并且能够更快地实现。 - -### 总之 - -当您需要在无状态或短期环境中管理 AI 模型交互和提示序列时,请使用 LangChain。 - -当您需要一个具有高级任务功能、持久会话和复杂任务管理的状态代理的强大框架时,请选择 Julep。 +在这个例子中,Julep 将自动管理并行执行,重试失败的步骤,重新发送 API 请求,并保持任务可靠运行直到完成。 ## 安装 @@ -273,7 +242,7 @@ pip install julep ``` > [!注意] -> 从 [此处](https://dashboard-dev.julep.ai) 获取您的 API 密钥。 +> 从[此处](https://dashboard-dev.julep.ai)获取您的 API 密钥。 > > 虽然我们处于测试阶段,但您也可以通过 [Discord](https://discord.com/invite/JTSBGRZrzj) 联系,以解除 API 密钥的速率限制。 @@ -406,25 +375,24 @@ while (message := input("Enter a message: ")) != "quit": print(response) ``` -> [!提示] -> 您可以在[这里](example.py)找到完整的 python 示例。 - +您可以在[这里](example.py)找到完整的python示例。 ## Node.js 快速入门 🟩 ### 步骤 1:创建代理 ```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 @@ -504,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); } @@ -527,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; } @@ -558,8 +528,7 @@ async function runExample() { runExample().catch(console.error); ``` -> [!提示] -> 您可以在[这里](example.js)找到完整的 Node.js 示例。 +您可以在[这里](example.js)找到完整的 Node.js 示例。 ## 成分 @@ -578,10 +547,12 @@ Julep 由以下成分组成: 您可以将 Julep 视为一个结合了客户端和服务器端组件的平台,以帮助您构建高级 AI 代理。以下是它的可视化方法: 1. **您的申请代码:** + - 您可以在应用程序中使用 Julep SDK 来定义代理、任务和工作流。 - SDK 提供的函数和类使得设置和管理这些组件变得容易。 2. **Julep 后端服务:** + - SDK 通过网络与 Julep 后端通信。 - 后端处理任务的执行,维护会话状态,存储文档并协调工作流程。 @@ -589,11 +560,6 @@ Julep 由以下成分组成: - 在您的工作流程中,您可以集成外部工具和服务。 - 后端促进这些集成,因此您的代理可以执行网络搜索、访问数据库或调用第三方 API。 -简单来说: -- Julep 是一个用于构建有状态 AI 代理的平台。 -- 您在代码中使用 SDK(类似工具包)来定义代理的功能。 -- 后端服务(您可以将其视为引擎)运行这些定义、管理状态并处理复杂性。 - ## 概念 Julep 基于几个关键技术组件构建,这些组件共同协作以创建强大的 AI 工作流程: @@ -624,7 +590,7 @@ graph TD - **文档**:与代理或用户相关的文本或数据对象,矢量化并存储以用于语义搜索和检索。 - **执行**:通过特定输入启动的任务实例,具有自己的生命周期和状态机。 -有关这些概念及其相互作用的更详细说明,请参阅我们的[概念文档](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)。 +有关更详细的解释,请参阅我们的[概念文档](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)。 ## 理解任务 @@ -636,138 +602,328 @@ graph TD ### 工作流步骤的类型 -Julep 中的任务可以包含各种类型的步骤,让您可以创建复杂而强大的工作流程。以下是按类别组织的可用步骤类型的概述: +Julep 中的任务可以包含各种类型的步骤,让您可以创建复杂而强大的工作流程。以下是可用步骤类型的概述: #### 常见步骤 -1. **提示**:向AI模型发送消息并收到回复。 - ```yaml - - prompt: "Analyze the following data: {{data}}" - ``` - -2. **工具调用**:执行集成的工具或API。 - ```yaml - - tool: web_search - arguments: - query: "Latest AI developments" - ``` - -3. **评估**:执行计算或处理数据。 - ```yaml - - evaluate: - average_score: "sum(scores) / len(scores)" - ``` - -4. **等待输入**:暂停工作流程,直到收到输入。 - ```yaml - - wait_for_input: - info: - message: "Please provide additional information." - ``` - -5. **日志**:记录指定的值或消息。 - ```yaml - - log: "Processing completed for item {{item_id}}" - ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
姓名 关于句法
迅速的 +向 AI 模型发送消息并接收响应 + + + +```yaml +- prompt: "Analyze the following data: {{data}}" +``` + +
工具调用 +执行集成工具或 API + + + +```yaml +- tool: web_search + arguments: + query: "Latest AI developments" +``` + +
评价 +执行计算或处理数据 + + + +```yaml +- evaluate: + average_score: "sum(scores) / len(scores)" +``` + +
等待输入 +暂停工作流程直到收到输入 + + + +```yaml +- wait_for_input: + info: + message: "Please provide additional information." +``` + +
日志 +记录指定的值或消息 + + + +```yaml +- log: "Processing completed for item {{item_id}}" +``` + +
#### 键值步骤 -6. **获取**:从键值存储中检索值。 - ```yaml - - get: "user_preference" - ``` + + + + + + + + + + + + + + + + +
姓名 关于句法
得到 +从键值存储中检索值 + + + +```yaml +- get: "user_preference" +``` + +
+为键值存储中的键分配值 + + + +```yaml +- set: + user_preference: "dark_mode" +``` -7. **设置**:为键值存储中的键分配一个值。 - ```yaml - - set: - user_preference: "dark_mode" - ``` +
#### 迭代步骤 -8. **Foreach**:遍历集合并对每个项目执行步骤。 - ```yaml - - foreach: - in: "data_list" - do: - - log: "Processing item {{_}}" - ``` - -9. **Map-Reduce**:对集合进行映射并减少结果。 - ```yaml - - map_reduce: - over: "numbers" - map: - - evaluate: - squared: "_ ** 2" - reduce: "sum(results)" - ``` - -10.**并行**:并行运行多个步骤。 - ```yaml - - parallel: - - tool: web_search - arguments: - query: "AI news" - - tool: weather_check - arguments: - location: "New York" - ``` + + + + + + + + + + + + + + + + + + + + + + +
姓名 关于句法
Foreach +遍历集合并对每个项目执行步骤 + + + +```yaml +- foreach: + in: "data_list" + do: + - log: "Processing item {{_}}" +``` + +
Map-Reduce +对集合进行映射并减少结果 + + + +```yaml +- map_reduce: + over: "numbers" + map: + - evaluate: + squared: "_ ** 2" + reduce: "sum(results)" +``` + +
平行线 +并行运行多个步骤 + + + +```yaml +- parallel: + - tool: web_search + arguments: + query: "AI news" + - tool: weather_check + arguments: + location: "New York" +``` + +
#### 条件步骤 -11. **If-Else**:条件执行步骤。 - ```yaml - - if: "score > 0.8" + + + + + + + + + + + + + + + + +
姓名 关于句法
如果-否则 +有条件地执行步骤 + + + +```yaml +- if: "score > 0.8" + then: + - log: "High score achieved" + else: + - log: "Score needs improvement" +``` + +
转变 +根据多个条件执行步骤 + + + +```yaml +- switch: + - case: "category == 'A'" + then: + - log: "Category A processing" + - case: "category == 'B'" then: - - log: "High score achieved" - else: - - log: "Score needs improvement" - ``` - -12.**Switch**:根据多种条件执行步骤。 - ```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: "Category B processing" + - case: "_" # Default case + then: + - log: "Unknown category" +``` + +
#### 其他控制流 -13. **睡眠**:暂停工作流一段指定的时间。 - ```yaml - - sleep: - seconds: 30 - ``` - -14. **返回**:从工作流返回一个值。 - ```yaml - - return: - result: "Task completed successfully" - ``` - -15. **收益**:运行子工作流并等待其完成。 - ```yaml - - yield: - workflow: "data_processing_subflow" - arguments: - input_data: "{{raw_data}}" - ``` + + + + + + + -每种步骤类型在构建复杂的 AI 工作流中都有特定的用途。此分类有助于理解 Julep 任务中可用的各种控制流程和操作。 + + + + + + + + + + + + + + + + + + + + + +
姓名 关于句法
睡觉 +暂停工作流一段指定的时间 -16.**错误**:通过指定错误消息来处理错误。 - ```yaml - - error: "Invalid input provided" - ``` + + +```yaml +- sleep: + seconds: 30 +``` +
返回 +从工作流返回值 + + + +```yaml +- return: + result: "Task completed successfully" +``` + +
屈服 +运行子工作流并等待其完成 + + + +```yaml +- yield: + workflow: "data_processing_subflow" + arguments: + input_data: "{{raw_data}}" +``` + +
错误 +通过指定错误消息来处理错误 + + + +```yaml +- error: "Invalid input provided" +``` + +
+ +每种步骤类型在构建复杂的 AI 工作流中都有特定的用途。此分类有助于理解 Julep 任务中可用的各种控制流程和操作。 ## 工具类型 @@ -781,200 +937,249 @@ julep 中的工具可以是以下之一: 这些是您可以为模型提供的函数签名,类似于 [openai] 的函数调用工作方式。例如: -```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 - - main: - - tool: send_notification - arguments: - content: hi +```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 + +main: + - tool: send_notification + arguments: + content: hi ``` - + 每当 julep 遇到_用户定义函数_时,它就会暂停,将控制权交还给客户端,并等待客户端运行函数调用并将结果返回给 julep。 > [!提示] > **示例食谱**:[cookbooks/13-Error_Handling_and_Recovery.py](https://github.com/julep-ai/julep/blob/dev/cookbooks/13-Error_Handling_and_Recovery.py) ### `系统` 工具 + 内置工具可用于调用 julep API 本身,例如触发任务执行、附加到元数据字段等。 “系统”工具内置于后端。它们会在需要时自动执行。它们不需要客户端的任何操作。 - + 例如, - - ```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 +``` > [!提示] > **示例食谱**:[cookbooks/10-Document_Management_and_Search.py​​](https://github.com/julep-ai/julep/blob/dev/cookbooks/10-Document_Management_and_Search.py​​) - + ### 内置“集成” + Julep 带有许多内置集成(如下节所述)。`集成` 工具直接在 julep 后端执行。它们在运行时所需的任何其他参数都可以在代理/会话/用户的 `元数据` 字段中设置。 > [!提示] > **示例食谱**:[cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) julep 后端附带来自以下提供商的集成第三方工具: -- [composio](https://composio.dev) \*\* -- [匿名](https://anon.com) \*\* -- [langchain 工具包](https://python.langchain.com/v0.2/docs/integrations/toolkits/)。计划支持 _Github、Gitlab、Gmail、Jira、MultiOn、Slack_ 工具包。 -\*\* 由于 _composio_ 和 _anon_ 是第三方提供商,因此他们的工具需要设置帐户链接。 +- [合成](https://composio.dev) +- [匿名](https://anon.com) +- [langchain 工具包](https://python.langchain.com/v0.2/docs/integrations/toolkits/) +计划支持_Github、Gitlab、Gmail、Jira、MultiOn、Slack_工具包。 -### 直接 `api_call` +由于_composio_和_anon_是第三方提供商,因此他们的工具需要设置帐户链接。 + +### 直接 `api_calls` julep 还可以在工作流执行期间直接以工具调用的形式进行 api 调用。与“集成”相同,其他运行时参数从“元数据”字段加载。 - + 例如, - - ```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 - ``` + +```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 +``` ## 集成 Julep 支持各种集成,可以扩展您的 AI 代理的功能。以下是可用集成及其支持的参数的列表: -### 勇敢搜索 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
勇敢搜索 ```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 ``` -> [!提示] -> **示例食谱**:[cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + -### 浏览器基础 +**示例食谱**:[cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + +
浏览器基础 ```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 ``` -### 电子邮件 +
电子邮件 ```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 ``` -> [!提示] -> **示例食谱**:[cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + -### 蜘蛛 +**示例食谱**:[cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + +
蜘蛛 ```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 ``` -> [!提示] -> **示例食谱**:[cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + -### 天气 +**示例食谱**:[cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + +
天气 ```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 ``` -> [!提示] -> **示例食谱**:[cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + + +**示例食谱**:[cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) -维基百科 +
维基百科 ```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 ``` -> [!提示] -> **示例食谱**:[cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + + +**示例食谱**:[cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + +
-这些集成可用于您的任务中,以扩展您的 AI 代理的功能。有关如何在您的工作流程中使用这些集成的详细信息,请参阅我们的 [集成文档](https://docs.julep.ai/integrations)。 +有关更多详细信息,请参阅我们的 [集成文档](https://docs.julep.ai/integrations)。 其他功能 @@ -1042,9 +1247,11 @@ results = client.agents.docs.search( ## 本地快速启动 **要求**: + - 安装了最新的docker compose **步骤**: + 1. `git 克隆 https://github.com/julep-ai/julep.git` 2. `cd julep` 3. `docker 卷创建 cozo_backup` @@ -1065,10 +1272,45 @@ API 参考 - [任务 API](https://api.julep.ai/api/docs#tag/tasks) - [执行 API](https://api.julep.ai/api/docs#tag/executions) +***** + +## 为什么选择 Julep 而不是 LangChain? + +### 不同的用例 + +可以将 LangChain 和 Julep 视为 AI 开发堆栈中具有不同重点的工具。 + +LangChain 非常适合创建提示序列和管理与 LLM 的交互。它拥有庞大的生态系统,包含大量预构建的集成,如果您想快速启动和运行某些功能,这会非常方便。LangChain 非常适合涉及线性提示链和 API 调用的简单用例。 + +另一方面,Julep 更侧重于构建持久的 AI 代理,这些代理可以在长期交互​​中保持上下文。当您需要涉及多步骤任务、条件逻辑以及在代理流程中直接与各种工具或 API 集成的复杂工作流时,它会大放异彩。它从头开始设计,以管理持久会话和复杂的工作流。 + +如果您想构建一个需要执行以下操作的复杂 AI 助手,请使用 Julep: + +- 跟踪几天或几周内的用户互动。 +- 执行计划任务,例如发送每日摘要或监控数据源。 +- 根据之前的互动或存储的数据做出决策。 +- 作为其工作流程的一部分与多个外部服务进行交互。 + +然后 Julep 提供支持所有这些的基础设施,而无需您从头开始构建。 + +### 不同的外形尺寸 + +Julep 是一个**平台**,其中包括用于描述工作流的语言、用于运行这些工作流的服务器以及用于与平台交互的 SDK。要使用 Julep 构建某些东西,您需要在“YAML”中编写工作流描述,然后在云中运行工作流。 + +Julep 专为繁重、多步骤和长时间运行的工作流程而构建,并且工作流程的复杂程度没有限制。 + +LangChain 是一个**库**,其中包含一些工具和一个用于构建线性提示和工具链的框架。为了使用 LangChain 构建某些东西,您通常需要编写 Python 代码来配置和运行要使用的模型链。 -
+对于涉及线性提示和 API 调用链的简单用例,LangChain 可能足够并且能够更快地实现。 + +### 总之 + +当您需要在无状态或短期环境中管理 LLM 交互和提示序列时,请使用 LangChain。 + +当您需要一个具有高级工作流功能、持久会话和复杂任务编排的状态代理的强大框架时,请选择 Julep。 + +
Back to Top
- diff --git a/README-FR.md b/README-FR.md index 1114ec877..d74f9a013 100644 --- a/README-FR.md +++ b/README-FR.md @@ -1,6 +1,6 @@ [English](README.md) | [中文翻译](README-CN.md) | [日本語翻訳](README-JA.md) | [French](README-FR.md) -
+
julep
@@ -15,7 +15,6 @@ LinkedIn

-

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

-***** +--- > [!REMARQUE] -> 👨‍💻 Vous êtes ici pour l'événement devfest.ai ? Rejoignez notre [Discord](https://discord.com/invite/JTSBGRZrzj) et consultez les détails ci-dessous. -> +> 👨‍💻 Vous êtes ici pour l'événement devfest.ai ? Rejoignez notre [Discord](https://discord.com/invite/JTSBGRZrzj) et consultez les détails ci-dessous. +> > Obtenez votre clé API [ici](https://dashboard-dev.julep.ai).
@@ -64,50 +63,44 @@ Des nouvelles passionnantes ! Nous participons au DevFest.AI tout au long du moi
-

📖 Table of Contents

- -- [Introduction](#introduction) -- [Exemple rapide](#exemple-rapide) -- [Principales caractéristiques](#principales-caract%C3%A9ristiques) -- [Pourquoi Julep vs. LangChain ?](#pourquoi-julep-vs-langchain%C2%A0) - - [Différents cas d'utilisation](#diff%C3%A9rents-cas-dutilisation) - - [Facteur de forme différent](#facteur-de-forme-diff%C3%A9rent) - - [En résumé](#en-r%C3%A9sum%C3%A9) +

📖 Table des matières

+ +- [Présentation](#introduction) +- [Caractéristiques principales](#key-features) +- [Exemple rapide](#quick-example) - [Installation](#installation) -- [Démarrage rapide de Python 🐍](#d%C3%A9marrage-rapide-de-python-) - - [Étape 1 : Créer un agent](#%C3%89tape-1%C2%A0-cr%C3%A9er-un-agent) - - [Étape 2 : Créer une tâche qui génère une histoire et une bande dessinée](#%C3%89tape-2%C2%A0-cr%C3%A9er-une-t%C3%A2che-qui-g%C3%A9n%C3%A8re-une-histoire-et-une-bande-dessin%C3%A9e) - - [Étape 3 : Exécuter la tâche](#%C3%89tape-3%C2%A0-ex%C3%A9cuter-la-t%C3%A2che) - - [Étape 4 : Discuter avec l'agent](#%C3%89tape-4%C2%A0-discuter-avec-lagent) -- [Démarrage rapide de Node.js 🟩](#d%C3%A9marrage-rapide-de-nodejs-) - - [Étape 1 : Créer un agent](#%C3%89tape-1%C2%A0-cr%C3%A9er-un-agent-1) - - [Étape 2 : Créer une tâche qui génère une histoire et une bande dessinée](#%C3%89tape-2%C2%A0-cr%C3%A9er-une-t%C3%A2che-qui-g%C3%A9n%C3%A8re-une-histoire-et-une-bande-dessin%C3%A9e-1) - - [Étape 3 : Exécuter la tâche](#%C3%89tape-3%C2%A0-ex%C3%A9cuter-la-t%C3%A2che-1) - - [Étape 4 : Discuter avec l'agent](#%C3%89tape-4%C2%A0-discuter-avec-lagent-1) +- [Démarrage rapide de Python 🐍](#python-quick-start-) +- [Étape 1 : Créer un agent](#step-1-create-an-agent) +- [Étape 2 : Créer une tâche qui génère une histoire et une bande dessinée](#step-2-create-a-task-that-generates-a-story-and-comic-strip) +- [Étape 3 : Exécuter la tâche](#step-3-execute-the-task) +- [Étape 4 : discuter avec l'agent](#step-4-chat-with-the-agent) +- [Démarrage rapide de Node.js 🟩](#nodejs-quick-start-) +- [Étape 1 : Créer un agent](#step-1-create-an-agent-1) +- [Étape 2 : Créer une tâche qui génère une histoire et une bande dessinée](#step-2-create-a-task-that-generates-a-story-and-comic-strip-1) +- [Étape 3 : Exécuter la tâche](#step-3-execute-the-task-1) +- [Étape 4 : discuter avec l'agent](#step-4-chat-with-the-agent-1) - [Composants](#composants) - - [Modèle mental](#mod%C3%A8le-mental) +- [Modèle mental](#mental-model) - [Concepts](#concepts) -- [Comprendre les tâches](#comprendre-les-t%C3%A2ches) - - [Types d'étapes de flux de travail](#types-d%C3%A9tapes-de-flux-de-travail) -- [Types d'outils](#types-doutils) - - [Fonctions définies par l'utilisateur](#fonctions-d%C3%A9finies-par-lutilisateur) - - [outils `système`](#outils-syst%C3%A8me) - - [Intégrations intégrées](#int%C3%A9grations-int%C3%A9gr%C3%A9es) - - [Appels directs `api_call`](#appels-directs-api_call) -- [Intégrations](#int%C3%A9grations) - - [Recherche courageuse](#recherche-courageuse) - - [Base de navigateur](#base-de-navigateur) - - [E-mail](#e-mail) - - [Araignée](#araign%C3%A9e) - - [Météo](#m%C3%A9t%C3%A9o) - - [Wikipédia](#wikip%C3%A9dia) -- [Autres fonctionnalités](#autres-fonctionnalit%C3%A9s) - - [Ajout d'outils aux agents](#ajout-doutils-aux-agents) - - [Gestion des sessions et des utilisateurs](#gestion-des-sessions-et-des-utilisateurs) - - [Intégration et recherche de documents](#int%C3%A9gration-et-recherche-de-documents) -- [Démarrage rapide local](#d%C3%A9marrage-rapide-local) -- [Référence du SDK](#r%C3%A9f%C3%A9rence-du-sdk) -- [Référence API](#r%C3%A9f%C3%A9rence-api) +- [Comprendre les tâches](#understanding-tasks) +- [Types d'étapes de flux de travail](#types-of-workflow-steps) +- [Types d'outils](#types-d'outils) +- [`Fonctions` définies par l'utilisateur](#user-defined-functions) +- [outils système](#outils-système) +- [`Intégrations` intégrées](#integrations-integrées) +- [Appels directs `api_calls`](#appels directs-api_calls) +- [Intégrations](#intégrations) +- [Autres fonctionnalités](#other-features) +- [Ajout d'outils aux agents](#adding-tools-to-agents) +- [Gestion des sessions et des utilisateurs](#managing-sessions-and-users) +- [Intégration et recherche de documents](#document-integration-and-search) +- [Démarrage rapide local](#local-quickstart) +- [Référence SDK](#sdk-reference) +- [Référence API](#api-reference) +- [Pourquoi Julep contre LangChain ?](#pourquoi-julep-vs-langchain) +- [Différents cas d'utilisation](#different-use-cases) +- [Facteur de forme différent](#different-form-factor) +- [En résumé](#en-resumé)
@@ -121,6 +114,7 @@ Julep permet la création de tâches en plusieurs étapes intégrant la prise de Alors que de nombreuses applications d’IA se limitent à des chaînes simples et linéaires d’invites et d’appels d’API avec une ramification minimale, Julep est conçu pour gérer des scénarios plus complexes. Il prend en charge : + - Processus complexes en plusieurs étapes - Prise de décision dynamique - Exécution parallèle @@ -128,9 +122,22 @@ Il prend en charge : > [!TIP] > Imaginez que vous souhaitiez créer un agent d'IA capable de faire plus que simplement répondre à des questions simples : il doit gérer des tâches complexes, se souvenir des interactions passées et peut-être même utiliser d'autres outils ou API. C'est là qu'intervient Julep. +## Principales caractéristiques + +1. 🧠 **Agents IA persistants** : mémorisent le contexte et les informations au cours d'interactions à long terme. +2. 💾 **Sessions avec état** : gardez une trace des interactions passées pour des réponses personnalisées. +3. 🔄 **Tâches en plusieurs étapes** : créez des processus complexes en plusieurs étapes avec des boucles et une prise de décision. +4. ⏳ **Gestion des tâches** : gérez les tâches de longue durée qui peuvent s'exécuter indéfiniment. +5. 🛠️ **Outils intégrés** : utilisez des outils intégrés et des API externes dans vos tâches. +6. 🔧 **Auto-réparation** : Julep réessaiera automatiquement les étapes ayant échoué, renverra les messages et assurera généralement le bon déroulement de vos tâches. +7. 📚 **RAG** ​​: Utilisez le magasin de documents de Julep pour créer un système permettant de récupérer et d'utiliser vos propres données. + +Julep est idéal pour les applications qui nécessitent des cas d’utilisation de l’IA au-delà des simples modèles de réponse rapide. + ## Exemple rapide Imaginez un agent d’IA de recherche capable d’effectuer les opérations suivantes : + 1. Prenez un sujet, 2. Proposez 100 requêtes de recherche pour ce sujet, 3. Effectuez ces recherches sur le Web en parallèle, @@ -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 est vraiment utile lorsque vous souhaitez créer des agents IA capables de conserver le contexte et l'état lors d'interactions à long terme. Il est idéal pour concevoir des flux de travail complexes en plusieurs étapes et pour intégrer divers outils et API directement dans les processus de votre agent. -> -> Dans cet exemple, Julep gérera automatiquement les exécutions parallèles, réessayera les étapes ayant échoué, renverra les requêtes API et maintiendra les tâches en cours d'exécution de manière fiable jusqu'à leur achèvement. - -## Principales caractéristiques - -1. 🧠 **Agents IA persistants** : mémorisent le contexte et les informations au cours d'interactions à long terme. -2. 💾 **Sessions avec état** : gardez une trace des interactions passées pour des réponses personnalisées. -3. 🔄 **Tâches en plusieurs étapes** : créez des processus complexes en plusieurs étapes avec des boucles et une prise de décision. -4. ⏳ **Gestion des tâches** : gérez les tâches de longue durée qui peuvent s'exécuter indéfiniment. -5. 🛠️ **Outils intégrés** : utilisez des outils intégrés et des API externes dans vos tâches. -6. 🔧 **Auto-réparation** : Julep réessaiera automatiquement les étapes ayant échoué, renverra les messages et assurera généralement le bon déroulement de vos tâches. -7. 📚 **RAG** ​​: Utilisez le magasin de documents de Julep pour créer un système permettant de récupérer et d'utiliser vos propres données. - -Julep est idéal pour les applications qui nécessitent des cas d’utilisation de l’IA au-delà des simples modèles de réponse rapide. - -## Pourquoi Julep vs. LangChain ? - -### Différents cas d'utilisation - -Considérez LangChain et Julep comme des outils avec des objectifs différents au sein de la pile de développement de l’IA. - -LangChain est idéal pour créer des séquences d'invites et gérer les interactions avec les modèles d'IA. Il dispose d'un vaste écosystème avec de nombreuses intégrations prédéfinies, ce qui le rend pratique si vous souhaitez mettre en place quelque chose rapidement. LangChain s'adapte bien aux cas d'utilisation simples qui impliquent une chaîne linéaire d'invites et d'appels d'API. - -Julep, en revanche, s'intéresse davantage à la création d'agents d'IA persistants capables de mémoriser des éléments au cours d'interactions à long terme. Il est particulièrement efficace lorsque vous avez besoin de tâches complexes impliquant plusieurs étapes, une prise de décision et une intégration avec divers outils ou API directement dans le processus de l'agent. Il est conçu dès le départ pour gérer les sessions persistantes et les tâches complexes. - -Utilisez Julep si vous imaginez créer un assistant IA complexe qui doit : - -- Suivez les interactions des utilisateurs sur plusieurs jours ou semaines. -- Exécutez des tâches planifiées, comme l'envoi de résumés quotidiens ou la surveillance de sources de données. -- Prendre des décisions basées sur des interactions antérieures ou des données stockées. -- Interagir avec plusieurs services externes dans le cadre de sa mission. - -Ensuite, Julep fournit l’infrastructure pour prendre en charge tout cela sans que vous ayez à le construire à partir de zéro. - -### Facteur de forme différent - -Julep est une **plateforme** qui comprend un langage pour décrire les tâches, un serveur pour exécuter ces tâches et un SDK pour interagir avec la plateforme. Pour créer quelque chose avec Julep, vous écrivez une description de la tâche en YAML, puis vous exécutez la tâche dans le cloud. - -Julep est conçu pour les tâches lourdes, en plusieurs étapes et de longue durée, et il n'y a aucune limite à la complexité de la tâche. - -LangChain est une **bibliothèque** qui inclut quelques outils et un framework pour créer des chaînes linéaires d'invites et d'outils. Pour créer quelque chose avec LangChain, vous écrivez généralement du code Python qui configure et exécute les chaînes de modèles que vous souhaitez utiliser. - -LangChain pourrait être suffisant et plus rapide à mettre en œuvre pour les cas d'utilisation simples impliquant une chaîne linéaire d'invites et d'appels d'API. - -### En résumé - -Utilisez LangChain lorsque vous devez gérer les interactions des modèles d’IA et les séquences d’invite dans un contexte sans état ou à court terme. - -Choisissez Julep lorsque vous avez besoin d'un framework robuste pour les agents avec état avec des capacités de tâches avancées, des sessions persistantes et une gestion de tâches complexes. +Dans cet exemple, Julep gérera automatiquement les exécutions parallèles, réessayera les étapes ayant échoué, renverra les requêtes API et maintiendra les tâches en cours d'exécution de manière fiable jusqu'à leur achèvement. ## Installation @@ -418,25 +375,24 @@ while (message := input("Enter a message: ")) != "quit": print(response) ``` -> [!TIP] -> Vous pouvez trouver l'exemple Python complet [ici](example.py). - +Vous pouvez trouver l'exemple Python complet [ici](example.py). ## Démarrage rapide de Node.js 🟩 ### Étape 1 : Créer un 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] -> Vous pouvez trouver l'exemple complet de Node.js [ici](example.js). +Vous pouvez trouver l'exemple complet de Node.js [ici](example.js). ## Composants @@ -590,10 +547,12 @@ Julep est composé des éléments suivants : Considérez Julep comme une plateforme qui combine des composants côté client et côté serveur pour vous aider à créer des agents d'IA avancés. Voici comment le visualiser : 1. **Votre code d'application :** -- Vous utilisez le SDK Julep dans votre application pour définir des agents, des tâches et des workflows. + +- Vous pouvez utiliser le SDK Julep dans votre application pour définir des agents, des tâches et des workflows. - Le SDK fournit des fonctions et des classes qui facilitent la configuration et la gestion de ces composants. 2. **Service back-end Julep :** + - Le SDK communique avec le backend Julep via le réseau. - Le backend gère l'exécution des tâches, maintient l'état de la session, stocke les documents et orchestre les flux de travail. @@ -601,11 +560,6 @@ Considérez Julep comme une plateforme qui combine des composants côté client - Au sein de vos workflows, vous pouvez intégrer des outils et services externes. - Le backend facilite ces intégrations, afin que vos agents puissent, par exemple, effectuer des recherches sur le Web, accéder à des bases de données ou appeler des API tierces. -En termes plus simples : -- Julep est une plateforme permettant de créer des agents d'IA avec état. -- Vous utilisez le SDK (comme une boîte à outils) dans votre code pour définir ce que font vos agents. -- Le service backend (que vous pouvez considérer comme le moteur) exécute ces définitions, gère l'état et gère la complexité. - ## Concepts Julep s'appuie sur plusieurs composants techniques clés qui fonctionnent ensemble pour créer de puissants flux de travail d'IA : @@ -636,7 +590,7 @@ graph TD - **Documents** : Objets textes ou données associés à des agents ou utilisateurs, vectorisés et stockés pour la recherche et la récupération sémantiques. - **Exécutions** : instances de tâches qui ont été initiées avec des entrées spécifiques, avec leur propre cycle de vie et leur propre machine d'état. -Pour une explication plus détaillée de ces concepts et de leurs interactions, veuillez vous référer à notre [Documentation sur les concepts](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md). +Pour une explication plus détaillée, reportez-vous à notre [Documentation des concepts](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md). ## Comprendre les tâches @@ -648,138 +602,328 @@ Les tâches sont au cœur du système de workflow de Julep. Elles vous permetten ### Types d'étapes de flux de travail -Les tâches dans Julep peuvent inclure différents types d'étapes, ce qui vous permet de créer des flux de travail complexes et puissants. Voici un aperçu des types d'étapes disponibles, organisés par catégorie : +Les tâches dans Julep peuvent inclure différents types d'étapes, ce qui vous permet de créer des flux de travail complexes et puissants. Voici un aperçu des types d'étapes disponibles : #### Étapes courantes -1. **Invite** : envoyez un message au modèle d’IA et recevez une réponse. - ```yaml - - prompt: "Analyze the following data: {{data}}" - ``` - -2. **Appel d'outil** : Exécutez un outil ou une API intégrée. - ```yaml - - tool: web_search - arguments: - query: "Latest AI developments" - ``` - -3. **Évaluer** : Effectuer des calculs ou manipuler des données. - ```yaml - - evaluate: - average_score: "sum(scores) / len(scores)" - ``` - -4. **Attendre l'entrée** : mettre le flux de travail en pause jusqu'à ce que l'entrée soit reçue. - ```yaml - - wait_for_input: - info: - message: "Please provide additional information." - ``` - -5. **Journal** : Enregistrer une valeur ou un message spécifié. - ```yaml - - log: "Processing completed for item {{item_id}}" - ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Nom À proposSyntaxe
Rapide +Envoyez un message au modèle d'IA et recevez une réponse + + + +```yaml +- prompt: "Analyze the following data: {{data}}" +``` + +
Appel d'outil +Exécuter un outil intégré ou une API + + + +```yaml +- tool: web_search + arguments: + query: "Latest AI developments" +``` + +
Évaluer +Effectuer des calculs ou manipuler des données + + + +```yaml +- evaluate: + average_score: "sum(scores) / len(scores)" +``` + +
Attendre l'entrée +Suspendre le flux de travail jusqu'à ce que les données soient reçues + + + +```yaml +- wait_for_input: + info: + message: "Please provide additional information." +``` + +
Enregistrer +Enregistrer une valeur ou un message spécifié + + + +```yaml +- log: "Processing completed for item {{item_id}}" +``` + +
#### Étapes clé-valeur -6. **Get** : récupérer une valeur à partir d'un magasin clé-valeur. - ```yaml - - get: "user_preference" - ``` + + + + + + + + + + + + + + + + +
Nom À proposSyntaxe
Obtenir +Récupérer une valeur d'un magasin clé-valeur -7. **Set** : attribuez une valeur à une clé dans un magasin clé-valeur. - ```yaml - - set: - user_preference: "dark_mode" - ``` + + +```yaml +- get: "user_preference" +``` + +
Ensemble +Attribuer une valeur à une clé dans un magasin clé-valeur + + + +```yaml +- set: + user_preference: "dark_mode" +``` + +
#### Étapes d'itération -8. **Foreach** : itérer sur une collection et effectuer des étapes pour chaque élément. - ```yaml - - foreach: - in: "data_list" - do: - - log: "Processing item {{_}}" - ``` - -9. **Map-Reduce** : Cartographiez une collection et réduisez les résultats. - ```yaml - - map_reduce: - over: "numbers" - map: - - evaluate: - squared: "_ ** 2" - reduce: "sum(results)" - ``` - -10. **Parallèle** : exécuter plusieurs étapes en parallèle. - ```yaml - - parallel: - - tool: web_search - arguments: - query: "AI news" - - tool: weather_check - arguments: - location: "New York" - ``` + + + + + + + + + + + + + + + + + + + + + + +
Nom À proposSyntaxe
Pour chaque +Itérer sur une collection et effectuer des étapes pour chaque élément + + + +```yaml +- foreach: + in: "data_list" + do: + - log: "Processing item {{_}}" +``` + +
Carte-Réduction +Cartographier une collection et réduire les résultats + + + +```yaml +- map_reduce: + over: "numbers" + map: + - evaluate: + squared: "_ ** 2" + reduce: "sum(results)" +``` + +
Parallèle +Exécuter plusieurs étapes en parallèle + + + +```yaml +- parallel: + - tool: web_search + arguments: + query: "AI news" + - tool: weather_check + arguments: + location: "New York" +``` + +
#### Étapes conditionnelles -11. **If-Else** : Exécution conditionnelle des étapes. - ```yaml - - if: "score > 0.8" + + + + + + + + + + + + + + + + +
Nom À proposSyntaxe
Si-Sinon +Exécution conditionnelle des étapes + + + +```yaml +- if: "score > 0.8" + then: + - log: "High score achieved" + else: + - log: "Score needs improvement" +``` + +
Changer +Exécuter des étapes en fonction de plusieurs conditions + + + +```yaml +- switch: + - case: "category == 'A'" + then: + - log: "Category A processing" + - case: "category == 'B'" then: - - log: "High score achieved" - else: - - log: "Score needs improvement" - ``` - -12. **Switch** : exécuter des étapes en fonction de plusieurs 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: "Category B processing" + - case: "_" # Default case + then: + - log: "Unknown category" +``` + +
#### Autre flux de contrôle -13. **Veille** : met le flux de travail en pause pendant une durée spécifiée. - ```yaml - - sleep: - seconds: 30 - ``` - -14. **Retour** : renvoie une valeur du flux de travail. - ```yaml - - return: - result: "Task completed successfully" - ``` - -15. **Rendement** : Exécutez un sous-flux de travail et attendez sa fin. - ```yaml - - yield: - workflow: "data_processing_subflow" - arguments: - input_data: "{{raw_data}}" - ``` + + + + + + + -Chaque type d'étape remplit un objectif spécifique dans la création de workflows d'IA sophistiqués. Cette catégorisation permet de comprendre les différents flux de contrôle et opérations disponibles dans les tâches Julep. + + + + + + + + + + + + + + + + + + + + +
Nom À proposSyntaxe
Dormir +Suspendre le flux de travail pendant une durée spécifiée -16. **Erreur** : gérez les erreurs en spécifiant un message d’erreur. - ```yaml - - error: "Invalid input provided" - ``` + + +```yaml +- sleep: + seconds: 30 +``` + +
Retour +Renvoyer une valeur du workflow + + + +```yaml +- return: + result: "Task completed successfully" +``` + +
Rendement +Exécuter un sous-workflow et attendre sa fin + + + +```yaml +- yield: + workflow: "data_processing_subflow" + arguments: + input_data: "{{raw_data}}" +``` + +
Erreur +Gérer les erreurs en spécifiant un message d'erreur + + + +```yaml +- error: "Invalid input provided" +``` + +
+ +Chaque type d'étape remplit un objectif spécifique dans la création de workflows d'IA sophistiqués. Cette catégorisation permet de comprendre les différents flux de contrôle et opérations disponibles dans les tâches Julep. ## Types d'outils @@ -793,200 +937,249 @@ Les outils du julep peuvent être l’un des suivants : Il s'agit de signatures de fonctions que vous pouvez attribuer au modèle pour qu'il puisse choisir, de la même manière que fonctionne l'appel de fonctions d'[openai]. Un exemple : -```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 - - main: - - tool: send_notification - arguments: - content: hi +```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 + +main: + - tool: send_notification + arguments: + content: hi ``` - + Chaque fois que julep rencontre une _fonction définie par l'utilisateur_, il s'arrête, rend le contrôle au client et attend que le client exécute l'appel de fonction et renvoie les résultats à julep. > [!TIP] > **Exemple de livre de recettes** : [cookbooks/13-Error_Handling_and_Recovery.py](https://github.com/julep-ai/julep/blob/dev/cookbooks/13-Error_Handling_and_Recovery.py) ### outils `système` + Outils intégrés qui peuvent être utilisés pour appeler les API julep elles-mêmes, comme déclencher l'exécution d'une tâche, ajouter à un champ de métadonnées, etc. Les outils « système » sont intégrés au backend. Ils sont exécutés automatiquement lorsque cela est nécessaire. Ils ne nécessitent aucune action du côté client. - + Par exemple, - - ```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] > **Exemple de livre de recettes** : [cookbooks/10-Document_Management_and_Search.py](https://github.com/julep-ai/julep/blob/dev/cookbooks/10-Document_Management_and_Search.py) - -### Intégrations intégrées + +### « Intégrations » intégrées + Julep est livré avec un certain nombre d'intégrations intégrées (comme décrit dans la section ci-dessous). Les outils « d'intégration » sont directement exécutés sur le backend de Julep. Tous les paramètres supplémentaires dont ils ont besoin au moment de l'exécution peuvent être définis dans les champs « métadonnées » de l'agent/session/utilisateur. > [!TIP] > **Exemple de livre de recettes** : [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) Le backend Julep est livré avec des outils tiers intégrés provenant des fournisseurs suivants : -- [composio](https://composio.dev) \*\* -- [anonyme](https://anon.com) \*\* -- [kits d'outils langchain](https://python.langchain.com/v0.2/docs/integrations/toolkits/). La prise en charge des kits d'outils _Github, Gitlab, Gmail, Jira, MultiOn, Slack_ est prévue. -\*\* Étant donné que _composio_ et _anon_ sont des fournisseurs tiers, leurs outils nécessitent la configuration d'une liaison de compte. +- [composio](https://composio.dev) +- [anonyme](https://anon.com) +- [boîtes à outils langchain](https://python.langchain.com/v0.2/docs/integrations/toolkits/) + +La prise en charge des boîtes à outils _Github, Gitlab, Gmail, Jira, MultiOn, Slack_ est prévue. +Étant donné que _composio_ et _anon_ sont des fournisseurs tiers, leurs outils nécessitent la configuration d'une liaison de compte. -### Appels directs `api_call` +### Appels directs `api_calls` julep peut également effectuer directement des appels d'API lors des exécutions de workflows sous forme d'appels d'outils. Comme pour `integration`, des paramètres d'exécution supplémentaires sont chargés à partir des champs `metadata`. - + Par exemple, - - ```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 - ``` + +```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 +``` ## Intégrations Julep prend en charge diverses intégrations qui étendent les capacités de vos agents IA. Voici une liste des intégrations disponibles et de leurs arguments pris en charge : -### Recherche courageuse + + + + + -### Base de navigateur + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Recherche courageuse ```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] -> **Exemple de livre de recettes** : [cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + + +**Exemple de livre de recettes** : [cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + +
Base de navigateur ```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 ``` -### E-mail +
E-mail ```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] -> **Exemple de livre de recettes** : [cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + -### Araignée +**Exemple de livre de recettes** : [cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + +
Araignée ```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] -> **Exemple de livre de recettes** : [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + -### Météo +**Exemple de livre de recettes** : [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + +
Météo ```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] -> **Exemple de livre de recettes** : [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + + +**Exemple de livre de recettes** : [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) -### Wikipédia +
Wikipédia ```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] -> **Exemple de livre de recettes** : [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + + +**Exemple de livre de recettes** : [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + +
-Ces intégrations peuvent être utilisées dans vos tâches pour étendre les capacités de vos agents IA. Pour des informations plus détaillées sur la manière d'utiliser ces intégrations dans vos workflows, veuillez consulter notre [Documentation sur les intégrations](https://docs.julep.ai/integrations). +Pour plus de détails, reportez-vous à notre [Documentation sur les intégrations](https://docs.julep.ai/integrations). ## Autres fonctionnalités @@ -1054,9 +1247,11 @@ results = client.agents.docs.search( ## Démarrage rapide local **Exigences**: + - dernier docker compose installé **Mesures**: + 1. `git clone https://github.com/julep-ai/julep.git` 2. `cd julep` 3. `docker volume create cozo_backup` @@ -1077,10 +1272,45 @@ Explorez notre documentation API complète pour en savoir plus sur les agents, l - [API des tâches](https://api.julep.ai/api/docs#tag/tasks) - [API d'exécution](https://api.julep.ai/api/docs#tag/executions) +***** + +## Pourquoi Julep vs. LangChain ? + +### Différents cas d'utilisation + +Considérez LangChain et Julep comme des outils avec des objectifs différents au sein de la pile de développement de l’IA. + +LangChain est idéal pour créer des séquences d'invites et gérer les interactions avec les LLM. Il dispose d'un vaste écosystème avec de nombreuses intégrations prédéfinies, ce qui le rend pratique si vous souhaitez mettre en place quelque chose rapidement. LangChain s'adapte bien aux cas d'utilisation simples qui impliquent une chaîne linéaire d'invites et d'appels d'API. + +Julep, en revanche, s'intéresse davantage à la création d'agents d'IA persistants capables de conserver le contexte lors d'interactions à long terme. Il est idéal lorsque vous avez besoin de flux de travail complexes impliquant des tâches en plusieurs étapes, une logique conditionnelle et une intégration avec divers outils ou API directement dans le processus de l'agent. Il est conçu dès le départ pour gérer les sessions persistantes et les flux de travail complexes. + +Utilisez Julep si vous imaginez créer un assistant IA complexe qui doit : + +- Suivez les interactions des utilisateurs sur plusieurs jours ou semaines. +- Exécutez des tâches planifiées, comme l'envoi de résumés quotidiens ou la surveillance de sources de données. +- Prendre des décisions basées sur des interactions antérieures ou des données stockées. +- Interagir avec plusieurs services externes dans le cadre de son flux de travail. -
+Ensuite, Julep fournit l’infrastructure pour prendre en charge tout cela sans que vous ayez à le construire à partir de zéro. + +### Facteur de forme différent + +Julep est une **plateforme** qui comprend un langage pour décrire les workflows, un serveur pour exécuter ces workflows et un SDK pour interagir avec la plateforme. Pour créer quelque chose avec Julep, vous écrivez une description du workflow en YAML, puis vous exécutez le workflow dans le cloud. + +Julep est conçu pour les flux de travail lourds, en plusieurs étapes et de longue durée, et il n'y a aucune limite à la complexité du flux de travail. + +LangChain est une **bibliothèque** qui inclut quelques outils et un framework pour créer des chaînes linéaires d'invites et d'outils. Pour créer quelque chose avec LangChain, vous écrivez généralement du code Python qui configure et exécute les chaînes de modèles que vous souhaitez utiliser. + +LangChain pourrait être suffisant et plus rapide à mettre en œuvre pour les cas d'utilisation simples impliquant une chaîne linéaire d'invites et d'appels d'API. + +### En résumé + +Utilisez LangChain lorsque vous devez gérer les interactions LLM et les séquences d'invite dans un contexte sans état ou à court terme. + +Choisissez Julep lorsque vous avez besoin d'un framework robuste pour les agents avec état avec des capacités de workflow avancées, des sessions persistantes et une orchestration de tâches complexes. + + - diff --git a/README-JA.md b/README-JA.md index dc856698a..9f4ecb2ae 100644 --- a/README-JA.md +++ b/README-JA.md @@ -1,6 +1,6 @@ [English](README.md) | [中文翻译](README-CN.md) | [日本語翻訳](README-JA.md) | [French](README-FR.md) -
+
julep
@@ -15,7 +15,6 @@ リンクトイン

-

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

-***** +--- > [!注意] > 👨‍💻 devfest.ai イベントに参加しませんか? [Discord](https://discord.com/invite/JTSBGRZrzj) に参加して、以下の詳細を確認してください。 -> +> > API キーを [こちら](https://dashboard-dev.julep.ai) から取得します。
@@ -64,47 +63,44 @@ Julep プロジェクトに新しい貢献者を迎えられることを嬉し
-

📖 Table of Contents

- -- [簡単な例](#%E7%B0%A1%E5%8D%98%E3%81%AA%E4%BE%8B) -- [主な特徴](#%E4%B8%BB%E3%81%AA%E7%89%B9%E5%BE%B4) -- [Julep と LangChain を比較する理由](#julep-%E3%81%A8-langchain-%E3%82%92%E6%AF%94%E8%BC%83%E3%81%99%E3%82%8B%E7%90%86%E7%94%B1) - - [さまざまなユースケース](#%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9) - - [異なるフォームファクタ](#%E7%95%B0%E3%81%AA%E3%82%8B%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%83%95%E3%82%A1%E3%82%AF%E3%82%BF) -- [インストール](#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB) -- [Python クイックスタート 🐍](#python-%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88-) - - [ステップ 1: エージェントを作成する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%97-1-%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B) - - [ステップ2: ストーリーと漫画を生成するタスクを作成する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%972-%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AA%E3%83%BC%E3%81%A8%E6%BC%AB%E7%94%BB%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B) - - [ステップ3: タスクを実行する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%973-%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B) - - [ステップ4: エージェントとチャットする](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%974-%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%81%A8%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%81%99%E3%82%8B) -- [Node.js クイックスタート 🟩](#nodejs-%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88-) - - [ステップ 1: エージェントを作成する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%97-1-%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B-1) - - [ステップ2: ストーリーと漫画を生成するタスクを作成する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%972-%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AA%E3%83%BC%E3%81%A8%E6%BC%AB%E7%94%BB%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B-1) - - [ステップ3: タスクを実行する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%973-%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B-1) - - [ステップ4: エージェントとチャットする](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%974-%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%81%A8%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%81%99%E3%82%8B-1) -- [コンポーネント](#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88) - - [メンタルモデル](#%E3%83%A1%E3%83%B3%E3%82%BF%E3%83%AB%E3%83%A2%E3%83%87%E3%83%AB) -- [コンセプト](#%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88) -- [タスクを理解する](#%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B) - - [ワークフローステップの種類](#%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E3%81%AE%E7%A8%AE%E9%A1%9E) -- [ツールの種類](#%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AE%E7%A8%AE%E9%A1%9E) - - [ユーザー定義の `function`](#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%AE%9A%E7%BE%A9%E3%81%AE-function) - - [`システム` ツール](#%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0-%E3%83%84%E3%83%BC%E3%83%AB) - - [組み込みの `integration`](#%E7%B5%84%E3%81%BF%E8%BE%BC%E3%81%BF%E3%81%AE-integration) - - [直接の `api_call`](#%E7%9B%B4%E6%8E%A5%E3%81%AE-api_call) -- [統合](#%E7%B5%B1%E5%90%88) - - [ブレイブサーチ](#%E3%83%96%E3%83%AC%E3%82%A4%E3%83%96%E3%82%B5%E3%83%BC%E3%83%81) - - [ブラウザベース](#%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%83%99%E3%83%BC%E3%82%B9) - - [メール](#%E3%83%A1%E3%83%BC%E3%83%AB) - - [スパイダー](#%E3%82%B9%E3%83%91%E3%82%A4%E3%83%80%E3%83%BC) - - [ウィキペディア](#%E3%82%A6%E3%82%A3%E3%82%AD%E3%83%9A%E3%83%87%E3%82%A3%E3%82%A2) -- [その他の機能](#%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E6%A9%9F%E8%83%BD) - - [エージェントへのツールの追加](#%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%81%B8%E3%81%AE%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AE%E8%BF%BD%E5%8A%A0) - - [セッションとユーザーの管理](#%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E7%AE%A1%E7%90%86) - - [ドキュメントの統合と検索](#%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AE%E7%B5%B1%E5%90%88%E3%81%A8%E6%A4%9C%E7%B4%A2) -- [ローカルクイックスタート](#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88) -- [SDK リファレンス](#sdk-%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9) -- [APIリファレンス](#api%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9) +

📖 目次

+ +- [はじめに](#introduction) +- [主な特徴](#key-features) +- [簡単な例](#quick-example) +- [インストール](#installation) +- [Python クイックスタート 🐍](#python-quick-start-) +- [ステップ 1: エージェントを作成する](#step-1-create-an-agent) +- [ステップ 2: ストーリーとコミック ストリップを生成するタスクを作成する](#step-2-create-a-task-that-generates-a-story-and-comic-strip) +- [ステップ 3: タスクを実行する](#step-3-execute-the-task) +- [ステップ 4: エージェントとチャットする](#step-4-chat-with-the-agent) +- [Node.js クイック スタート 🟩](#nodejs-quick-start-) +- [ステップ 1: エージェントを作成する](#step-1-create-an-agent-1) +- [ステップ 2: ストーリーとコミック ストリップを生成するタスクを作成する](#step-2-create-a-task-that-generates-a-story-and-comic-strip-1) +- [ステップ 3: タスクを実行する](#step-3-execute-the-task-1) +- [ステップ 4: エージェントとチャットする](#step-4-chat-with-the-agent-1) +- [コンポーネント](#components) +- [メンタルモデル](#mental-model) +- [コンセプト](#concepts) +- [タスクの理解](#understanding-tasks) +- [ワークフロー ステップの種類](#types-of-workflow-steps) +- [ツールの種類](#tool-types) +- [ユーザー定義の `functions`](#user-defined-functions) +- [`システム` ツール](#system-tools) +- [組み込みの `integrations`](#built-in-integrations) +- [直接の `api_calls`](#direct-api_calls) +- [統合](#integrations) +- [その他の機能](#other-features) +- [エージェントへのツールの追加](#adding-tools-to-agents) +- [セッションとユーザーの管理](#managing-sessions-and-users) +- [ドキュメントの統合と検索](#document-integration-and-search) +- [ローカルクイックスタート](#local-quickstart) +- [SDKリファレンス](#sdk-reference) +- [APIリファレンス](#api-reference) +- [なぜ Julep 対 LangChain?](#why-julep-vs-langchain) +- [さまざまなユースケース](#different-use-cases) +- [異なるフォームファクター](#different-form-factor) +- [要約](#in-summary)
@@ -118,6 +114,7 @@ Julep を使用すると、意思決定、ループ、並列処理、多数の 多くの AI アプリケーションは、分岐が最小限の、プロンプトと API 呼び出しの単純な線形チェーンに制限されていますが、Julep はより複雑なシナリオを処理できるように構築されています。 サポート対象: + - 複雑で多段階のプロセス - ダイナミックな意思決定 - 並列実行 @@ -125,9 +122,22 @@ Julep を使用すると、意思決定、ループ、並列処理、多数の > [!ヒント] > 単純な質問に答えるだけでなく、複雑なタスクを処理し、過去のやり取りを記憶し、場合によっては他のツールや API も使用できる AI エージェントを構築したいとします。そこで Julep の出番です。 +## 主な特徴 + +1. 🧠 **永続的な AI エージェント**: 長期にわたるやり取りを通じてコン​​テキストと情報を記憶します。 +2. 💾 **ステートフル セッション**: 過去のやり取りを追跡して、パーソナライズされた応答を提供します。 +3. 🔄 **複数ステップのタスク**: ループと意思決定を使用して、複雑な複数ステップのプロセスを構築します。 +4. ⏳ **タスク管理**: 無期限に実行される可能性のある長時間実行タスクを処理します。 +5. 🛠️ **組み込みツール**: タスクで組み込みツールと外部 API を使用します。 +6. 🔧 **自己修復**: Julep は失敗したステップを自動的に再試行し、メッセージを再送信し、一般的にタスクがスムーズに実行されるようにします。 +7. 📚 **RAG**: Julep のドキュメント ストアを使用して、独自のデータを取得して使用するためのシステムを構築します。 + +Julep は、単純なプロンプト応答モデルを超えた AI ユースケースを必要とするアプリケーションに最適です。 + ## 簡単な例 次のことができる研究 AI エージェントを想像してください。 + 1. トピックを取り上げ、 2. そのトピックについて100個の検索クエリを考えます。 3. ウェブ検索を並行して実行する @@ -149,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 @@ -171,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}}** - {{_}} + {{_}} ``` -> [!ヒント] -> Julep は、長期的なインタラクションを通じてコン​​テキストと状態を維持できる AI エージェントを構築する場合に非常に便利です。複雑な複数ステップのワークフローを設計し、さまざまなツールや API をエージェントのプロセスに直接統合するのに最適です。 -> -> この例では、Julep は並列実行を自動的に管理し、失敗したステップを再試行し、API リクエストを再送信し、タスクが完了するまで確実に実行し続けます。 - -## 主な特徴 - -1. 🧠 **永続的な AI エージェント**: 長期にわたるやり取りを通じてコン​​テキストと情報を記憶します。 -2. 💾 **ステートフル セッション**: 過去のやり取りを追跡して、パーソナライズされた応答を提供します。 -3. 🔄 **複数ステップのタスク**: ループと意思決定を使用して、複雑な複数ステップのプロセスを構築します。 -4. ⏳ **タスク管理**: 無期限に実行される可能性のある長時間実行タスクを処理します。 -5. 🛠️ **組み込みツール**: タスクで組み込みツールと外部 API を使用します。 -6. 🔧 **自己修復**: Julep は失敗したステップを自動的に再試行し、メッセージを再送信し、タスクをスムーズに実行し続けます。 -7. 📚 **RAG**: Julep のドキュメント ストアを使用して、独自のデータを取得して使用するためのシステムを構築します。 - -Julep は、単純なプロンプト応答モデルを超えた AI ユースケースを必要とするアプリケーションに最適です。 - -## Julep と LangChain を比較する理由 - -### さまざまなユースケース - -LangChain と Julep は、AI 開発スタック内で異なる重点を置いたツールと考えてください。 - -LangChain は、プロンプトのシーケンスを作成し、AI モデルとのやり取りを管理するのに最適です。多数の事前構築された統合を備えた大規模なエコシステムを備えているため、何かをすぐに立ち上げて実行したい場合に便利です。LangChain は、プロンプトと API 呼び出しの線形チェーンを含む単純なユースケースに適しています。 - -一方、Julep は、長期的なインタラクションを通じて物事を記憶できる永続的な AI エージェントの構築に重点を置いています。エージェントのプロセス内で複数のステップ、意思決定、さまざまなツールや API との直接統合を伴う複雑なタスクが必要な場合に効果を発揮します。永続的なセッションと複雑なタスクを管理するために、ゼロから設計されています。 - -以下のことが必要となる複雑な AI アシスタントの構築を考えている場合には、Julep を使用してください。 - -- 数日または数週間にわたってユーザーのインタラクションを追跡します。 -- 毎日のサマリーの送信やデータ ソースの監視などのスケジュールされたタスクを実行します。 -- 以前のやり取りや保存されたデータに基づいて決定を下します。 -- タスクの一部として複数の外部サービスと対話します。 - -そして、Julep は、ゼロから構築する必要なく、これらすべてをサポートするインフラストラクチャを提供します。 - -### 異なるフォームファクタ - -Julep は、タスクを記述するための言語、それらのタスクを実行するためのサーバー、プラットフォームと対話するための SDK を含む **プラットフォーム** です。Julep で何かを構築するには、タスクの説明を `YAML` で記述し、クラウドでタスクを実行します。 - -Julep は、負荷の高い、複数のステップから成る、長時間実行されるタスク向けに構築されており、タスクの複雑さに制限はありません。 - -LangChain は、プロンプトとツールの線形チェーンを構築するためのいくつかのツールとフレームワークを含む **ライブラリ** です。LangChain を使用して何かを構築するには、通常、使用するモデル チェーンを設定して実行する Python コードを記述します。 - -LangChain は、プロンプトと API 呼び出しの線形チェーンを含む単純なユースケースでは十分であり、実装も迅速です。 - -### 要約すれば - -ステートレスまたは短期的なコンテキストで AI モデルのインタラクションとプロンプト シーケンスを管理する必要がある場合は、LangChain を使用します。 - -高度なタスク機能、永続的なセッション、複雑なタスク管理を備えたステートフル エージェント用の堅牢なフレームワークが必要な場合は、Julep を選択してください。 +この例では、Julep は並列実行を自動的に管理し、失敗したステップを再試行し、API リクエストを再送信し、タスクが完了するまで確実に実行し続けます。 ## インストール @@ -415,25 +375,24 @@ while (message := input("Enter a message: ")) != "quit": print(response) ``` -> [!ヒント] -> 完全な Python の例は [ここ](example.py) にあります。 - +完全な Python の例は [ここ](example.py) にあります。 ## Node.js クイックスタート 🟩 ### ステップ 1: エージェントを作成する ```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 @@ -513,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); } @@ -536,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; } @@ -567,8 +528,7 @@ async function runExample() { runExample().catch(console.error); ``` -> [!ヒント] -> 完全な Node.js の例は [ここ](example.js) にあります。 +完全な Node.js の例は [ここ](example.js) にあります。 ## コンポーネント @@ -587,10 +547,12 @@ Julep は次のコンポーネントで構成されています。 Julep は、クライアント側とサーバー側の両方のコンポーネントを組み合わせて、高度な AI エージェントの構築を支援するプラットフォームと考えてください。これを視覚化する方法は次のとおりです。 1. **アプリケーションコード:** -- アプリケーションで Julep SDK を使用して、エージェント、タスク、ワークフローを定義します。 + +- アプリケーションで Julep SDK を使用して、エージェント、タスク、ワークフローを定義できます。 - SDK は、これらのコンポーネントのセットアップと管理を容易にする関数とクラスを提供します。 2. **Julep バックエンド サービス:** + - SDK はネットワーク経由で Julep バックエンドと通信します。 - バックエンドは、タスクの実行を処理し、セッション状態を維持し、ドキュメントを保存し、ワークフローを調整します。 @@ -598,11 +560,6 @@ Julep は、クライアント側とサーバー側の両方のコンポーネ - ワークフロー内で、外部ツールやサービスを統合できます。 - バックエンドはこれらの統合を容易にするため、エージェントは、たとえば、Web 検索を実行したり、データベースにアクセスしたり、サードパーティの API を呼び出したりすることができます。 -もっと簡単に言うと: -- Julep は、ステートフル AI エージェントを構築するためのプラットフォームです。 -- コード内で SDK (ツールキットのようなもの) を使用して、エージェントの動作を定義します。 -- バックエンド サービス (エンジンと考えることができます) は、これらの定義を実行し、状態を管理し、複雑さを処理します。 - ## コンセプト Julep は、強力な AI ワークフローを作成するために連携するいくつかの主要な技術コンポーネントに基づいて構築されています。 @@ -633,7 +590,7 @@ graph TD - **ドキュメント**: エージェントまたはユーザーに関連付けられたテキストまたはデータ オブジェクト。セマンティック検索と取得のためにベクトル化され、保存されます。 - **実行**: 特定の入力で開始され、独自のライフサイクルとステート マシンを持つタスクのインスタンス。 -これらの概念とその相互作用の詳細な説明については、[概念ドキュメント](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)を参照してください。 +より詳細な説明については、[コンセプトのドキュメント](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)を参照してください。 ## タスクを理解する @@ -645,138 +602,328 @@ graph TD ### ワークフローステップの種類 -Julep のタスクにはさまざまな種類のステップを含めることができるため、複雑で強力なワークフローを作成できます。利用可能なステップの種類の概要をカテゴリ別にまとめると次のようになります。 +Julep のタスクにはさまざまな種類のステップを含めることができるため、複雑で強力なワークフローを作成できます。利用可能なステップの種類の概要は次のとおりです。 #### 一般的な手順 -1. **プロンプト**: AI モデルにメッセージを送信し、応答を受信します。 - ```yaml - - prompt: "Analyze the following data: {{data}}" - ``` - -2. **ツール呼び出し**: 統合ツールまたは API を実行します。 - ```yaml - - tool: web_search - arguments: - query: "Latest AI developments" - ``` - -3. **評価**: 計算を実行したり、データを操作したりします。 - ```yaml - - evaluate: - average_score: "sum(scores) / len(scores)" - ``` - -4. **入力を待機**: 入力が受信されるまでワークフローを一時停止します。 - ```yaml - - wait_for_input: - info: - message: "Please provide additional information." - ``` - -5. **ログ**: 指定された値またはメッセージをログに記録します。 - ```yaml - - log: "Processing completed for item {{item_id}}" - ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名前 について構文
プロンプト +AIモデルにメッセージを送信し、応答を受け取る + + + +```yaml +- prompt: "Analyze the following data: {{data}}" +``` + +
ツールコール +統合ツールまたはAPIを実行する + + + +```yaml +- tool: web_search + arguments: + query: "Latest AI developments" +``` + +
評価する +計算を実行したりデータを操作したりする + + + +```yaml +- evaluate: + average_score: "sum(scores) / len(scores)" +``` + +
入力を待つ +入力を受信するまでワークフローを一時停止する + + + +```yaml +- wait_for_input: + info: + message: "Please provide additional information." +``` + +
ログ +指定された値またはメッセージをログに記録する + + + +```yaml +- log: "Processing completed for item {{item_id}}" +``` + +
#### キー値ステップ -6. **Get**: キー値ストアから値を取得します。 - ```yaml - - get: "user_preference" - ``` + + + + + + + + + + + + + + + + +
名前 について構文
得る +キーバリューストアから値を取得する -7. **Set**: キー値ストア内のキーに値を割り当てます。 - ```yaml - - set: - user_preference: "dark_mode" - ``` + + +```yaml +- get: "user_preference" +``` + +
セット +キーバリューストア内のキーに値を割り当てる + + + +```yaml +- set: + user_preference: "dark_mode" +``` + +
#### 反復ステップ -8. **Foreach**: コレクションを反復処理し、各項目に対して手順を実行します。 - ```yaml - - foreach: - in: "data_list" - do: - - log: "Processing item {{_}}" - ``` - -9. **Map-Reduce**: コレクションをマップし、結果を縮小します。 - ```yaml - - map_reduce: - over: "numbers" - map: - - evaluate: - squared: "_ ** 2" - reduce: "sum(results)" - ``` - -10. **並列**: 複数のステップを並列に実行します。 - ```yaml - - parallel: - - tool: web_search - arguments: - query: "AI news" - - tool: weather_check - arguments: - location: "New York" - ``` + + + + + + + + + + + + + + + + + + + + + + +
名前 について構文
フォア +コレクションを反復処理し、各アイテムに対して手順を実行します。 + + + +```yaml +- foreach: + in: "data_list" + do: + - log: "Processing item {{_}}" +``` + +
マップリデュース +コレクションをマップして結果を減らす + + + +```yaml +- map_reduce: + over: "numbers" + map: + - evaluate: + squared: "_ ** 2" + reduce: "sum(results)" +``` + +
平行 +複数のステップを並行して実行する + + + +```yaml +- parallel: + - tool: web_search + arguments: + query: "AI news" + - tool: weather_check + arguments: + location: "New York" +``` + +
#### 条件付きステップ -11. **If-Else**: ステップの条件付き実行。 - ```yaml - - if: "score > 0.8" + + + + + + + + + + + + + + + + +
名前 について構文
If-Else +ステップの条件付き実行 + + + +```yaml +- if: "score > 0.8" + then: + - log: "High score achieved" + else: + - log: "Score needs improvement" +``` + +
スイッチ +複数の条件に基づいてステップを実行する + + + +```yaml +- switch: + - case: "category == 'A'" then: - - log: "High score achieved" - else: - - log: "Score needs improvement" - ``` - -12. **スイッチ**: 複数の条件に基づいてステップを実行します。 - ```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: "Category A processing" + - case: "category == 'B'" + then: + - log: "Category B processing" + - case: "_" # Default case + then: + - log: "Unknown category" +``` + +
#### その他の制御フロー -13. **スリープ**: 指定した期間、ワークフローを一時停止します。 - ```yaml - - sleep: - seconds: 30 - ``` - -14. **Return**: ワークフローから値を返します。 - ```yaml - - return: - result: "Task completed successfully" - ``` - -15. **Yield**: サブワークフローを実行し、完了を待ちます。 - ```yaml - - yield: - workflow: "data_processing_subflow" - arguments: - input_data: "{{raw_data}}" - ``` + + + + + + + -各ステップ タイプは、高度な AI ワークフローを構築する上で特定の目的を果たします。この分類は、Julep タスクで使用できるさまざまな制御フローと操作を理解するのに役立ちます。 + + + + + + + + + + + + + + + + + + + + + +
名前 について構文
寝る +指定した期間ワークフローを一時停止する -16. **エラー**: エラー メッセージを指定してエラーを処理します。 - ```yaml - - error: "Invalid input provided" - ``` + + +```yaml +- sleep: + seconds: 30 +``` + +
戻る +ワークフローから値を返す + + +```yaml +- return: + result: "Task completed successfully" +``` + +
収率 +サブワークフローを実行し、完了を待ちます + + + +```yaml +- yield: + workflow: "data_processing_subflow" + arguments: + input_data: "{{raw_data}}" +``` + +
エラー +エラーメッセージを指定してエラーを処理する + + + +```yaml +- error: "Invalid input provided" +``` + +
+ +各ステップ タイプは、高度な AI ワークフローを構築する上で特定の目的を果たします。この分類は、Julep タスクで使用できるさまざまな制御フローと操作を理解するのに役立ちます。 ## ツールの種類 @@ -786,204 +933,253 @@ Julep のタスクにはさまざまな種類のステップを含めること julep のツールは次のいずれかになります。 -### ユーザー定義の `function` +### ユーザー定義の `functions` これらは、[openai] の関数呼び出しの仕組みと同様に、モデルに選択させることができる関数シグネチャです。例: -```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 - - main: - - tool: send_notification - arguments: - content: hi +```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 + +main: + - tool: send_notification + arguments: + content: hi ``` - -julep は、_ユーザー定義関数_ に遭遇するたびに一時停止し、制御をクライアントに戻し、クライアントが関数呼び出しを実行して結果を julep に返すのを待ちます。 + +julep は、_ユーザー定義関数_ に遭遇するたびに一時停止し、クライアントに制御を戻し、クライアントが関数呼び出しを実行して結果を julep に返すのを待ちます。 > [!ヒント] > **サンプルクックブック**: [cookbooks/13-Error_Handling_and_Recovery.py](https://github.com/julep-ai/julep/blob/dev/cookbooks/13-Error_Handling_and_Recovery.py) ### `システム` ツール + タスク実行のトリガー、メタデータ フィールドへの追加など、julep API 自体を呼び出すために使用できる組み込みツール。 `system` ツールはバックエンドに組み込まれています。必要に応じて自動的に実行されます。クライアント側からのアクションは必要ありません。 - + 例えば、 - - ```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 +``` > [!ヒント] > **サンプルクックブック**: [cookbooks/10-Document_Management_and_Search.py​​](https://github.com/julep-ai/julep/blob/dev/cookbooks/10-Document_Management_and_Search.py​​) - -### 組み込みの `integration` -Julep には、多数の組み込み統合が付属しています (以下のセクションで説明)。`integration` ツールは、julep バックエンドで直接実行されます。実行時に必要な追加パラメータは、エージェント/セッション/ユーザーの `metadata` フィールドで設定できます。 + +### 組み込みの `integrations` + +Julep には、いくつかの組み込み統合が付属しています (以下のセクションで説明)。`integration` ツールは、julep バックエンドで直接実行されます。実行時に必要な追加パラメータは、エージェント/セッション/ユーザーの `metadata` フィールドで設定できます。 > [!ヒント] > **サンプルクックブック**: [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) julep バックエンドには、次のプロバイダーからの統合サードパーティ ツールが付属しています。 -- [composio](https://composio.dev) \*\* -- [匿名](https://anon.com) \*\* -- [langchain ツールキット](https://python.langchain.com/v0.2/docs/integrations/toolkits/)。_Github、Gitlab、Gmail、Jira、MultiOn、Slack_ ツールキットのサポートが計画されています。 -\*\* _composio_ と _anon_ はサードパーティプロバイダーであるため、それらのツールではアカウントリンクを設定する必要があります。 +- [composio](https://composio.dev) +- [匿名](https://anon.com) +- [langchain ツールキット](https://python.langchain.com/v0.2/docs/integrations/toolkits/) +_Github、Gitlab、Gmail、Jira、MultiOn、Slack_ ツールキットのサポートが計画されています。 -### 直接の `api_call` +_composio_ と _anon_ はサードパーティプロバイダーであるため、それらのツールではアカウントリンクを設定する必要があります。 + +### 直接の `api_calls` julep は、ワークフロー実行中にツール呼び出しとして直接 API 呼び出しを行うこともできます。`integration` と同様に、追加のランタイム パラメータは `metadata` フィールドから読み込まれます。 - + 例えば、 - - ```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 - ``` + +```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 +``` ## 統合 Julep は、AI エージェントの機能を拡張するさまざまな統合をサポートしています。利用可能な統合とサポートされている引数のリストは次のとおりです。 -### ブレイブサーチ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
勇敢な検索 ```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 ``` -> [!ヒント] -> **サンプルクックブック**: [cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + -### ブラウザベース +**サンプルクックブック**: [cookbooks/03-SmartResearcher_With_WebSearch.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/03-SmartResearcher_With_WebSearch.ipynb) + +
ブラウザベース ```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 ``` -### メール +
メール ```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 ``` -> [!ヒント] -> **サンプルクックブック**: [cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + -### スパイダー +**サンプルクックブック**: [cookbooks/00-Devfest-Email-Assistant.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/00-Devfest-Email-Assistant.ipynb) + +
スパイダー ```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 ``` -> [!ヒント] -> **サンプルクックブック**: [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + -### 天気 +**サンプルクックブック**: [cookbooks/01-Website_Crawler_using_Spider.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/01-Website_Crawler_using_Spider.ipynb) + +
天気 ```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 ``` -> [!ヒント] -> **サンプルクックブック**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + + +**サンプルクックブック**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) -### ウィキペディア +
ウィキペディア ```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 ``` -> [!ヒント] -> **サンプルクックブック**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + + +**サンプルクックブック**: [cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb](https://github.com/julep-ai/julep/blob/dev/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb) + +
-これらの統合をタスク内で使用して、AI エージェントの機能を拡張できます。ワークフローでこれらの統合を使用する方法の詳細については、[統合ドキュメント](https://docs.julep.ai/integrations)を参照してください。 +詳細については、[統合ドキュメント](https://docs.julep.ai/integrations)を参照してください。 ## その他の機能 @@ -1051,9 +1247,11 @@ results = client.agents.docs.search( ## ローカルクイックスタート **要件**: + - 最新の docker compose がインストールされている **手順**: + 1. `git clone https://github.com/julep-ai/julep.git` 2. `cd ジュレップ` 3. `docker volume create cozo_backup` @@ -1074,10 +1272,45 @@ results = client.agents.docs.search( - [タスク API](https://api.julep.ai/api/docs#tag/tasks) - [実行API](https://api.julep.ai/api/docs#tag/executions) +***** + +## Julep と LangChain を比較する理由 + +### さまざまなユースケース + +LangChain と Julep は、AI 開発スタック内で異なる重点を置いたツールと考えてください。 + +LangChain は、プロンプトのシーケンスを作成し、LLM とのやり取りを管理するのに最適です。多数の事前構築された統合を備えた大規模なエコシステムを備えているため、何かをすぐに起動して実行したい場合に便利です。LangChain は、プロンプトと API 呼び出しの線形チェーンを含む単純なユースケースに適しています。 + +一方、Julep は、長期的なインタラクションでコンテキストを維持できる永続的な AI エージェントの構築に重点を置いています。複数ステップのタスク、条件付きロジック、エージェントのプロセス内で直接さまざまなツールや API との統合を伴う複雑なワークフローが必要な場合に効果を発揮します。永続的なセッションと複雑なワークフローを管理するために、ゼロから設計されています。 + +以下のことが必要となる複雑な AI アシスタントの構築を考えている場合には、Julep を使用してください。 + +- 数日または数週間にわたってユーザーのインタラクションを追跡します。 +- 毎日のサマリーの送信やデータ ソースの監視などのスケジュールされたタスクを実行します。 +- 以前のやり取りや保存されたデータに基づいて決定を下します。 +- ワークフローの一部として複数の外部サービスと対話します。 -
+そして、Julep は、ゼロから構築する必要なく、これらすべてをサポートするインフラストラクチャを提供します。 + +### 異なるフォームファクタ + +Julep は、ワークフローを記述するための言語、それらのワークフローを実行するためのサーバー、およびプラットフォームと対話するための SDK を含む **プラットフォーム** です。Julep で何かを構築するには、ワークフローの説明を `YAML` で記述し、クラウドでワークフローを実行します。 + +Julep は、負荷の高い、複数のステップから成る、長時間実行されるワークフロー向けに構築されており、ワークフローの複雑さに制限はありません。 + +LangChain は、プロンプトとツールの線形チェーンを構築するためのいくつかのツールとフレームワークを含む **ライブラリ** です。LangChain を使用して何かを構築するには、通常、使用するモデル チェーンを設定して実行する Python コードを記述します。 + +LangChain は、プロンプトと API 呼び出しの線形チェーンを含む単純なユースケースでは十分であり、実装も迅速です。 + +### 要約すれば + +ステートレスまたは短期的なコンテキストで LLM インタラクションとプロンプト シーケンスを管理する必要がある場合は、LangChain を使用します。 + +高度なワークフロー機能、永続的なセッション、複雑なタスク オーケストレーションを備えたステートフル エージェント用の堅牢なフレームワークが必要な場合は、Julep を選択してください。 + + - diff --git a/agents-api/agents_api/activities/embed_docs.py b/agents-api/agents_api/activities/embed_docs.py index bbdc66043..0dbf7f03b 100644 --- a/agents-api/agents_api/activities/embed_docs.py +++ b/agents-api/agents_api/activities/embed_docs.py @@ -7,11 +7,13 @@ from temporalio import activity from ..clients import cozo, litellm +from ..common.storage_handler import auto_blob_store from ..env import testing from ..models.docs.embed_snippets import embed_snippets as embed_snippets_query from .types import EmbedDocsPayload +@auto_blob_store @beartype async def embed_docs( payload: EmbedDocsPayload, cozo_client=None, max_batch_size: int = 100 diff --git a/agents-api/agents_api/activities/excecute_api_call.py b/agents-api/agents_api/activities/excecute_api_call.py index 956ca9370..1d01c45ea 100644 --- a/agents-api/agents_api/activities/excecute_api_call.py +++ b/agents-api/agents_api/activities/excecute_api_call.py @@ -6,12 +6,9 @@ from temporalio import activity from ..autogen.openapi_model import ApiCallDef - -# from ..clients import integrations +from ..common.storage_handler import auto_blob_store from ..env import testing -# from ..models.tools import get_tool_args_from_metadata - class RequestArgs(TypedDict): content: Optional[str] @@ -23,6 +20,7 @@ class RequestArgs(TypedDict): headers: Optional[dict[str, str]] +@auto_blob_store @beartype async def execute_api_call( api_call: ApiCallDef, diff --git a/agents-api/agents_api/activities/execute_integration.py b/agents-api/agents_api/activities/execute_integration.py index 964ad6e12..70f7009d1 100644 --- a/agents-api/agents_api/activities/execute_integration.py +++ b/agents-api/agents_api/activities/execute_integration.py @@ -6,10 +6,12 @@ from ..autogen.openapi_model import IntegrationDef from ..clients import integrations from ..common.protocol.tasks import StepContext +from ..common.storage_handler import auto_blob_store from ..env import testing from ..models.tools import get_tool_args_from_metadata +@auto_blob_store @beartype async def execute_integration( context: StepContext, diff --git a/agents-api/agents_api/activities/execute_system.py b/agents-api/agents_api/activities/execute_system.py index 2d3d26687..ae3b9fc17 100644 --- a/agents-api/agents_api/activities/execute_system.py +++ b/agents-api/agents_api/activities/execute_system.py @@ -14,6 +14,7 @@ ) from ..autogen.Tools import SystemDef from ..common.protocol.tasks import StepContext +from ..common.storage_handler import auto_blob_store from ..env import testing from ..models.agent.create_agent import create_agent as create_agent_query from ..models.agent.delete_agent import delete_agent as delete_agent_query @@ -41,6 +42,7 @@ from ..routers.docs.search_docs import search_agent_docs, search_user_docs +@auto_blob_store @beartype async def execute_system( context: StepContext, diff --git a/agents-api/agents_api/activities/task_steps/base_evaluate.py b/agents-api/agents_api/activities/task_steps/base_evaluate.py index c6b83ba89..0e3fb3b44 100644 --- a/agents-api/agents_api/activities/task_steps/base_evaluate.py +++ b/agents-api/agents_api/activities/task_steps/base_evaluate.py @@ -6,10 +6,12 @@ from openai import BaseModel from temporalio import activity +from ...common.storage_handler import auto_blob_store from ...env import testing from ..utils import get_evaluator +@auto_blob_store @beartype async def base_evaluate( exprs: str | list[str] | dict[str, str] | dict[str, dict[str, str]], diff --git a/agents-api/agents_api/activities/task_steps/cozo_query_step.py b/agents-api/agents_api/activities/task_steps/cozo_query_step.py index 8d28d83c9..7a13ae6ec 100644 --- a/agents-api/agents_api/activities/task_steps/cozo_query_step.py +++ b/agents-api/agents_api/activities/task_steps/cozo_query_step.py @@ -4,9 +4,11 @@ from temporalio import activity from ... import models +from ...common.storage_handler import auto_blob_store from ...env import testing +@auto_blob_store @beartype async def cozo_query_step( query_name: str, diff --git a/agents-api/agents_api/activities/task_steps/evaluate_step.py b/agents-api/agents_api/activities/task_steps/evaluate_step.py index 6b1650ff4..dcdbfe592 100644 --- a/agents-api/agents_api/activities/task_steps/evaluate_step.py +++ b/agents-api/agents_api/activities/task_steps/evaluate_step.py @@ -5,9 +5,11 @@ from ...activities.utils import simple_eval_dict from ...common.protocol.tasks import StepContext, StepOutcome +from ...common.storage_handler import auto_blob_store from ...env import testing +@auto_blob_store @beartype async def evaluate_step( context: StepContext, diff --git a/agents-api/agents_api/activities/task_steps/for_each_step.py b/agents-api/agents_api/activities/task_steps/for_each_step.py index 45f6d11dc..c9a48e44d 100644 --- a/agents-api/agents_api/activities/task_steps/for_each_step.py +++ b/agents-api/agents_api/activities/task_steps/for_each_step.py @@ -8,10 +8,12 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store from ...env import testing from .base_evaluate import base_evaluate +@auto_blob_store @beartype async def for_each_step(context: StepContext) -> StepOutcome: try: diff --git a/agents-api/agents_api/activities/task_steps/get_value_step.py b/agents-api/agents_api/activities/task_steps/get_value_step.py index 71c6d5221..dc9b73832 100644 --- a/agents-api/agents_api/activities/task_steps/get_value_step.py +++ b/agents-api/agents_api/activities/task_steps/get_value_step.py @@ -2,11 +2,13 @@ from temporalio import activity from ...common.protocol.tasks import StepContext, StepOutcome +from ...common.storage_handler import auto_blob_store from ...env import testing # TODO: We should use this step to query the parent workflow and get the value from the workflow context # SCRUM-1 +@auto_blob_store @beartype async def get_value_step( context: StepContext, diff --git a/agents-api/agents_api/activities/task_steps/if_else_step.py b/agents-api/agents_api/activities/task_steps/if_else_step.py index ecb935ca6..1b6aeb60e 100644 --- a/agents-api/agents_api/activities/task_steps/if_else_step.py +++ b/agents-api/agents_api/activities/task_steps/if_else_step.py @@ -6,10 +6,12 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store from ...env import testing from .base_evaluate import base_evaluate +@auto_blob_store @beartype async def if_else_step(context: StepContext) -> StepOutcome: # NOTE: This activity is only for logging, so we just evaluate the expression diff --git a/agents-api/agents_api/activities/task_steps/log_step.py b/agents-api/agents_api/activities/task_steps/log_step.py index 34def9bf2..b57c624b5 100644 --- a/agents-api/agents_api/activities/task_steps/log_step.py +++ b/agents-api/agents_api/activities/task_steps/log_step.py @@ -6,10 +6,12 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store from ...common.utils.template import render_template from ...env import testing +@auto_blob_store @beartype async def log_step(context: StepContext) -> StepOutcome: # NOTE: This activity is only for logging, so we just evaluate the expression diff --git a/agents-api/agents_api/activities/task_steps/map_reduce_step.py b/agents-api/agents_api/activities/task_steps/map_reduce_step.py index 97fd0c154..43cd13690 100644 --- a/agents-api/agents_api/activities/task_steps/map_reduce_step.py +++ b/agents-api/agents_api/activities/task_steps/map_reduce_step.py @@ -8,10 +8,12 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store from ...env import testing from .base_evaluate import base_evaluate +@auto_blob_store @beartype async def map_reduce_step(context: StepContext) -> StepOutcome: try: diff --git a/agents-api/agents_api/activities/task_steps/prompt_step.py b/agents-api/agents_api/activities/task_steps/prompt_step.py index bdc8a5c6e..e8af00378 100644 --- a/agents-api/agents_api/activities/task_steps/prompt_step.py +++ b/agents-api/agents_api/activities/task_steps/prompt_step.py @@ -7,6 +7,7 @@ litellm, # We dont directly import `acompletion` so we can mock it ) from ...common.protocol.tasks import StepContext, StepOutcome +from ...common.storage_handler import auto_blob_store from ...common.utils.template import render_template from ...models.tools.list_tools import list_tools @@ -28,6 +29,7 @@ def format_agent_tool(tool: Tool) -> dict: @activity.defn +@auto_blob_store @beartype async def prompt_step(context: StepContext) -> StepOutcome: # Get context data diff --git a/agents-api/agents_api/activities/task_steps/raise_complete_async.py b/agents-api/agents_api/activities/task_steps/raise_complete_async.py index 54fd8a32c..904b298d3 100644 --- a/agents-api/agents_api/activities/task_steps/raise_complete_async.py +++ b/agents-api/agents_api/activities/task_steps/raise_complete_async.py @@ -1,5 +1,6 @@ import base64 +from beartype import beartype from temporalio import activity from ...autogen.openapi_model import CreateTransitionRequest @@ -7,10 +8,13 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store from .transition_step import original_transition_step @activity.defn +@auto_blob_store +@beartype async def raise_complete_async(context: StepContext, output: StepOutcome) -> None: activity_info = activity.info() diff --git a/agents-api/agents_api/activities/task_steps/return_step.py b/agents-api/agents_api/activities/task_steps/return_step.py index 1e272bab2..cb85c38be 100644 --- a/agents-api/agents_api/activities/task_steps/return_step.py +++ b/agents-api/agents_api/activities/task_steps/return_step.py @@ -1,3 +1,4 @@ +from beartype import beartype from temporalio import activity from ...autogen.openapi_model import ReturnStep @@ -5,13 +6,14 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store from ...env import testing from .base_evaluate import base_evaluate +@auto_blob_store +@beartype async def return_step(context: StepContext) -> StepOutcome: - # NOTE: This activity is only for returning immediately, so we just evaluate the expression - # Hence, it's a local activity and SHOULD NOT fail try: assert isinstance(context.current_step, ReturnStep) diff --git a/agents-api/agents_api/activities/task_steps/set_value_step.py b/agents-api/agents_api/activities/task_steps/set_value_step.py index 2a199b324..5a89fb87b 100644 --- a/agents-api/agents_api/activities/task_steps/set_value_step.py +++ b/agents-api/agents_api/activities/task_steps/set_value_step.py @@ -5,11 +5,13 @@ from ...activities.utils import simple_eval_dict from ...common.protocol.tasks import StepContext, StepOutcome +from ...common.storage_handler import auto_blob_store from ...env import testing # TODO: We should use this step to signal to the parent workflow and set the value on the workflow context # SCRUM-2 +@auto_blob_store @beartype async def set_value_step( context: StepContext, diff --git a/agents-api/agents_api/activities/task_steps/switch_step.py b/agents-api/agents_api/activities/task_steps/switch_step.py index b28150450..29ad8ea65 100644 --- a/agents-api/agents_api/activities/task_steps/switch_step.py +++ b/agents-api/agents_api/activities/task_steps/switch_step.py @@ -6,10 +6,12 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store from ...env import testing from ..utils import get_evaluator +@auto_blob_store @beartype async def switch_step(context: StepContext) -> StepOutcome: try: @@ -36,8 +38,6 @@ async def switch_step(context: StepContext) -> StepOutcome: return StepOutcome(error=str(e)) -# Note: This is here just for clarity. We could have just imported switch_step directly -# They do the same thing, so we dont need to mock the switch_step function mock_switch_step = switch_step switch_step = activity.defn(name="switch_step")( diff --git a/agents-api/agents_api/activities/task_steps/tool_call_step.py b/agents-api/agents_api/activities/task_steps/tool_call_step.py index 8d5d2fc8c..fa99dabd4 100644 --- a/agents-api/agents_api/activities/task_steps/tool_call_step.py +++ b/agents-api/agents_api/activities/task_steps/tool_call_step.py @@ -11,6 +11,7 @@ StepContext, StepOutcome, ) +from ...common.storage_handler import auto_blob_store # FIXME: This shouldn't be here. @@ -44,6 +45,7 @@ def construct_tool_call(tool: TaskToolDef, arguments: dict, call_id: str) -> dic @activity.defn +@auto_blob_store @beartype async def tool_call_step(context: StepContext) -> StepOutcome: assert isinstance(context.current_step, ToolCallStep) diff --git a/agents-api/agents_api/activities/task_steps/wait_for_input_step.py b/agents-api/agents_api/activities/task_steps/wait_for_input_step.py index 58b7da489..59a75ea00 100644 --- a/agents-api/agents_api/activities/task_steps/wait_for_input_step.py +++ b/agents-api/agents_api/activities/task_steps/wait_for_input_step.py @@ -1,11 +1,15 @@ +from beartype import beartype from temporalio import activity from ...autogen.openapi_model import WaitForInputStep from ...common.protocol.tasks import StepContext, StepOutcome +from ...common.storage_handler import auto_blob_store from ...env import testing from .base_evaluate import base_evaluate +@auto_blob_store +@beartype async def wait_for_input_step(context: StepContext) -> StepOutcome: try: assert isinstance(context.current_step, WaitForInputStep) @@ -21,8 +25,6 @@ async def wait_for_input_step(context: StepContext) -> StepOutcome: return StepOutcome(error=str(e)) -# Note: This is here just for clarity. We could have just imported wait_for_input_step directly -# They do the same thing, so we dont need to mock the wait_for_input_step function mock_wait_for_input_step = wait_for_input_step wait_for_input_step = activity.defn(name="wait_for_input_step")( diff --git a/agents-api/agents_api/activities/task_steps/yield_step.py b/agents-api/agents_api/activities/task_steps/yield_step.py index 41fa2eb87..6a97b5a07 100644 --- a/agents-api/agents_api/activities/task_steps/yield_step.py +++ b/agents-api/agents_api/activities/task_steps/yield_step.py @@ -3,17 +3,16 @@ from beartype import beartype from temporalio import activity -from agents_api.autogen.openapi_model import TransitionTarget, YieldStep - +from ...autogen.openapi_model import TransitionTarget, YieldStep from ...common.protocol.tasks import StepContext, StepOutcome +from ...common.storage_handler import auto_blob_store from ...env import testing from .base_evaluate import base_evaluate +@auto_blob_store @beartype async def yield_step(context: StepContext) -> StepOutcome: - # NOTE: This activity is only for returning immediately, so we just evaluate the expression - # Hence, it's a local activity and SHOULD NOT fail try: assert isinstance(context.current_step, YieldStep) diff --git a/agents-api/agents_api/clients/s3.py b/agents-api/agents_api/clients/s3.py new file mode 100644 index 000000000..749f53245 --- /dev/null +++ b/agents-api/agents_api/clients/s3.py @@ -0,0 +1,92 @@ +from functools import cache, lru_cache + +from beartype import beartype +from temporalio import workflow + +with workflow.unsafe.imports_passed_through(): + import boto3 + import botocore + from xxhash import xxh3_64_hexdigest as xxhash_key + + from ..env import ( + blob_store_bucket, + blob_store_cutoff_kb, + s3_access_key, + s3_endpoint, + s3_secret_key, + ) + + +@cache +def get_s3_client(): + return boto3.client( + "s3", + endpoint_url=s3_endpoint, + aws_access_key_id=s3_access_key, + aws_secret_access_key=s3_secret_key, + ) + + +def list_buckets() -> list[str]: + client = get_s3_client() + data = client.list_buckets() + buckets = [bucket["Name"] for bucket in data["Buckets"]] + + return buckets + + +@cache +def setup(): + client = get_s3_client() + if blob_store_bucket not in list_buckets(): + client.create_bucket(Bucket=blob_store_bucket) + + +@lru_cache(maxsize=10_000) +def exists(key: str) -> bool: + client = get_s3_client() + + try: + client.head_object(Bucket=blob_store_bucket, Key=key) + return True + + except botocore.exceptions.ClientError as e: + if e.response["Error"]["Code"] == "404": + return False + else: + raise e + + +@beartype +def add_object(key: str, body: bytes, replace: bool = False) -> None: + client = get_s3_client() + + if replace: + client.put_object(Bucket=blob_store_bucket, Key=key, Body=body) + return + + if exists(key): + return + + client.put_object(Bucket=blob_store_bucket, Key=key, Body=body) + + +@lru_cache(maxsize=256 * 1024 // blob_store_cutoff_kb) # 256mb in cache +@beartype +def get_object(key: str) -> bytes: + client = get_s3_client() + return client.get_object(Bucket=blob_store_bucket, Key=key)["Body"].read() + + +@beartype +def delete_object(key: str) -> None: + client = get_s3_client() + client.delete_object(Bucket=blob_store_bucket, Key=key) + + +@beartype +def add_object_with_hash(body: bytes, replace: bool = False) -> str: + key = xxhash_key(body) + add_object(key, body, replace=replace) + + return key diff --git a/agents-api/agents_api/common/protocol/tasks.py b/agents-api/agents_api/common/protocol/tasks.py index 872d83516..8d46c57b7 100644 --- a/agents-api/agents_api/common/protocol/tasks.py +++ b/agents-api/agents_api/common/protocol/tasks.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass from typing import Annotated, Any from uuid import UUID @@ -215,6 +216,11 @@ class StepOutcome(BaseModel): transition_to: tuple[TransitionType, TransitionTarget] | None = None +@dataclass +class RemoteObject: + key: str + + def task_to_spec( task: Task | CreateTaskRequest | UpdateTaskRequest | PatchTaskRequest, **model_opts ) -> TaskSpecDef | PartialTaskSpecDef: diff --git a/agents-api/agents_api/common/storage_handler.py b/agents-api/agents_api/common/storage_handler.py new file mode 100644 index 000000000..ca669620c --- /dev/null +++ b/agents-api/agents_api/common/storage_handler.py @@ -0,0 +1,68 @@ +import inspect +import sys +from functools import wraps +from typing import Any, Callable + +from ..clients import s3 +from ..common.protocol.tasks import RemoteObject +from ..env import blob_store_cutoff_kb, use_blob_store_for_temporal +from ..worker.codec import deserialize, serialize + +if use_blob_store_for_temporal: + s3.setup() + + +def store_in_blob_store_if_large(x: Any) -> RemoteObject | Any: + serialized = serialize(x) + data_size = sys.getsizeof(serialized) + + if data_size > blob_store_cutoff_kb * 1024: + key = s3.add_object_with_hash(serialized) + return RemoteObject(key=key) + + return x + + +def load_from_blob_store_if_remote(x: Any) -> Any: + if isinstance(x, RemoteObject): + fetched = s3.get_object(x.key) + return deserialize(fetched) + + return x + + +# Decorator that automatically does two things: +# 1. store in blob store if the output of a function is large +# 2. load from blob store if the input is a RemoteObject + + +def auto_blob_store(f: Callable) -> Callable: + def load_args( + args: list[Any], kwargs: dict[str, Any] + ) -> tuple[list[Any], dict[str, Any]]: + new_args = [load_from_blob_store_if_remote(arg) for arg in args] + new_kwargs = {k: load_from_blob_store_if_remote(v) for k, v in kwargs.items()} + + return new_args, new_kwargs + + if inspect.iscoroutinefunction(f): + + @wraps(f) + async def async_wrapper(*args, **kwargs) -> Any: + new_args, new_kwargs = load_args(args, kwargs) + output = await f(*new_args, **new_kwargs) + + return store_in_blob_store_if_large(output) + + return async_wrapper if use_blob_store_for_temporal else f + + else: + + @wraps(f) + def wrapper(*args, **kwargs) -> Any: + new_args, new_kwargs = load_args(args, kwargs) + output = f(*new_args, **new_kwargs) + + return store_in_blob_store_if_large(output) + + return wrapper if use_blob_store_for_temporal else f diff --git a/agents-api/agents_api/env.py b/agents-api/agents_api/env.py index 2b016fd40..43cfc45d0 100644 --- a/agents-api/agents_api/env.py +++ b/agents-api/agents_api/env.py @@ -25,6 +25,17 @@ # ----- task_max_parallelism: int = env.int("AGENTS_API_TASK_MAX_PARALLELISM", default=100) +# Blob Store +# ---------- +use_blob_store_for_temporal: bool = env.bool( + "USE_BLOB_STORE_FOR_TEMPORAL", default=False +) + +blob_store_bucket: str = env.str("BLOB_STORE_BUCKET", default="agents-api") +blob_store_cutoff_kb: int = env.int("BLOB_STORE_CUTOFF_KB", default=1024) +s3_endpoint: str = env.str("S3_ENDPOINT", default="http://seaweedfs:8333") +s3_access_key: str | None = env.str("S3_ACCESS_KEY", default=None) +s3_secret_key: str | None = env.str("S3_SECRET_KEY", default=None) # Debug # ----- diff --git a/agents-api/agents_api/worker/codec.py b/agents-api/agents_api/worker/codec.py index 611d7b8f1..0ca68a9d3 100644 --- a/agents-api/agents_api/worker/codec.py +++ b/agents-api/agents_api/worker/codec.py @@ -24,11 +24,17 @@ def serialize(x: Any) -> bytes: - return compress(pickle.dumps(x, protocol=pickle.HIGHEST_PROTOCOL)) + pickled = pickle.dumps(x, protocol=pickle.HIGHEST_PROTOCOL) + compressed = compress(pickled) + + return compressed def deserialize(b: bytes) -> Any: - return pickle.loads(decompress(b)) + decompressed = decompress(b) + object = pickle.loads(decompressed) + + return object def from_payload_data(data: bytes, type_hint: Optional[Type] = None) -> Any: diff --git a/agents-api/docker-compose.yml b/agents-api/docker-compose.yml index d385db0a8..d1a43d64a 100644 --- a/agents-api/docker-compose.yml +++ b/agents-api/docker-compose.yml @@ -22,6 +22,12 @@ x--shared-environment: &shared-environment TEMPORAL_WORKER_URL: ${TEMPORAL_WORKER_URL:-temporal:7233} TRUNCATE_EMBED_TEXT: ${TRUNCATE_EMBED_TEXT:-True} WORKER_URL: ${WORKER_URL:-temporal:7233} + USE_BLOB_STORE_FOR_TEMPORAL: ${USE_BLOB_STORE_FOR_TEMPORAL:-false} + BLOB_STORE_CUTOFF_KB: ${BLOB_STORE_CUTOFF_KB:-1024} + BLOB_STORE_BUCKET: ${BLOB_STORE_BUCKET:-agents-api} + S3_ENDPOINT: ${S3_ENDPOINT:-http://seaweedfs:8333} + S3_ACCESS_KEY: ${S3_ACCESS_KEY} + S3_SECRET_KEY: ${S3_SECRET_KEY} x--base-agents-api: &base-agents-api image: julepai/agents-api:${TAG:-dev} diff --git a/agents-api/poetry.lock b/agents-api/poetry.lock index 8d85fdb4d..6a928e86f 100644 --- a/agents-api/poetry.lock +++ b/agents-api/poetry.lock @@ -431,6 +431,44 @@ webencodings = "*" [package.extras] css = ["tinycss2 (>=1.1.0,<1.3)"] +[[package]] +name = "boto3" +version = "1.35.41" +description = "The AWS SDK for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "boto3-1.35.41-py3-none-any.whl", hash = "sha256:2bf7e7f376aee52155fc4ae4487f29333a6bcdf3a05c3bc4fede10b972d951a6"}, + {file = "boto3-1.35.41.tar.gz", hash = "sha256:e74bc6d69c04ca611b7f58afe08e2ded6cb6504a4a80557b656abeefee395f88"}, +] + +[package.dependencies] +botocore = ">=1.35.41,<1.36.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.10.0,<0.11.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "botocore" +version = "1.35.41" +description = "Low-level, data-driven core of boto 3." +optional = false +python-versions = ">=3.8" +files = [ + {file = "botocore-1.35.41-py3-none-any.whl", hash = "sha256:915c4d81e3a0be3b793c1e2efdf19af1d0a9cd4a2d8de08ee18216c14d67764b"}, + {file = "botocore-1.35.41.tar.gz", hash = "sha256:8a09a32136df8768190a6c92f0240cd59c30deb99c89026563efadbbed41fa00"}, +] + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} + +[package.extras] +crt = ["awscrt (==0.22.0)"] + [[package]] name = "certifi" version = "2024.8.30" @@ -1612,6 +1650,17 @@ files = [ {file = "jiter-0.6.1.tar.gz", hash = "sha256:e19cd21221fc139fb032e4112986656cb2739e9fe6d84c13956ab30ccc7d4449"}, ] +[[package]] +name = "jmespath" +version = "1.0.1" +description = "JSON Matching Expressions" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] + [[package]] name = "json5" version = "0.9.25" @@ -3945,6 +3994,23 @@ files = [ {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, ] +[[package]] +name = "s3transfer" +version = "0.10.3" +description = "An Amazon S3 Transfer Manager" +optional = false +python-versions = ">=3.8" +files = [ + {file = "s3transfer-0.10.3-py3-none-any.whl", hash = "sha256:263ed587a5803c6c708d3ce44dc4dfedaab4c1a32e8329bab818933d79ddcf5d"}, + {file = "s3transfer-0.10.3.tar.gz", hash = "sha256:4f50ed74ab84d474ce614475e0b8d5047ff080810aac5d01ea25231cfc944b0c"}, +] + +[package.dependencies] +botocore = ">=1.33.2,<2.0a.0" + +[package.extras] +crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] + [[package]] name = "scalar-fastapi" version = "1.0.3" @@ -4713,6 +4779,138 @@ files = [ {file = "widgetsnbextension-4.0.13.tar.gz", hash = "sha256:ffcb67bc9febd10234a362795f643927f4e0c05d9342c727b65d2384f8feacb6"}, ] +[[package]] +name = "xxhash" +version = "3.5.0" +description = "Python binding for xxHash" +optional = false +python-versions = ">=3.7" +files = [ + {file = "xxhash-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ece616532c499ee9afbb83078b1b952beffef121d989841f7f4b3dc5ac0fd212"}, + {file = "xxhash-3.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3171f693dbc2cef6477054a665dc255d996646b4023fe56cb4db80e26f4cc520"}, + {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c5d3e570ef46adaf93fc81b44aca6002b5a4d8ca11bd0580c07eac537f36680"}, + {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cb29a034301e2982df8b1fe6328a84f4b676106a13e9135a0d7e0c3e9f806da"}, + {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0d307d27099bb0cbeea7260eb39ed4fdb99c5542e21e94bb6fd29e49c57a23"}, + {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0342aafd421795d740e514bc9858ebddfc705a75a8c5046ac56d85fe97bf196"}, + {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dbbd9892c5ebffeca1ed620cf0ade13eb55a0d8c84e0751a6653adc6ac40d0c"}, + {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4cc2d67fdb4d057730c75a64c5923abfa17775ae234a71b0200346bfb0a7f482"}, + {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ec28adb204b759306a3d64358a5e5c07d7b1dd0ccbce04aa76cb9377b7b70296"}, + {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1328f6d8cca2b86acb14104e381225a3d7b42c92c4b86ceae814e5c400dbb415"}, + {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8d47ebd9f5d9607fd039c1fbf4994e3b071ea23eff42f4ecef246ab2b7334198"}, + {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b96d559e0fcddd3343c510a0fe2b127fbff16bf346dd76280b82292567523442"}, + {file = "xxhash-3.5.0-cp310-cp310-win32.whl", hash = "sha256:61c722ed8d49ac9bc26c7071eeaa1f6ff24053d553146d5df031802deffd03da"}, + {file = "xxhash-3.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:9bed5144c6923cc902cd14bb8963f2d5e034def4486ab0bbe1f58f03f042f9a9"}, + {file = "xxhash-3.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:893074d651cf25c1cc14e3bea4fceefd67f2921b1bb8e40fcfeba56820de80c6"}, + {file = "xxhash-3.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02c2e816896dc6f85922ced60097bcf6f008dedfc5073dcba32f9c8dd786f3c1"}, + {file = "xxhash-3.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6027dcd885e21581e46d3c7f682cfb2b870942feeed58a21c29583512c3f09f8"}, + {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1308fa542bbdbf2fa85e9e66b1077eea3a88bef38ee8a06270b4298a7a62a166"}, + {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28b2fdcee797e1c1961cd3bcd3d545cab22ad202c846235197935e1df2f8ef7"}, + {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:924361811732ddad75ff23e90efd9ccfda4f664132feecb90895bade6a1b4623"}, + {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89997aa1c4b6a5b1e5b588979d1da048a3c6f15e55c11d117a56b75c84531f5a"}, + {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:685c4f4e8c59837de103344eb1c8a3851f670309eb5c361f746805c5471b8c88"}, + {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbd2ecfbfee70bc1a4acb7461fa6af7748ec2ab08ac0fa298f281c51518f982c"}, + {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25b5a51dc3dfb20a10833c8eee25903fd2e14059e9afcd329c9da20609a307b2"}, + {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a8fb786fb754ef6ff8c120cb96629fb518f8eb5a61a16aac3a979a9dbd40a084"}, + {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a905ad00ad1e1c34fe4e9d7c1d949ab09c6fa90c919860c1534ff479f40fd12d"}, + {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:963be41bcd49f53af6d795f65c0da9b4cc518c0dd9c47145c98f61cb464f4839"}, + {file = "xxhash-3.5.0-cp311-cp311-win32.whl", hash = "sha256:109b436096d0a2dd039c355fa3414160ec4d843dfecc64a14077332a00aeb7da"}, + {file = "xxhash-3.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:b702f806693201ad6c0a05ddbbe4c8f359626d0b3305f766077d51388a6bac58"}, + {file = "xxhash-3.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:c4dcb4120d0cc3cc448624147dba64e9021b278c63e34a38789b688fd0da9bf3"}, + {file = "xxhash-3.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:14470ace8bd3b5d51318782cd94e6f94431974f16cb3b8dc15d52f3b69df8e00"}, + {file = "xxhash-3.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59aa1203de1cb96dbeab595ded0ad0c0056bb2245ae11fac11c0ceea861382b9"}, + {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08424f6648526076e28fae6ea2806c0a7d504b9ef05ae61d196d571e5c879c84"}, + {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61a1ff00674879725b194695e17f23d3248998b843eb5e933007ca743310f793"}, + {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2f2c61bee5844d41c3eb015ac652a0229e901074951ae48581d58bfb2ba01be"}, + {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d32a592cac88d18cc09a89172e1c32d7f2a6e516c3dfde1b9adb90ab5df54a6"}, + {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70dabf941dede727cca579e8c205e61121afc9b28516752fd65724be1355cc90"}, + {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e5d0ddaca65ecca9c10dcf01730165fd858533d0be84c75c327487c37a906a27"}, + {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e5b5e16c5a480fe5f59f56c30abdeba09ffd75da8d13f6b9b6fd224d0b4d0a2"}, + {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149b7914451eb154b3dfaa721315117ea1dac2cc55a01bfbd4df7c68c5dd683d"}, + {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:eade977f5c96c677035ff39c56ac74d851b1cca7d607ab3d8f23c6b859379cab"}, + {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fa9f547bd98f5553d03160967866a71056a60960be00356a15ecc44efb40ba8e"}, + {file = "xxhash-3.5.0-cp312-cp312-win32.whl", hash = "sha256:f7b58d1fd3551b8c80a971199543379be1cee3d0d409e1f6d8b01c1a2eebf1f8"}, + {file = "xxhash-3.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:fa0cafd3a2af231b4e113fba24a65d7922af91aeb23774a8b78228e6cd785e3e"}, + {file = "xxhash-3.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:586886c7e89cb9828bcd8a5686b12e161368e0064d040e225e72607b43858ba2"}, + {file = "xxhash-3.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:37889a0d13b0b7d739cfc128b1c902f04e32de17b33d74b637ad42f1c55101f6"}, + {file = "xxhash-3.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:97a662338797c660178e682f3bc180277b9569a59abfb5925e8620fba00b9fc5"}, + {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f85e0108d51092bdda90672476c7d909c04ada6923c14ff9d913c4f7dc8a3bc"}, + {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2fd827b0ba763ac919440042302315c564fdb797294d86e8cdd4578e3bc7f3"}, + {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82085c2abec437abebf457c1d12fccb30cc8b3774a0814872511f0f0562c768c"}, + {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07fda5de378626e502b42b311b049848c2ef38784d0d67b6f30bb5008642f8eb"}, + {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c279f0d2b34ef15f922b77966640ade58b4ccdfef1c4d94b20f2a364617a493f"}, + {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:89e66ceed67b213dec5a773e2f7a9e8c58f64daeb38c7859d8815d2c89f39ad7"}, + {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bcd51708a633410737111e998ceb3b45d3dbc98c0931f743d9bb0a209033a326"}, + {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ff2c0a34eae7df88c868be53a8dd56fbdf592109e21d4bfa092a27b0bf4a7bf"}, + {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e28503dccc7d32e0b9817aa0cbfc1f45f563b2c995b7a66c4c8a0d232e840c7"}, + {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a6c50017518329ed65a9e4829154626f008916d36295b6a3ba336e2458824c8c"}, + {file = "xxhash-3.5.0-cp313-cp313-win32.whl", hash = "sha256:53a068fe70301ec30d868ece566ac90d873e3bb059cf83c32e76012c889b8637"}, + {file = "xxhash-3.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:80babcc30e7a1a484eab952d76a4f4673ff601f54d5142c26826502740e70b43"}, + {file = "xxhash-3.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:4811336f1ce11cac89dcbd18f3a25c527c16311709a89313c3acaf771def2d4b"}, + {file = "xxhash-3.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6e5f70f6dca1d3b09bccb7daf4e087075ff776e3da9ac870f86ca316736bb4aa"}, + {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e76e83efc7b443052dd1e585a76201e40b3411fe3da7af4fe434ec51b2f163b"}, + {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33eac61d0796ca0591f94548dcfe37bb193671e0c9bcf065789b5792f2eda644"}, + {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ec70a89be933ea49222fafc3999987d7899fc676f688dd12252509434636622"}, + {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86b8e7f703ec6ff4f351cfdb9f428955859537125904aa8c963604f2e9d3e7"}, + {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0adfbd36003d9f86c8c97110039f7539b379f28656a04097e7434d3eaf9aa131"}, + {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:63107013578c8a730419adc05608756c3fa640bdc6abe806c3123a49fb829f43"}, + {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:683b94dbd1ca67557850b86423318a2e323511648f9f3f7b1840408a02b9a48c"}, + {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:5d2a01dcce81789cf4b12d478b5464632204f4c834dc2d064902ee27d2d1f0ee"}, + {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:a9d360a792cbcce2fe7b66b8d51274ec297c53cbc423401480e53b26161a290d"}, + {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:f0b48edbebea1b7421a9c687c304f7b44d0677c46498a046079d445454504737"}, + {file = "xxhash-3.5.0-cp37-cp37m-win32.whl", hash = "sha256:7ccb800c9418e438b44b060a32adeb8393764da7441eb52aa2aa195448935306"}, + {file = "xxhash-3.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c3bc7bf8cb8806f8d1c9bf149c18708cb1c406520097d6b0a73977460ea03602"}, + {file = "xxhash-3.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:74752ecaa544657d88b1d1c94ae68031e364a4d47005a90288f3bab3da3c970f"}, + {file = "xxhash-3.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dee1316133c9b463aa81aca676bc506d3f80d8f65aeb0bba2b78d0b30c51d7bd"}, + {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:602d339548d35a8579c6b013339fb34aee2df9b4e105f985443d2860e4d7ffaa"}, + {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:695735deeddfb35da1677dbc16a083445360e37ff46d8ac5c6fcd64917ff9ade"}, + {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1030a39ba01b0c519b1a82f80e8802630d16ab95dc3f2b2386a0b5c8ed5cbb10"}, + {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5bc08f33c4966f4eb6590d6ff3ceae76151ad744576b5fc6c4ba8edd459fdec"}, + {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:160e0c19ee500482ddfb5d5570a0415f565d8ae2b3fd69c5dcfce8a58107b1c3"}, + {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f1abffa122452481a61c3551ab3c89d72238e279e517705b8b03847b1d93d738"}, + {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d5e9db7ef3ecbfc0b4733579cea45713a76852b002cf605420b12ef3ef1ec148"}, + {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:23241ff6423378a731d84864bf923a41649dc67b144debd1077f02e6249a0d54"}, + {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:82b833d5563fefd6fceafb1aed2f3f3ebe19f84760fdd289f8b926731c2e6e91"}, + {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a80ad0ffd78bef9509eee27b4a29e56f5414b87fb01a888353e3d5bda7038bd"}, + {file = "xxhash-3.5.0-cp38-cp38-win32.whl", hash = "sha256:50ac2184ffb1b999e11e27c7e3e70cc1139047e7ebc1aa95ed12f4269abe98d4"}, + {file = "xxhash-3.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:392f52ebbb932db566973693de48f15ce787cabd15cf6334e855ed22ea0be5b3"}, + {file = "xxhash-3.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bfc8cdd7f33d57f0468b0614ae634cc38ab9202c6957a60e31d285a71ebe0301"}, + {file = "xxhash-3.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e0c48b6300cd0b0106bf49169c3e0536408dfbeb1ccb53180068a18b03c662ab"}, + {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe1a92cfbaa0a1253e339ccec42dbe6db262615e52df591b68726ab10338003f"}, + {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33513d6cc3ed3b559134fb307aae9bdd94d7e7c02907b37896a6c45ff9ce51bd"}, + {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eefc37f6138f522e771ac6db71a6d4838ec7933939676f3753eafd7d3f4c40bc"}, + {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a606c8070ada8aa2a88e181773fa1ef17ba65ce5dd168b9d08038e2a61b33754"}, + {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42eca420c8fa072cc1dd62597635d140e78e384a79bb4944f825fbef8bfeeef6"}, + {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:604253b2143e13218ff1ef0b59ce67f18b8bd1c4205d2ffda22b09b426386898"}, + {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6e93a5ad22f434d7876665444a97e713a8f60b5b1a3521e8df11b98309bff833"}, + {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7a46e1d6d2817ba8024de44c4fd79913a90e5f7265434cef97026215b7d30df6"}, + {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:30eb2efe6503c379b7ab99c81ba4a779748e3830241f032ab46bd182bf5873af"}, + {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c8aa771ff2c13dd9cda8166d685d7333d389fae30a4d2bb39d63ab5775de8606"}, + {file = "xxhash-3.5.0-cp39-cp39-win32.whl", hash = "sha256:5ed9ebc46f24cf91034544b26b131241b699edbfc99ec5e7f8f3d02d6eb7fba4"}, + {file = "xxhash-3.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:220f3f896c6b8d0316f63f16c077d52c412619e475f9372333474ee15133a558"}, + {file = "xxhash-3.5.0-cp39-cp39-win_arm64.whl", hash = "sha256:a7b1d8315d9b5e9f89eb2933b73afae6ec9597a258d52190944437158b49d38e"}, + {file = "xxhash-3.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2014c5b3ff15e64feecb6b713af12093f75b7926049e26a580e94dcad3c73d8c"}, + {file = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fab81ef75003eda96239a23eda4e4543cedc22e34c373edcaf744e721a163986"}, + {file = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2febf914ace002132aa09169cc572e0d8959d0f305f93d5828c4836f9bc5a6"}, + {file = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5d3a10609c51da2a1c0ea0293fc3968ca0a18bd73838455b5bca3069d7f8e32b"}, + {file = "xxhash-3.5.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a74f23335b9689b66eb6dbe2a931a88fcd7a4c2cc4b1cb0edba8ce381c7a1da"}, + {file = "xxhash-3.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2b4154c00eb22e4d543f472cfca430e7962a0f1d0f3778334f2e08a7ba59363c"}, + {file = "xxhash-3.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d30bbc1644f726b825b3278764240f449d75f1a8bdda892e641d4a688b1494ae"}, + {file = "xxhash-3.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fa0b72f2423e2aa53077e54a61c28e181d23effeaafd73fcb9c494e60930c8e"}, + {file = "xxhash-3.5.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13de2b76c1835399b2e419a296d5b38dc4855385d9e96916299170085ef72f57"}, + {file = "xxhash-3.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:0691bfcc4f9c656bcb96cc5db94b4d75980b9d5589f2e59de790091028580837"}, + {file = "xxhash-3.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:297595fe6138d4da2c8ce9e72a04d73e58725bb60f3a19048bc96ab2ff31c692"}, + {file = "xxhash-3.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc1276d369452040cbb943300dc8abeedab14245ea44056a2943183822513a18"}, + {file = "xxhash-3.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2061188a1ba352fc699c82bff722f4baacb4b4b8b2f0c745d2001e56d0dfb514"}, + {file = "xxhash-3.5.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38c384c434021e4f62b8d9ba0bc9467e14d394893077e2c66d826243025e1f81"}, + {file = "xxhash-3.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e6a4dd644d72ab316b580a1c120b375890e4c52ec392d4aef3c63361ec4d77d1"}, + {file = "xxhash-3.5.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:531af8845aaadcadf951b7e0c1345c6b9c68a990eeb74ff9acd8501a0ad6a1c9"}, + {file = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ce379bcaa9fcc00f19affa7773084dd09f5b59947b3fb47a1ceb0179f91aaa1"}, + {file = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd1b2281d01723f076df3c8188f43f2472248a6b63118b036e641243656b1b0f"}, + {file = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c770750cc80e8694492244bca7251385188bc5597b6a39d98a9f30e8da984e0"}, + {file = "xxhash-3.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b150b8467852e1bd844387459aa6fbe11d7f38b56e901f9f3b3e6aba0d660240"}, + {file = "xxhash-3.5.0.tar.gz", hash = "sha256:84f2caddf951c9cbf8dc2e22a89d4ccf5d86391ac6418fe81e3c67d0cf60b45f"}, +] + [[package]] name = "yarl" version = "1.15.2" @@ -4847,4 +5045,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "d6f0a373b8b246791c4b20ed32827659328d50d5b51644c16ecea2ec467de5f5" +content-hash = "d314acb39fa48742da35437160d180810ec9edcedbb11ac783a858ccb5ebbbd6" diff --git a/agents-api/pyproject.toml b/agents-api/pyproject.toml index 45e0b055a..1fecc70e5 100644 --- a/agents-api/pyproject.toml +++ b/agents-api/pyproject.toml @@ -38,6 +38,10 @@ sse-starlette = "^2.1.3" anyio = "^4.4.0" python-box = {extras = [], version = "^7.2.0"} prometheus-fastapi-instrumentator = "^7.0.0" +boto3 = "^1.35.39" +xxhash = "^3.5.0" +ruamel-yaml = "^0.18.6" + [tool.poetry.group.dev.dependencies] ipython = "^8.26.0" ruff = "^0.5.5" diff --git a/agents-api/scripts/agents_api.py b/agents-api/scripts/agents_api.py index 8ab7d2e0c..5bacef0c8 100644 --- a/agents-api/scripts/agents_api.py +++ b/agents-api/scripts/agents_api.py @@ -1,4 +1,5 @@ import fire + from agents_api.web import main diff --git a/blob-store/docker-compose.yml b/blob-store/docker-compose.yml index 4fe9a658e..089b31f39 100644 --- a/blob-store/docker-compose.yml +++ b/blob-store/docker-compose.yml @@ -22,7 +22,7 @@ services: # - 19333:19333 # master grpc port # - 18081:18080 # volume grpc port # - 18888:18888 # filer grpc port - command: "-filer -s3 -dir=/data -ip=seaweedfs -ip.bind=0.0.0.0 -metricsPort=9321 -master.raftBootstrap=false -master.port=9333 -master.resumeState=true -volume.port=28080 -volume.index=leveldb -filer.port=8888 -s3.port=8333" + command: "-volume -volume.dir.idx /data -filer -s3 -dir=/data -ip=seaweedfs -ip.bind=0.0.0.0 -metricsPort=9321 -master.raftBootstrap=false -master.port=9333 -volume.port=28080 -volume.index=leveldb -filer.port=8888 -s3.port=8333" healthcheck: test: [ "CMD", "wget", "-qSO", "-", "http://0.0.0.0:9333/cluster/healthz" ] interval: 60s