From b7593314854804fd028d1e2a95b9a3e3ff59765d Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Mon, 7 Oct 2024 01:00:27 +0900 Subject: [PATCH 01/23] docs: add Japanese README (#598) I created Japanese translated README. ---- > [!IMPORTANT] > Add Japanese translation of README and update language links in existing READMEs. > > - **Documentation**: > - Add `README-JP.md` for Japanese translation of the README. > - Update language navigation links in `README.md` and `README-CN.md` to include Japanese translation. > > This description was created by [Ellipsis](https://www.ellipsis.dev?ref=julep-ai%2Fjulep&utm_source=github&utm_medium=referral) for f6dc4d29691e889113dd6ab555cabbec34437c4e. It will automatically update as commits are pushed. --- README-CN.md | 4 +- README-JP.md | 667 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 +- 3 files changed, 670 insertions(+), 3 deletions(-) create mode 100644 README-JP.md diff --git a/README-CN.md b/README-CN.md index 8dca6dcbb..437faf13b 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,4 +1,4 @@ -[English](README.md) | 中文 +[English](README.md) | 中文 | [日本語](README-JP.md)
julep @@ -661,4 +661,4 @@ results = client.documents.search( ## 致谢 -我们要感谢所有贡献者和开源社区为他们宝贵的资源和贡献。 \ No newline at end of file +我们要感谢所有贡献者和开源社区为他们宝贵的资源和贡献。 diff --git a/README-JP.md b/README-JP.md new file mode 100644 index 000000000..6110c5601 --- /dev/null +++ b/README-JP.md @@ -0,0 +1,667 @@ +[English](README.md) | [中文](README-CN.md) | 日本語 + +
+ julep +
+ +

+
+ ドキュメントを探索する + · + Discord + · + 𝕏 + · + LinkedIn +

+ + +

+ NPM Version +   + PyPI - Version +   + Docker Image Version +   + GitHub License +

+ +***** + +## 🌟 コントリビューター募集! + +Julepプロジェクトに新しいコントリビューターを歓迎します!スタートに役立つ「初心者向けの問題」をいくつか作成しました。以下は、貢献する方法です: + +1. [CONTRIBUTING.md](CONTRIBUTING.md)ファイルを確認して、貢献のガイドラインを確認してください。 +2. [初心者向けの問題](https://github.com/julep-ai/julep/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)を閲覧して、興味のあるタスクを見つけてください。 +3. 質問がある場合や助けが必要な場合は、[Discord](https://discord.com/invite/JTSBGRZrzj)チャンネルでお気軽にお問い合わせください。 + +あなたの貢献、大きいものでも小さいものでも、私たちにとっては貴重です。一緒に素晴らしいものを作りましょう!🚀 + +### 🎉 DevFest.AI 2024年10月 + +エキサイティングなニュース!2024年10月中、DevFest.AIに参加します!🗓️ + +- このイベント中にJulepに貢献し、素晴らしいJulepのグッズや景品を獲得するチャンスを得ましょう!🎁 +- 世界中の開発者と一緒にAIリポジトリに貢献し、素晴らしいイベントに参加しましょう。 +- この素晴らしいイニシアチブを組織してくれたDevFest.AIに大きな感謝を! + +> [!TIP] +> 楽しみに参加する準備はできましたか?**[ツイートして参加を開始](https://twitter.com/intent/tweet?text=Pumped%20to%20be%20participating%20in%20%40devfestai%20with%20%40julep_ai%20building%20%23ai%20%23agents%20%23workflows%20Let's%20gooo!%20https%3A%2F%2Fgit.new%2Fjulep)**し、コーディングを始めましょう!🖥️ + +![Julep DevFest.AI](https://media.giphy.com/media/YjyUeyotft6epaMHtU/giphy.gif) + +***** + +## 🎉🚀 **エキサイティングなニュース:Julep 1.0 Alphaリリース!** 🚀🎉 + +**Julep 1.0**の**アルファ**リリースを発表できることを嬉しく思います!🥳 + +🌟 **新機能:** +- 強化されたワークフロー機能 +- 改善されたエージェントの持続性 +- 多数の組み込みツール統合(dalle、google検索、sendgridなど) +- 簡素化されたAPI + +🧪 試してみて、AIワークフローの未来を形作る手助けをしましょう! + +> [!NOTE] +> ベータ版の間、APIキーを取得するには[Discord](https://discord.com/invite/JTSBGRZrzj)でお問い合わせください。 + +> [!TIP] +> 🐛 バグを見つけましたか?提案がありますか?私たちはあなたの意見を聞きたいです! +> [Discord](https://discord.com/invite/JTSBGRZrzj)に参加するか、[issue](https://github.com/julep-ai/julep/issues)を開いてください。 + +安定版リリースに向けて、さらに多くの更新情報をお楽しみに!📢 + +***** + +## 紹介 + +Julepは、カスタマイズ可能なワークフローを持つ持続可能なAIエージェントを作成するためのオープンソースプラットフォームです。柔軟性と使いやすさに重点を置いて、AI駆動のアプリケーションを開発、管理、展開するためのツールを提供します。 + +Julepを使用すると、次のことができます: +- 複数のインタラクションにわたってコンテキストと状態を保持するAIエージェントを迅速に開発する +- AIエージェントに合わせた洗練されたワークフローを設計および実行する +- さまざまなツールやAPIをAIワークフローにシームレスに統合する +- 持続的なセッションとユーザーインタラクションを簡単に管理する + +チャットボットの開発、タスクの自動化、または複雑なAIアシスタントの構築を行う場合でも、Julepはアイデアを迅速かつ効率的に現実に変えるために必要な柔軟性と機能を提供します。 + + + +
+ここに簡単なPythonの例があります: + + + +

+from julep import Julep, AsyncJulep
+
+# 🔑 Julepクライアントを初期化する
+#     または、非同期操作のためにAsyncJulepを使用する
+client = Julep(api_key="your_api_key")
+
+##################
+## 🤖 エージェント 🤖 ##
+##################
+
+# 研究エージェントを作成する
+agent = client.agents.create(
+    name="Research Agent",
+    model="claude-3.5-sonnet",
+    about="You are a research agent designed to handle research inquiries.",
+)
+
+# 🔍 エージェントにウェブ検索ツールを追加する
+client.agents.tools.create(
+    agent_id=agent.id,
+    name="web_search",  # Pythonの有効な変数名である必要があります
+    description="Use this tool to research inquiries.",
+    integration={
+        "provider": "brave",
+        "method": "search",
+        "setup": {
+            "api_key": "your_brave_api_key",
+        },
+    },
+)
+
+#################
+## 💬 チャット 💬 ##
+#################
+
+# エージェントとのインタラクティブなチャットセッションを開始する
+session = client.sessions.create(
+    agent_id=agent.id,
+    context_overflow="adaptive",  # 🧠 必要に応じてJulepがコンテキストウィンドウを動的に計算します
+)
+
+# 🔄 チャットループ
+while (user_input := input("You: ")) != "exit":
+    response = client.sessions.chat(
+        session_id=session.id,
+        message=user_input,
+    )
+
+    print("Agent: ", response.choices[0].message.content)
+
+
+#################
+## 📋 タスク 📋 ##
+#################
+
+# エージェントのための定期的な研究タスクを作成する
+task = client.tasks.create(
+    agent_id=agent.id,
+    name="Research Task",
+    description="Research the given topic every 24 hours.",
+    #
+    # 🛠️ タスク固有のツール
+    tools=[
+        {
+            "name": "send_email",
+            "description": "Send an email to the user with the results.",
+            "api_call": {
+                "method": "post",
+                "url": "https://api.sendgrid.com/v3/mail/send",
+                "headers": {"Authorization": "Bearer YOUR_SENDGRID_API_KEY"},
+            },
+        }
+    ],
+    #
+    # 🔢 タスクの主なステップ
+    main=[
+        #
+        # ステップ1:トピックを調査する
+        {
+            # `_`(アンダースコア)変数は前のステップの出力を指します
+            # ここでは、ユーザーからのトピック入力を指します
+            "prompt": "Look up topic '{{_.topic}}' and summarize the results.",
+            "tools": [{"ref": {"name": "web_search"}}],  # 🔍 エージェントのウェブ検索ツールを使用する
+            "unwrap": True,
+        },
+        #
+        # ステップ2:研究結果を含むメールを送信する
+        {
+            "tool": "send_email",
+            "arguments": {
+                "subject": "Research Results",
+                "body": "'Here are the research results for today: ' + _.content",
+                "to": "inputs[0].email",  # ユーザーの入力からメールを参照する
+            },
+        },
+        #
+        # ステップ3:繰り返す前に24時間待つ
+        {"sleep": "24 * 60 * 60"},
+    ],
+)
+
+# 🚀 定期的なタスクを開始する
+client.executions.create(task_id=task.id, input={"topic": "Python"})
+
+# 🔁 これにより、タスクは24時間ごとに実行され、
+#    "Python"のトピックを調査し、
+#    結果をユーザーのメールに送信します
+
+
+ + +## 特徴 + +Julepは、カスタマイズ可能なワークフローを持つ持続可能なAIエージェントの構築プロセスを簡素化します。主な特徴は次のとおりです: + +- **持続可能なAIエージェント**:複数のインタラクションにわたってコンテキストを保持するAIエージェントを作成および管理します。 +- **カスタマイズ可能なワークフロー**:タスクを使用して複雑な多段階のAIワークフローを設計します。 +- **ツール統合**:さまざまなツールやAPIをAIワークフローにシームレスに統合します。 +- **ドキュメント管理**:エージェントのためのドキュメントを効率的に管理および検索します。 +- **セッション管理**:継続的なインタラクションのための持続的なセッションを処理します。 +- **柔軟な実行**:ワークフローでの並行処理、条件ロジック、およびエラー処理をサポートします。 + +## インストール + +Julepを始めるには、[npm](https://www.npmjs.com/package/@julep/sdk)または[pip](https://pypi.org/project/julep/)を使用してインストールします: + +```bash +npm install @julep/sdk +``` + +または + +```bash +pip install julep +``` + +> [!TIP] +> ~~APIキーを[こちら](https://app.julep.ai/api-keys)から取得してください。~~ +> +> ベータ版の間、APIキーを取得するには[Discord](https://discord.com/invite/JTSBGRZrzj)でお問い合わせください。 + +## クイックスタートガイド + +### ステップ1:Julepをインポートする + +まず、Julep SDKをプロジェクトにインポートします: + +```javascript +const Julep = require('@julep/sdk'); +``` + +または + +```python +from julep import AsyncJulep +``` + +### ステップ2:エージェントを初期化する + +基本設定で新しいエージェントを作成します: + +```javascript +const julep = new Julep({ apiKey: 'your-api-key' }); + +const agent = await julep.agents.create({ + name: 'ResearchAssistant', + model: 'gpt-4-turbo', + about: "You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", +}); +``` + +または + +```python +client = AsyncJulep(api_key="your_api_key") + +agent = await client.agents.create( + name="Storytelling Agent", + model="gpt-4-turbo", + about="You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", +) +``` + +### ステップ3:エージェントとチャットする + +エージェントとのインタラクティブなチャットセッションを開始します: + +```javascript +const session = await julep.sessions.create({ + agentId: agent.id, +}); + +// エージェントにメッセージを送信する +const response = await julep.sessions.chat({ + sessionId: session.id, + message: 'Hello, can you tell me a story?', +}); + +console.log(response); +``` + +または + +```python +session = await client.sessions.create(agent_id=agent.id) + +# エージェントにメッセージを送信する +response = await client.sessions.chat( + session_id=session.id, + message="Hello, can you tell me a story?", +) + +print(response) +``` + + +### ステップ4:多段階タスクを作成する + +入力されたアイデアに基づいてストーリーを作成し、パネル化されたコミックストリップを生成する多段階タスクを定義しましょう: + +```python +# 🛠️ エージェントに画像生成ツール(DALL·E)を追加する +await client.agents.tools.create( + agent_id=agent.id, + name="image_generator", + description="Use this tool to generate images based on descriptions.", + integration={ + "provider": "dalle", + "method": "generate_image", + "setup": { + "api_key": "your_dalle_api_key", + }, + }, +) + +# 📋 タスク +# アイデアを受け取り、ストーリーと4コマ漫画を作成するタスクを作成する +task = await client.tasks.create( + agent_id=agent.id, + name="Story and Comic Creator", + description="Create a story based on an idea and generate a 4-panel comic strip illustrating the story.", + main=[ + # ステップ1:ストーリーを生成し、4つのパネルに要約する + { + "prompt": [ + { + "role": "system", + "content": "You are {{agent.name}}. {{agent.about}}" + }, + { + "role": "user", + "content": ( + "Based on the idea '{{_.idea}}', write a short story suitable for a 4-panel comic strip. " + "Provide the story and a numbered list of 4 brief descriptions for each panel illustrating key moments in the story." + ), + }, + ], + "unwrap": True, + }, + # ステップ2:パネルの説明とストーリーを抽出する + { + "evaluate": { + "story": "_.split('1. ')[0].strip()", + "panels": "re.findall(r'\\d+\\.\\s*(.*?)(?=\\d+\\.\\s*|$)', _)", + } + }, + # ステップ3:画像生成ツールを使用して各パネルの画像を生成する + { + "foreach": { + "in": "_.panels", + "do": { + "tool": "image_generator", + "arguments": { + "description": "_", + }, + }, + }, + }, + # ステップ4:ストーリーのキャッチーなタイトルを生成する + { + "prompt": [ + { + "role": "system", + "content": "You are {{agent.name}}. {{agent.about}}" + }, + { + "role": "user", + "content": "Based on the story below, generate a catchy title.\n\nStory: {{outputs[1].story}}", + }, + ], + "unwrap": True, + }, + # ステップ5:ストーリー、生成された画像、およびタイトルを返す + { + "return": { + "title": "outputs[3]", + "story": "outputs[1].story", + "comic_panels": "[output.image.url for output in outputs[2]]", + } + }, + ], +) +``` + +> [!TIP] +> これのnode.jsバージョンは似ています。 + +### ステップ5:タスクを実行する + +```python +# 🚀 アイデアを入力してタスクを実行する +execution = await client.executions.create( + task_id=task.id, + input={"idea": "A cat who learns to fly"} +) + +# 🎉 ストーリーとコミックパネルが生成される様子を見守る +await client.executions.stream(execution_id=execution.id) +``` + +この例は、カスタムツールを持つエージェントを作成し、複数のステップを持つ複雑なタスクを定義し、それを実行してクリエイティブな出力を生成する方法を示しています。 + + + +> [!TIP] +> もう一つのnode.jsの例は[こちら](example.ts)またはpythonの例は[こちら](example.py)にあります。 + +## 概念 + +Julepは、強力なAIワークフローを作成するために連携するいくつかの主要な技術コンポーネントに基づいて構築されています: + +### エージェント +タスクを実行し、ユーザーと対話する大規模な言語モデル(LLM)に支えられたAIエンティティ。エージェントはJulepのコア機能ユニットです。 + +```mermaid +graph TD + Agent[Agent] --> LLM[Large Language Model] + Agent --> Tasks[Tasks] + Agent --> Users[Users] + Tasks --> Tools[Tools] +``` + +### ユーザー +エージェントと対話するエンティティ。ユーザーはセッションに関連付けられ、独自のメタデータを持つことができ、個別の対話が可能になります。 + +```mermaid +graph LR + User[User] --> Sessions[Sessions] + Sessions --> Agents[Agents] + Sessions --> Metadata[Metadata] +``` + +### セッション +エージェントとユーザーの間の有状態の対話。セッションは複数の交換にわたってコンテキストを保持し、コンテキスト管理やオーバーフロー処理などの異なる動作に対して構成できます。 + +```mermaid +graph LR + Sessions[Sessions] --> Agents[Agents] + Sessions --> Users[Users] + Sessions --> ContextManagement[Context Management] + Sessions --> OverflowHandling[Overflow Handling] +``` + +### タスク +エージェントが実行できる多段階のプログラムワークフロー。タスクは複雑な操作を定義し、プロンプト、ツール呼び出し、条件ロジックなどのさまざまなタイプのステップを含むことができます。 + +```mermaid +graph TD + Tasks[Tasks] --> Steps[Workflow Steps] + Steps --> Prompt[Prompt] + Steps --> ToolCalls[Tool Calls] + Steps --> ConditionalLogic[Conditional Logic] +``` + +### ツール +エージェントの能力を拡張する統合。ツールはユーザー定義の関数、システムツール、またはサードパーティのAPI統合である可能性があります。これにより、エージェントはテキスト生成を超えたアクションを実行できます。 + +```mermaid +graph LR + Tools[Tools] --> UserDefinedFunctions[User-Defined Functions] + Tools --> SystemTools[System Tools] + Tools --> ThirdPartyAPIs[Third-Party APIs] +``` + +### ドキュメント +エージェントまたはユーザーに関連付けることができるテキストまたはデータオブジェクト。ドキュメントはベクトル化され、エージェントの対話中にセマンティック検索と取得を可能にするベクトルデータベースに保存されます。 + +```mermaid +graph LR + Documents[Documents] --> VectorDatabase[Vector Database] + Documents --> SemanticSearch[Semantic Search] + Documents --> AgentsOrUsers[Agents or Users] +``` + +### 実行 +特定の入力で開始されたタスクのインスタンス。実行には独自のライフサイクルと状態マシンがあり、長時間実行されるプロセスの監視、管理、および再開が可能です。 + +```mermaid +graph LR + Executions[Executions] --> Tasks[Tasks] + Executions --> Lifecycle[Lifecycle] + Executions --> Monitoring[Monitoring] + Executions --> Management[Management] + Executions --> Resumption[Resumption] +``` + +これらの概念とその相互作用の詳細な説明については、[概念ドキュメント](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)を参照してください。 + +## タスクの理解 + +タスクはJulepのワークフローシステムのコアです。これにより、エージェントが実行できる複雑な多段階のAIワークフローを定義できます。タスクコンポーネントの概要は次のとおりです: + +- **名前と説明**:各タスクには、簡単に識別できるように一意の名前と説明があります。 +- **主要なステップ**:タスクのコアであり、実行されるアクションのシーケンスを定義します。 +- **ツール**:タスク実行中にエージェントの能力を拡張するオプションの統合。 + +### ワークフローステップの種類 + +Julepのタスクには、さまざまな種類のステップを含めることができます: + +1. **プロンプト**:AIモデルにメッセージを送信し、応答を受け取ります。 + ```python + {"prompt": "Analyze the following data: {{data}}"} + ``` + +2. **ツール呼び出し**:統合されたツールまたはAPIを実行します。 + ```python + {"tool": "web_search", "arguments": {"query": "Latest AI developments"}} + ``` + +3. **評価**:計算を実行するか、データを操作します。 + ```python + {"evaluate": {"average_score": "sum(scores) / len(scores)"}} + ``` + +4. **条件ロジック**:条件に基づいてステップを実行します。 + ```python + {"if": "score > 0.8", "then": [...], "else": [...]} + ``` + +5. **ループ**:データを反復処理するか、ステップを繰り返します。 + ```python + {"foreach": {"in": "data_list", "do": [...]}} + ``` + +| ステップ名 | 説明 | 入力 | +|--------------------|--------------------------------------------------------------------------------------------------|------------------------------------------------------| +| **プロンプト** | AIモデルにメッセージを送信し、応答を受け取ります。 | プロンプトテキストまたはテンプレート | +| **ツール呼び出し** | 統合されたツールまたはAPIを実行します。 | ツール名と引数 | +| **評価** | 計算を実行するか、データを操作します。 | 評価する式または変数 | +| **入力待ち** | 入力が受信されるまでワークフローを一時停止します。 | 必要なユーザーまたはシステム入力 | +| **ログ** | 指定された値またはメッセージを記録します。 | 記録するメッセージまたは値 | +| **埋め込み** | テキストを特定の形式またはシステムに埋め込みます。 | 埋め込むテキストまたはコンテンツ | +| **検索** | クエリに基づいてドキュメント検索を実行します。 | 検索クエリ | +| **取得** | キー値ストアから値を取得します。 | キー識別子 | +| **設定** | キー値ストアのキーに値を割り当てます。 | 割り当てるキーと値 | +| **並列** | 複数のステップを並行して実行します。 | 同時に実行するステップのリスト | +| **反復** | コレクションを反復処理し、各アイテムに対してステップを実行します。 | 反復するコレクションまたはリスト | +| **マップリデュース** | コレクションをマップし、式に基づいて結果をリデュースします。 | マップおよびリデュースするコレクションと式 | +| **条件分岐** | 条件に基づいてステップを実行します。 | 評価する条件 | +| **スイッチ** | 複数の条件に基づいてステップを実行します。スイッチケース文に似ています。 | 複数の条件と対応するステップ | +| **生成** | サブワークフローを実行し、その完了を待ちます。 | サブワークフロー識別子と入力データ | +| **エラー** | エラーメッセージを指定してエラーを処理します。 | エラーメッセージまたは処理指示 | +| **スリープ** | 指定された期間ワークフローを一時停止します。 | 期間(秒、分など) | +| **リターン** | ワークフローから値を返します。 | 返す値 | + +各ステップタイプの詳細情報と高度な使用法については、[タスクドキュメント](https://docs.julep.ai/tasks)を参照してください。 + +## 高度な機能 + +Julepは、AIワークフローを強化するための高度な機能を提供します: + +### エージェントにツールを追加する + +外部ツールやAPIを統合してエージェントの能力を拡張します: + +```python +client.agents.tools.create( + agent_id=agent.id, + name="web_search", + description="Search the web for information.", + integration={ + "provider": "google", + "method": "search", + "setup": {"api_key": "your_google_api_key"}, + }, +) +``` + +### セッションとユーザーの管理 + +Julepは、持続的なインタラクションのための強力なセッション管理を提供します: + +```python +session = client.sessions.create( + agent_id=agent.id, + user_id="user123", + context_overflow="adaptive" +) + +# 同じセッションで会話を続ける +response = client.sessions.chat( + session_id=session.id, + message="Follow up on our previous conversation." +) +``` + +### ドキュメントの統合と検索 + +エージェントのためのドキュメントを簡単に管理および検索します: + +```python +# ドキュメントをアップロードする +document = client.documents.create( + file="path/to/document.pdf", + metadata={"category": "research_paper"} +) + +# ドキュメントを検索する +results = client.documents.search( + query="AI advancements", + filter={"category": "research_paper"} +) +``` + +高度な機能と詳細な使用法については、[高度な機能ドキュメント](https://docs.julep.ai/advanced-features)を参照してください。 + +## SDKリファレンス + +- [Node.js SDK](https://github.com/julep-ai/node-sdk/blob/main/api.md) +- [Python SDK](https://github.com/julep-ai/python-sdk/blob/main/api.md) + +## APIリファレンス + +エージェント、タスク、および実行について詳しく学ぶために、包括的なAPIドキュメントを探索してください: + +- [エージェントAPI](https://api.julep.ai/api/docs#tag/agents) +- [タスクAPI](https://api.julep.ai/api/docs#tag/tasks) +- [実行API](https://api.julep.ai/api/docs#tag/executions) + +## 例とチュートリアル + +提供された例を基にして始めるのに役立つ例のプロジェクトとチュートリアルを見つけてください: + +- [例のプロジェクト](https://github.com/julep-ai/julep/tree/main/examples) +- [チュートリアル](https://docs.julep.ai/tutorials) + +## 貢献 + +プロジェクトへの貢献を歓迎します!貢献方法と行動規範を学びましょう: + +- [貢献ガイドライン](https://github.com/julep-ai/julep/blob/main/CONTRIBUTING.md) +- [行動規範](https://github.com/julep-ai/julep/blob/main/CODE_OF_CONDUCT.md) + +## サポートとコミュニティ + +コミュニティに参加して、助けを得たり、質問したり、アイデアを共有したりしましょう: + +- [Discord](https://discord.com/invite/JTSBGRZrzj) +- [GitHub Discussions](https://github.com/julep-ai/julep/discussions) +- [Twitter](https://twitter.com/julep_ai) + +## ライセンス + +このプロジェクトは[Apache License 2.0](https://github.com/julep-ai/julep/blob/main/LICENSE)の下でライセンスされています。 + +## 謝辞 + +貴重なリソースと貢献を提供してくれたすべての貢献者とオープンソースコミュニティに感謝します。 diff --git a/README.md b/README.md index af87426b1..1a2657966 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The **Quick Start Guide Focused README** is the most promising for optimizing th * **Tone:** Maintain an encouraging and helpful tone throughout the README --> -English | [中文翻译](/README-CN.md) +English | [中文翻译](/README-CN.md) | [日本語翻訳](/README-JP.md)
julep From 35ec6af06b57db8131402a9f95e9092b3493d33d Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Sun, 6 Oct 2024 12:04:56 -0400 Subject: [PATCH 02/23] fix: Minor html fixes in READMEs Signed-off-by: Diwank Singh Tomer --- README-JP.md | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README-JP.md b/README-JP.md index 6110c5601..9aa04480c 100644 --- a/README-JP.md +++ b/README-JP.md @@ -1,7 +1,7 @@ -[English](README.md) | [中文](README-CN.md) | 日本語 +[English](README.md) | [中文翻译](/README-CN.md) | 日本語
- julep + julep

diff --git a/README.md b/README.md index 1a2657966..ca6e48531 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ The **Quick Start Guide Focused README** is the most promising for optimizing th English | [中文翻译](/README-CN.md) | [日本語翻訳](/README-JP.md)

- julep + julep

From d26c977493c13675e79198fbe3abca82c377d181 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Sun, 6 Oct 2024 19:15:20 -0400 Subject: [PATCH 03/23] doc: Update README according to feedback, add TOC and collapse devfest callout (#599) Signed-off-by: Diwank Singh Tomer ---- > [!IMPORTANT] > Enhances `README` files by adding TOC and collapsing DevFest.AI callout, and introduces a GitHub Action for TOC generation. > > - **GitHub Actions**: > - Adds `.github/workflows/doctoc-on-dev-push.yml` to generate TOC on push to `dev` branch using `technote-space/toc-generator@v4`. > - **README Updates**: > - Collapses "Contributors and DevFest.AI Participants" section in `README.md`, `README-CN.md`, and `README-JP.md` using `

` and `` tags. > - Removes Julep 1.0 Alpha release announcement from `README.md`, `README-CN.md`, and `README-JP.md`. > > This description was created by [Ellipsis](https://www.ellipsis.dev?ref=julep-ai%2Fjulep&utm_source=github&utm_medium=referral) for b65a1f0f1bfe713220648d08ab20e8ef93087024. It will automatically update as commits are pushed. --------- Signed-off-by: Diwank Singh Tomer Co-authored-by: vedantsahai18 Co-authored-by: creatorrr --- .github/workflows/doctoc-on-dev-push.yml | 15 + README-CN.md | 51 +- README-JP.md | 50 +- README.md | 856 +++++----- agents-api/poetry.lock | 301 ++-- agents-api/pyproject.toml | 1 + cookbooks/01-Website_Crawler_using_Spider.py | 71 + .../02-Sarcastic_News_Headline_Generator.py | 89 ++ .../03-SmartResearcher_With_WebSearch.py | 104 ++ ...4-TripPlanner_With_Weather_And_WikiInfo.py | 123 ++ ...05-Basic_Agent_Creation_and_Interaction.py | 71 + cookbooks/06-Designing_Multi-Step_Tasks.py | 138 ++ .../07-Integrating_External_Tools_and_APIs.py | 126 ++ cookbooks/08-Managing_Persistent_Sessions.py | 137 ++ .../09-User_Management_and_Personalization.py | 188 +++ .../10-Document_Management_and_Search.py | 156 ++ cookbooks/11-Advanced_Chat_Interactions.py | 177 +++ cookbooks/12-Monitoring_Task_Executions.py | 160 ++ cookbooks/13-Error_Handling_and_Recovery.py | 163 ++ cookbooks/IDEAS.md | 1377 +++++++++++++++++ cookbooks/README.md | 9 +- sdks/node-sdk | 2 +- sdks/python-sdk | 2 +- 23 files changed, 3779 insertions(+), 588 deletions(-) create mode 100644 .github/workflows/doctoc-on-dev-push.yml create mode 100644 cookbooks/01-Website_Crawler_using_Spider.py create mode 100644 cookbooks/02-Sarcastic_News_Headline_Generator.py create mode 100644 cookbooks/03-SmartResearcher_With_WebSearch.py create mode 100644 cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py create mode 100644 cookbooks/05-Basic_Agent_Creation_and_Interaction.py create mode 100644 cookbooks/06-Designing_Multi-Step_Tasks.py create mode 100644 cookbooks/07-Integrating_External_Tools_and_APIs.py create mode 100644 cookbooks/08-Managing_Persistent_Sessions.py create mode 100644 cookbooks/09-User_Management_and_Personalization.py create mode 100644 cookbooks/10-Document_Management_and_Search.py create mode 100644 cookbooks/11-Advanced_Chat_Interactions.py create mode 100644 cookbooks/12-Monitoring_Task_Executions.py create mode 100644 cookbooks/13-Error_Handling_and_Recovery.py create mode 100644 cookbooks/IDEAS.md diff --git a/.github/workflows/doctoc-on-dev-push.yml b/.github/workflows/doctoc-on-dev-push.yml new file mode 100644 index 000000000..f70807245 --- /dev/null +++ b/.github/workflows/doctoc-on-dev-push.yml @@ -0,0 +1,15 @@ +on: push + +name: TOC Generator +jobs: + generateTOC: + name: TOC Generator + runs-on: ubuntu-latest + steps: + - uses: technote-space/toc-generator@v4 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MAX_HEADER_LEVEL: 2 + TOC_TITLE: '📖 Table of Contents' + FOLDING: true + diff --git a/README-CN.md b/README-CN.md index 437faf13b..55ea307ca 100644 --- a/README-CN.md +++ b/README-CN.md @@ -28,6 +28,12 @@ ***** +> [!TIP] +> 👨‍💻 来参加 devfest.ai 活动?加入我们的 [Discord](https://discord.com/invite/JTSBGRZrzj) 并查看下方详情。 + +
+🌟 贡献者和 DevFest.AI 参与者: + ## 🌟 诚邀贡献者! 我们很高兴欢迎新的贡献者加入 Julep 项目!我们创建了几个"适合新手的问题"来帮助您入门。以下是您可以贡献的方式: @@ -51,31 +57,30 @@ ![Julep DevFest.AI](https://media.giphy.com/media/YjyUeyotft6epaMHtU/giphy.gif) -***** - -## 🎉🚀 **激动人心的消息:Julep 1.0 Alpha 版发布!** 🚀🎉 - -我们很高兴地宣布 **Julep 1.0** 的 **alpha** 版本发布!🥳 - -🌟 **新特性:** -- 增强的工作流功能 -- 改进的代理持久性 -- 大量内置工具集成(如 DALL·E、Google 搜索、SendGrid 等) -- 简化的 API - -🧪 尝试使用并帮助塑造 AI 工作流的未来! - -> [!NOTE] -> 在测试阶段,您可以通过 [Discord](https://discord.com/invite/JTSBGRZrzj) 获取 API 密钥。 - -> [!TIP] -> 🐛 发现了 bug?有建议?我们很乐意听取您的意见! -> 加入我们的 [Discord](https://discord.com/invite/JTSBGRZrzj) 或提交 [issue](https://github.com/julep-ai/julep/issues)。 - -请继续关注我们即将发布的稳定版本的更多更新!📢 +
+ + +
+📖 Table of Contents + +- [简介](#%E7%AE%80%E4%BB%8B) +- [特性](#%E7%89%B9%E6%80%A7) +- [安装](#%E5%AE%89%E8%A3%85) +- [快速入门指南](#%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97) +- [概念](#%E6%A6%82%E5%BF%B5) +- [理解任务](#%E7%90%86%E8%A7%A3%E4%BB%BB%E5%8A%A1) +- [高级功能](#%E9%AB%98%E7%BA%A7%E5%8A%9F%E8%83%BD) +- [SDK 参考](#sdk-%E5%8F%82%E8%80%83) +- [API 参考](#api-%E5%8F%82%E8%80%83) +- [示例和教程](#%E7%A4%BA%E4%BE%8B%E5%92%8C%E6%95%99%E7%A8%8B) +- [贡献](#%E8%B4%A1%E7%8C%AE) +- [支持和社区](#%E6%94%AF%E6%8C%81%E5%92%8C%E7%A4%BE%E5%8C%BA) +- [许可证](#%E8%AE%B8%E5%8F%AF%E8%AF%81) +- [致谢](#%E8%87%B4%E8%B0%A2) -***** +
+ ## 简介 diff --git a/README-JP.md b/README-JP.md index 9aa04480c..8f9e49cc2 100644 --- a/README-JP.md +++ b/README-JP.md @@ -28,6 +28,12 @@ ***** +> [!TIP] +> 👨‍💻 devfest.aiイベントに参加されましたか?私たちの[Discord](https://discord.com/invite/JTSBGRZrzj)に参加して、以下の詳細をご確認ください。 + +
+🌟 コントリビューターとDevFest.AI参加者の皆様へ: + ## 🌟 コントリビューター募集! Julepプロジェクトに新しいコントリビューターを歓迎します!スタートに役立つ「初心者向けの問題」をいくつか作成しました。以下は、貢献する方法です: @@ -51,30 +57,30 @@ Julepプロジェクトに新しいコントリビューターを歓迎します ![Julep DevFest.AI](https://media.giphy.com/media/YjyUeyotft6epaMHtU/giphy.gif) -***** - -## 🎉🚀 **エキサイティングなニュース:Julep 1.0 Alphaリリース!** 🚀🎉 - -**Julep 1.0**の**アルファ**リリースを発表できることを嬉しく思います!🥳 - -🌟 **新機能:** -- 強化されたワークフロー機能 -- 改善されたエージェントの持続性 -- 多数の組み込みツール統合(dalle、google検索、sendgridなど) -- 簡素化されたAPI - -🧪 試してみて、AIワークフローの未来を形作る手助けをしましょう! - -> [!NOTE] -> ベータ版の間、APIキーを取得するには[Discord](https://discord.com/invite/JTSBGRZrzj)でお問い合わせください。 - -> [!TIP] -> 🐛 バグを見つけましたか?提案がありますか?私たちはあなたの意見を聞きたいです! -> [Discord](https://discord.com/invite/JTSBGRZrzj)に参加するか、[issue](https://github.com/julep-ai/julep/issues)を開いてください。 +
-安定版リリースに向けて、さらに多くの更新情報をお楽しみに!📢 + + +
+📖 Table of Contents + +- [紹介](#%E7%B4%B9%E4%BB%8B) +- [特徴](#%E7%89%B9%E5%BE%B4) +- [インストール](#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%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%E3%82%AC%E3%82%A4%E3%83%89) +- [概念](#%E6%A6%82%E5%BF%B5) +- [タスクの理解](#%E3%82%BF%E3%82%B9%E3%82%AF%E3%81%AE%E7%90%86%E8%A7%A3) +- [高度な機能](#%E9%AB%98%E5%BA%A6%E3%81%AA%E6%A9%9F%E8%83%BD) +- [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) +- [例とチュートリアル](#%E4%BE%8B%E3%81%A8%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB) +- [貢献](#%E8%B2%A2%E7%8C%AE) +- [サポートとコミュニティ](#%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%81%A8%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3) +- [ライセンス](#%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9) +- [謝辞](#%E8%AC%9D%E8%BE%9E) -***** +
+ ## 紹介 diff --git a/README.md b/README.md index ca6e48531..37baacbc6 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,3 @@ - - English | [中文翻译](/README-CN.md) | [日本語翻訳](/README-JP.md)
@@ -46,6 +28,12 @@ The **Quick Start Guide Focused README** is the most promising for optimizing th ***** +> [!TIP] +> 👨‍💻 Here for the devfest.ai event? Join our [Discord](https://discord.com/invite/JTSBGRZrzj) and check out the details below. + +
+🌟 Contributors and DevFest.AI Participants + ## 🌟 Call for Contributors! We're excited to welcome new contributors to the Julep project! We've created several "good first issues" to help you get started. Here's how you can contribute: @@ -65,176 +53,210 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓 - A big thank you to DevFest.AI for organizing this fantastic initiative! > [!TIP] -> Ready to join the fun? **[Tweet to start participating](https://twitter.com/intent/tweet?text=Pumped%20to%20be%20participating%20in%20%40devfestai%20with%20%40julep_ai%20building%20%23ai%20%23agents%20%23workflows%20Let's%20gooo!%20https%3A%2F%2Fgit.new%2Fjulep)** and let's get coding! 🖥️ +> Ready to join the fun? **[Tweet that you are participating](https://twitter.com/intent/tweet?text=Pumped%20to%20be%20participating%20in%20%40devfestai%20with%20%40julep_ai%20building%20%23ai%20%23agents%20%23workflows%20Let's%20gooo!%20https%3A%2F%2Fgit.new%2Fjulep)** and let's get coding! 🖥️ ![Julep DevFest.AI](https://media.giphy.com/media/YjyUeyotft6epaMHtU/giphy.gif) -***** +
-## 🎉🚀 **Exciting News: Julep 1.0 Alpha Release!** 🚀🎉 + + +
+📖 Table of Contents + +- [Quick Intro](#quick-intro) +- [Key Features](#key-features) +- [Why Julep vs. LangChain?](#why-julep-vs-langchain) +- [Installation](#installation) +- [Python Quick Start 🐍](#python-quick-start-) +- [Node.js Quick Start 🟩](#nodejs-quick-start-) +- [Components](#components) +- [Concepts](#concepts) +- [Understanding Tasks](#understanding-tasks) +- [Advanced Features](#advanced-features) +- [SDK Reference](#sdk-reference) +- [API Reference](#api-reference) -We're thrilled to announce the **alpha** release of Julep 1.0! 🥳 +
+ -🌟 **What's New:** -- Enhanced workflow capabilities -- Improved agent persistence -- Tons of in-built tool integrations (like dalle, google search, sendgrid, etc.) -- Streamlined API +## Quick Intro -🧪 Try it out and help shape the future of AI workflows! + -> [!NOTE] -> While we are in beta, you can reach out on [Discord](https://discord.com/invite/JTSBGRZrzj) to get your API key. +Julep is a platform for creating AI agents that maintain state and execute complex workflows. It offers long-term context and orchestrates multi-step tasks. + +Imagine you want to build an AI agent that can do more than just answer simple queries—it needs to handle complex tasks, remember past interactions, and maybe even integrate with other tools or APIs. That's where Julep comes in. + +Julep lets you define multi-step tasks that can include conditional logic, loops, parallel processing, and built-in integration with 100s of external tools and APIs. Typically AI applications tend to be linear and have simple chains of a handful of prompts and API calls without much branching or decision-making. + +Imagine a Research AI agent that can do the following: + 1. Take a topic, + 2. Come up with 100 search queries for that topic, + 3. Perform those web searches in parallel, + 4. Collect and compile the results, + 5. Come up with 5 follow-up questions, + 6. Repeat the process with new queries, + 7. Summarize the results, + 8. Send the summary to Discord + +In julep, this would be a single task under 80 lines of code and run fully managed all on its own. Here's a working example: + +```yaml +name: Research Agent + +# Optional: Define the input schema for the task +input_schema: + type: object + properties: + topic: + type: string + description: The main topic to research + +# 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 + +# Special variables: +# - inputs: for accessing the input to the task +# - outputs: for accessing the output of previous steps +# - _: for accessing the output of the previous step + +# Define the main workflow +main: +- prompt: + - role: system + content: >- + You are a research assistant. + Generate 100 diverse search queries related to the topic: + {{inputs[0].topic}} + + Write one query per line. + unwrap: true + +# Evaluate the search queries using a simple python expression +- evaluate: + search_queries: "_.split('\n')" + +# Run the web search in parallel for each query +- over: "_.search_queries" + map: + tool: web_search + arguments: + query: "_" + on_error: + parallelism: 100 + +# Collect the results from the web search +- evaluate: + results: "'\n'.join([item.result for item in _])" + +# Generate follow-up questions based on the results +- prompt: + - role: system + content: >- + Based on the following research results, generate 5 follow-up questions that would deepen our understanding of {{inputs[0].topic}}: + {{_.results}} + + Write one question per line. + unwrap: true + +- evaluate: + follow_up_queries: "_.split('\n')" + +# Run the web search in parallel for each follow-up query +- over: "_.follow_up_queries" + map: + tool: web_search + arguments: + query: "_" + + parallelism: 5 + +- evaluate: + all_results: "outputs[3].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: + {{_.all_results}} + unwrap: true + +# Send the summary to Discord +- tool: discord_webhook + arguments: + content: > + **Research Summary for {{inputs[0].topic}}** + + {{_}} +``` > [!TIP] -> 🐛 Found a bug? Have a suggestion? We'd love to hear from you! -> Join our [Discord](https://discord.com/invite/JTSBGRZrzj) or open an [issue](https://github.com/julep-ai/julep/issues). +> Julep is really useful when you want to build AI agents that can maintain context and state over long-term interactions. It's great for designing complex, multi-step workflows and integrating various tools and APIs directly into your agent's processes. -Stay tuned for more updates as we approach our stable release! 📢 -***** +## Key Features -## Introduction +1. **Persistent AI Agents**: Persist context and state over long-term interactions. +2. **Stateful Sessions**: Remember past interactions for personalized responses. +3. **Multi-Step Workflows**: Build complex, multi-step processes with loops and conditional logic. +4. **Task Orchestration**: Manage long-running tasks that can run indefinitely. +5. **Built-in Tools**: Integrate built-in tools and external APIs into workflows. +6. **Self-Healing**: Julep will automatically retry failed steps, resend messages, and generally keep your workflows running smoothly. +7. **RAG**: Use Julep's document store to build a RAG system for your own data. -Julep is an open-source platform for creating persistent AI agents with customizable workflows. It provides tools to develop, manage, and deploy AI-driven applications, focusing on flexibility and ease of use. +Julep is ideal for applications that require AI use cases beyond simple prompt-response models. -With Julep, you can: -- Quickly develop AI agents that retain context and state across interactions -- Design and execute sophisticated workflows tailored to your AI agents -- Seamlessly integrate various tools and APIs into your AI workflows -- Effortlessly manage persistent sessions and user interactions +## Why Julep vs. LangChain? -Whether you're developing a chatbot, automating tasks, or building a complex AI assistant, Julep provides the flexibility and features you need to turn your ideas into reality swiftly and efficiently. +### Different Use Cases - - -
-Here's a quick python example: +Think of LangChain and Julep as tools with different focuses within the AI development stack. - +LangChain is great for creating sequences of prompts and managing interactions with LLMs. It has a large ecosystem with lots of pre-built integrations, which makes it convenient if you want to get something up and running quickly. LangChain fits well with simple use cases that involve a linear chain of prompts and API calls. -

-from julep import Julep, AsyncJulep
+Julep, on the other hand, is more about building persistent AI agents that can maintain context over long-term interactions. It shines when you need complex workflows that involve multi-step tasks, conditional logic, and integration with various tools or APIs directly within the agent's process. It's designed from the ground up to manage persistent sessions and complex workflows.
 
-# 🔑 Initialize the Julep client
-#     Or alternatively, use AsyncJulep for async operations
-client = Julep(api_key="your_api_key")
-
-##################
-## 🤖 Agent 🤖 ##
-##################
-
-# Create a research agent
-agent = client.agents.create(
-    name="Research Agent",
-    model="claude-3.5-sonnet",
-    about="You are a research agent designed to handle research inquiries.",
-)
-
-# 🔍 Add a web search tool to the agent
-client.agents.tools.create(
-    agent_id=agent.id,
-    name="web_search",  # Should be python valid variable name
-    description="Use this tool to research inquiries.",
-    integration={
-        "provider": "brave",
-        "method": "search",
-        "setup": {
-            "api_key": "your_brave_api_key",
-        },
-    },
-)
-
-#################
-## 💬 Chat 💬 ##
-#################
-
-# Start an interactive chat session with the agent
-session = client.sessions.create(
-    agent_id=agent.id,
-    context_overflow="adaptive",  # 🧠 Julep will dynamically compute the context window if needed
-)
-
-# 🔄 Chat loop
-while (user_input := input("You: ")) != "exit":
-    response = client.sessions.chat(
-        session_id=session.id,
-        message=user_input,
-    )
+Use Julep if you imagine building a complex AI assistant that needs to:
 
-    print("Agent: ", response.choices[0].message.content)
+- Keep track of user interactions over days or weeks.
+- Perform scheduled tasks, like sending daily summaries or monitoring data sources.
+- Make decisions based on prior interactions or stored data.
+- Interact with multiple external services as part of its workflow.
 
+Then Julep provides the infrastructure to support all that without you having to build it from scratch.
 
-#################
-## 📋 Task 📋 ##
-#################
+### Different Form Factor
 
-# Create a recurring research task for the agent
-task = client.tasks.create(
-    agent_id=agent.id,
-    name="Research Task",
-    description="Research the given topic every 24 hours.",
-    #
-    # 🛠️ Task specific tools
-    tools=[
-        {
-            "name": "send_email",
-            "description": "Send an email to the user with the results.",
-            "api_call": {
-                "method": "post",
-                "url": "https://api.sendgrid.com/v3/mail/send",
-                "headers": {"Authorization": "Bearer YOUR_SENDGRID_API_KEY"},
-            },
-        }
-    ],
-    #
-    # 🔢 Task main steps
-    main=[
-        #
-        # Step 1: Research the topic
-        {
-            # `_` (underscore) variable refers to the previous step's output
-            # Here, it points to the topic input from the user
-            "prompt": "Look up topic '{{_.topic}}' and summarize the results.",
-            "tools": [{"ref": {"name": "web_search"}}],  # 🔍 Use the web search tool from the agent
-            "unwrap": True,
-        },
-        #
-        # Step 2: Send email with research results
-        {
-            "tool": "send_email",
-            "arguments": {
-                "subject": "Research Results",
-                "body": "'Here are the research results for today: ' + _.content",
-                "to": "inputs[0].email",  # Reference the email from the user's input
-            },
-        },
-        #
-        # Step 3: Wait for 24 hours before repeating
-        {"sleep": "24 * 60 * 60"},
-    ],
-)
+Julep is a **platform** that includes a language for describing workflows, a server for running those workflows, and an SDK for interacting with the platform. In order to build something with Julep, you write a description of the workflow in `YAML`, and then run the workflow in the cloud.
 
-# 🚀 Start the recurring task
-client.executions.create(task_id=task.id, input={"topic": "Python"})
+Julep is built for heavy-lifting, multi-step, and long-running workflows and there's no limit to how complex the workflow can be.
 
-# 🔁 This will run the task every 24 hours,
-#    research for the topic "Python", and
-#    send the results to the user's email
-
-
+LangChain is a **library** that includes a few tools and a framework for building linear chains of prompts and tools. In order to build something with LangChain, you typically write Python code that configures and runs the model chains you want to use. +LangChain might be sufficient and quicker to implement for simple use cases that involve a linear chain of prompts and API calls. -## Features +### In Summary -Julep simplifies the process of building persistent AI agents with customizable workflows. Key features include: +Use LangChain when you need to manage LLM interactions and prompt sequences in a stateless or short-term context. -- **Persistent AI Agents**: Create and manage AI agents that maintain context across interactions. -- **Customizable Workflows**: Design complex, multi-step AI workflows using Tasks. -- **Tool Integration**: Seamlessly integrate various tools and APIs into your AI workflows. -- **Document Management**: Efficiently manage and search through documents for your agents. -- **Session Management**: Handle persistent sessions for continuous interactions. -- **Flexible Execution**: Support for parallel processing, conditional logic, and error handling in workflows. +Choose Julep when you need a robust framework for stateful agents with advanced workflow capabilities, persistent sessions, and complex task orchestration. ## Installation @@ -250,93 +272,34 @@ or pip install julep ``` -> [!TIP] +> [!NOTE] > ~~Get your API key [here](https://app.julep.ai/api-keys).~~ > > While we are in beta, you can reach out on [Discord](https://discord.com/invite/JTSBGRZrzj) to get your API key. -## Quick Start Guide - -### Step 1: Import Julep +> [!TIP] +> 💻 Are you a _show me the code!™_ kind of person? We have created a ton of cookbooks for you to get started with. **Check out the [cookbooks](/cookbooks)** to browse through examples. +> +> 💡 There's also lots of ideas that you can build on top of Julep. **Check out the [list of ideas](/cookbooks/IDEAS.md)** to get some inspiration. -First, import the Julep SDK into your project: +## Python Quick Start 🐍 -```javascript -const Julep = require('@julep/sdk'); -``` - -or +### Step 1: Create an Agent ```python -from julep import AsyncJulep -``` - -### Step 2: Initialize the Agent +import yaml +from julep import Julep # or AsyncJulep -Create a new agent with basic settings: +client = Julep(api_key="your_julep_api_key") -```javascript -const julep = new Julep({ apiKey: 'your-api-key' }); - -const agent = await julep.agents.create({ - name: 'ResearchAssistant', - model: 'gpt-4-turbo', - about: "You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", -}); -``` - -or - -```python -client = AsyncJulep(api_key="your_api_key") - -agent = await client.agents.create( +agent = client.agents.create( name="Storytelling Agent", - model="gpt-4-turbo", + model="gpt-4o", about="You are a creative storytelling agent that can craft engaging stories and generate comic panels based on ideas.", ) -``` - -### Step 3: Chat with the Agent - -Start an interactive chat session with the agent: -```javascript -const session = await julep.sessions.create({ - agentId: agent.id, -}); - -// Send messages to the agent -const response = await julep.sessions.chat({ - sessionId: session.id, - message: 'Hello, can you tell me a story?', -}); - -console.log(response); -``` - -or - -```python -session = await client.sessions.create(agent_id=agent.id) - -# Send messages to the agent -response = await client.sessions.chat( - session_id=session.id, - message="Hello, can you tell me a story?", -) - -print(response) -``` - - -### Step 4: Create a multi-step Task - -Let's define a multi-step task to create a story and generate a paneled comic strip based on an input idea: - -```python # 🛠️ Add an image generation tool (DALL·E) to the agent -await client.agents.tools.create( +client.agents.tools.create( agent_id=agent.id, name="image_generator", description="Use this tool to generate images based on descriptions.", @@ -344,183 +307,317 @@ await client.agents.tools.create( "provider": "dalle", "method": "generate_image", "setup": { - "api_key": "your_dalle_api_key", + "api_key": "your_openai_api_key", }, }, ) +``` +### Step 2: Create a Task that generates a story and comic strip + +Let's define a multi-step task to create a story and generate a paneled comic strip based on an input idea: + +```python # 📋 Task # Create a task that takes an idea and creates a story and a 4-panel comic strip -task = await client.tasks.create( +task_yaml = """ +name: Story and Comic Creator +description: Create a story based on an idea and generate a 4-panel comic strip illustrating the story. + +main: + # Step 1: Generate a story and outline into 4 panels + - prompt: + - role: system + content: You are {{agent.name}}. {{agent.about}} + - role: user + content: > + Based on the idea '{{_.idea}}', write a short story suitable for a 4-panel comic strip. + Provide the story and a numbered list of 4 brief descriptions for each panel illustrating key moments in the story. + unwrap: true + + # Step 2: Extract the panel descriptions and story + - evaluate: + story: _.split('1. ')[0].strip() + panels: re.findall(r'\\d+\\.\\s*(.*?)(?=\\d+\\.\\s*|$)', _) + + # Step 3: Generate images for each panel using the image generator tool + - foreach: + in: _.panels + do: + tool: image_generator + arguments: + description: _ + + # Step 4: Generate a catchy title for the story + - prompt: + - role: system + content: You are {{agent.name}}. {{agent.about}} + - role: user + content: > + Based on the story below, generate a catchy title. + + Story: {{outputs[1].story}} + unwrap: true + + # Step 5: Return the story, the generated images, and the title + - return: + title: outputs[3] + story: outputs[1].story + comic_panels: "[output.image.url for output in outputs[2]]" +""" + +task = client.tasks.create( agent_id=agent.id, - name="Story and Comic Creator", - description="Create a story based on an idea and generate a 4-panel comic strip illustrating the story.", - main=[ - # Step 1: Generate a story and outline into 4 panels - { - "prompt": [ - { - "role": "system", - "content": "You are {{agent.name}}. {{agent.about}}" - }, - { - "role": "user", - "content": ( - "Based on the idea '{{_.idea}}', write a short story suitable for a 4-panel comic strip. " - "Provide the story and a numbered list of 4 brief descriptions for each panel illustrating key moments in the story." - ), - }, - ], - "unwrap": True, - }, - # Step 2: Extract the panel descriptions and story - { - "evaluate": { - "story": "_.split('1. ')[0].strip()", - "panels": "re.findall(r'\\d+\\.\\s*(.*?)(?=\\d+\\.\\s*|$)', _)", - } - }, - # Step 3: Generate images for each panel using the image generator tool - { - "foreach": { - "in": "_.panels", - "do": { - "tool": "image_generator", - "arguments": { - "description": "_", - }, - }, - }, - }, - # Step 4: Generate a catchy title for the story - { - "prompt": [ - { - "role": "system", - "content": "You are {{agent.name}}. {{agent.about}}" - }, - { - "role": "user", - "content": "Based on the story below, generate a catchy title.\n\nStory: {{outputs[1].story}}", - }, - ], - "unwrap": True, - }, - # Step 5: Return the story, the generated images, and the title - { - "return": { - "title": "outputs[3]", - "story": "outputs[1].story", - "comic_panels": "[output.image.url for output in outputs[2]]", - } - }, - ], + **yaml.safe_load(task_yaml) ) ``` -> [!TIP] -> node.js version of this is similar. - -### Step 5: Execute the Task +### Step 3: Execute the Task ```python # 🚀 Execute the task with an input idea -execution = await client.executions.create( +execution = client.executions.create( task_id=task.id, input={"idea": "A cat who learns to fly"} ) # 🎉 Watch as the story and comic panels are generated -await client.executions.stream(execution_id=execution.id) +for transition in client.executions.transitions.stream(execution_id=execution.id): + print(transition) + +# 📦 Once the execution is finished, retrieve the results +result = client.executions.get(execution_id=execution.id) ``` -This example demonstrates how to create an agent with a custom tool, define a complex task with multiple steps, and execute it to generate a creative output. +### Step 4: Chat with the Agent + +Start an interactive chat session with the agent: + +```python +session = client.sessions.create(agent_id=agent.id) + +# 💬 Send messages to the agent +while (message := input("Enter a message: ")) != "quit": + response = client.sessions.chat( + session_id=session.id, + message=message, + ) - + print(response) +``` > [!TIP] -> You can find another node.js example [here](example.ts) or python example [here](example.py). +> You can find the full python example [here](example.py). -## Concepts -Julep is built on several key technical components that work together to create powerful AI workflows: +## Node.js Quick Start 🟩 -### Agents -AI-powered entities backed by large language models (LLMs) that execute tasks and interact with users. Agents are the core functional units of Julep. +### Step 1: Create an Agent -```mermaid -graph TD - Agent[Agent] --> LLM[Large Language Model] - Agent --> Tasks[Tasks] - Agent --> Users[Users] - Tasks --> Tools[Tools] +```javascript +import { Julep } from '@julep/sdk'; +import yaml from 'js-yaml'; + +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.", + }); + + // 🛠️ Add an image generation tool (DALL·E) to the agent + await client.agents.tools.create(agent.id, { + name: "image_generator", + description: "Use this tool to generate images based on descriptions.", + integration: { + provider: "dalle", + method: "generate_image", + setup: { + api_key: "your_openai_api_key", + }, + }, + }); + + return agent; +} ``` -### Users -Entities that interact with agents. Users can be associated with sessions and have their own metadata, allowing for personalized interactions. +### Step 2: Create a Task that generates a story and comic strip -```mermaid -graph LR - User[User] --> Sessions[Sessions] - Sessions --> Agents[Agents] - Sessions --> Metadata[Metadata] +```javascript +const taskYaml = ` +name: Story and Comic Creator +description: Create a story based on an idea and generate a 4-panel comic strip illustrating the story. + +main: + # Step 1: Generate a story and outline into 4 panels + - prompt: + - role: system + content: You are {{agent.name}}. {{agent.about}} + - role: user + content: > + Based on the idea '{{_.idea}}', write a short story suitable for a 4-panel comic strip. + Provide the story and a numbered list of 4 brief descriptions for each panel illustrating key moments in the story. + unwrap: true + + # Step 2: Extract the panel descriptions and story + - evaluate: + story: _.split('1. ')[0].trim() + panels: _.match(/\\d+\\.\\s*(.*?)(?=\\d+\\.\\s*|$)/g) + + # Step 3: Generate images for each panel using the image generator tool + - foreach: + in: _.panels + do: + tool: image_generator + arguments: + description: _ + + # Step 4: Generate a catchy title for the story + - prompt: + - role: system + content: You are {{agent.name}}. {{agent.about}} + - role: user + content: > + Based on the story below, generate a catchy title. + + Story: {{outputs[1].story}} + unwrap: true + + # Step 5: Return the story, the generated images, and the title + - return: + title: outputs[3] + story: outputs[1].story + comic_panels: outputs[2].map(output => output.image.url) +`; + +async function createTask(agent) { + const task = await client.tasks.create(agent.id, yaml.load(taskYaml)); + return task; +} ``` -### Sessions -Stateful interactions between agents and users. Sessions maintain context across multiple exchanges and can be configured for different behaviors, including context management and overflow handling. +### Step 3: Execute the Task -```mermaid -graph LR - Sessions[Sessions] --> Agents[Agents] - Sessions --> Users[Users] - Sessions --> ContextManagement[Context Management] - Sessions --> OverflowHandling[Overflow Handling] +```javascript +async function executeTask(task) { + const execution = await client.executions.create(task.id, { + 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)) { + console.log(transition); + } + + // 📦 Once the execution is finished, retrieve the results + const result = await client.executions.get(execution.id); + return result; +} ``` -### Tasks -Multi-step, programmatic workflows that agents can execute. Tasks define complex operations and can include various types of steps, such as prompts, tool calls, and conditional logic. +### Step 4: Chat with the Agent -```mermaid -graph TD - Tasks[Tasks] --> Steps[Workflow Steps] - Steps --> Prompt[Prompt] - Steps --> ToolCalls[Tool Calls] - Steps --> ConditionalLogic[Conditional Logic] +```javascript +async function chatWithAgent(agent) { + const session = await client.sessions.create({ agent_id: agent.id }); + + // 💬 Send messages to the agent + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + + const chat = async () => { + rl.question("Enter a message (or 'quit' to exit): ", async (message) => { + if (message.toLowerCase() === 'quit') { + rl.close(); + return; + } + + const response = await client.sessions.chat(session.id, { message }); + console.log(response); + chat(); + }); + }; + + chat(); +} + +// Run the example +async function runExample() { + const agent = await createAgent(); + const task = await createTask(agent); + const result = await executeTask(task); + console.log("Task Result:", result); + await chatWithAgent(agent); +} + +runExample().catch(console.error); ``` -### Tools -Integrations that extend an agent's capabilities. Tools can be user-defined functions, system tools, or third-party API integrations. They allow agents to perform actions beyond text generation. +> [!TIP] +> You can find the full Node.js example [here](example.js). + +## Components -```mermaid -graph LR - Tools[Tools] --> UserDefinedFunctions[User-Defined Functions] - Tools --> SystemTools[System Tools] - Tools --> ThirdPartyAPIs[Third-Party APIs] -``` +Julep is made up of the following components: -### Documents -Text or data objects that can be associated with agents or users. Documents are vectorized and stored in a vector database, enabling semantic search and retrieval during agent interactions. +- **Julep Platform**: The Julep platform is a cloud service that runs your workflows. It includes a language for describing workflows, a server for running those workflows, and an SDK for interacting with the platform. +- **Julep SDKs**: Julep SDKs are a set of libraries for building workflows. There are SDKs for Python and JavaScript, with more on the way. +- **Julep API**: The Julep API is a RESTful API that you can use to interact with the Julep platform. -```mermaid -graph LR - Documents[Documents] --> VectorDatabase[Vector Database] - Documents --> SemanticSearch[Semantic Search] - Documents --> AgentsOrUsers[Agents or Users] -``` +### Mental Model + +Think of Julep as a platform that combines both client-side and server-side components to help you build advanced AI agents. Here's how to visualize it: + +1. **Your Application Code:** + - You use the Julep SDK in your application to define agents, tasks, and workflows. + - The SDK provides functions and classes that make it easy to set up and manage these components. + +2. **Julep Backend Service:** + - The SDK communicates with the Julep backend over the network. + - The backend handles execution of tasks, maintains session state, stores documents, and orchestrates workflows. + +3. **Integration with Tools and APIs:** + - Within your workflows, you can integrate external tools and services. + - The backend facilitates these integrations, so your agents can, for example, perform web searches, access databases, or call third-party APIs. + +In simpler terms: +- Julep is a platform for building stateful AI agents. +- You use the SDK (like a toolkit) in your code to define what your agents do. +- The backend service (which you can think of as the engine) runs these definitions, manages state, and handles complexity. -### Executions -Instances of tasks that have been initiated with specific inputs. Executions have their own lifecycle and state machine, allowing for monitoring, management, and resumption of long-running processes. +## Concepts + +Julep is built on several key technical components that work together to create powerful AI workflows: ```mermaid -graph LR - Executions[Executions] --> Tasks[Tasks] - Executions --> Lifecycle[Lifecycle] - Executions --> Monitoring[Monitoring] - Executions --> Management[Management] - Executions --> Resumption[Resumption] +graph TD + User[User] --> Session[Session] + Session --> Agent[Agent] + Agent --> Tasks[Tasks] + Agent --> LLM[Large Language Model] + Tasks --> Tools[Tools] + Tasks --> Documents[Documents] + Documents --> VectorDB[Vector Database] + Agent --> Executions[Executions] + + classDef core fill:#f9f,stroke:#333,stroke-width:2px; + class Agent,Tasks,Session core; ``` -For a more detailed explanation of these concepts and their interactions, please refer to our [Concepts Documentation](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md). +- **Agents**: AI-powered entities backed by large language models (LLMs) that execute tasks and interact with users. +- **Users**: Entities that interact with agents through sessions. +- **Sessions**: Stateful interactions between agents and users, maintaining context across multiple exchanges. +- **Tasks**: Multi-step, programmatic workflows that agents can execute, including various types of steps like prompts, tool calls, and conditional logic. +- **Tools**: Integrations that extend an agent's capabilities, including user-defined functions, system tools, or third-party API integrations. +- **Documents**: Text or data objects associated with agents or users, vectorized and stored for semantic search and retrieval. +- **Executions**: Instances of tasks that have been initiated with specific inputs, with their own lifecycle and state machine. + +For a more detailed explanation of these concepts and their interactions, please refer to our [Concepts Documentation](/docs/julep-concepts.md). ## Understanding Tasks @@ -628,14 +725,15 @@ Easily manage and search through documents for your agents: ```python # Upload a document document = client.documents.create( - file="path/to/document.pdf", + title="AI advancements", + content="AI is changing the world...", metadata={"category": "research_paper"} ) # Search documents results = client.documents.search( query="AI advancements", - filter={"category": "research_paper"} + metadata_filter={"category": "research_paper"} ) ``` @@ -652,34 +750,4 @@ Explore our comprehensive API documentation to learn more about agents, tasks, a - [Agents API](https://api.julep.ai/api/docs#tag/agents) - [Tasks API](https://api.julep.ai/api/docs#tag/tasks) -- [Executions API](https://api.julep.ai/api/docs#tag/executions) - -## Examples and Tutorials - -Discover example projects and tutorials to help you get started and build upon provided examples: - -- [Example Projects](https://github.com/julep-ai/julep/tree/main/examples) -- [Tutorials](https://docs.julep.ai/tutorials) - -## Contributing - -We welcome contributions to the project! Learn how to contribute and our code of conduct: - -- [Contributing Guidelines](https://github.com/julep-ai/julep/blob/main/CONTRIBUTING.md) -- [Code of Conduct](https://github.com/julep-ai/julep/blob/main/CODE_OF_CONDUCT.md) - -## Support and Community - -Join our community to get help, ask questions, and share your ideas: - -- [Discord](https://discord.com/invite/JTSBGRZrzj) -- [GitHub Discussions](https://github.com/julep-ai/julep/discussions) -- [Twitter](https://twitter.com/julep_ai) - -## License - -This project is licensed under the [Apache License 2.0](https://github.com/julep-ai/julep/blob/main/LICENSE). - -## Acknowledgements - -We would like to express our gratitude to all contributors and the open-source community for their valuable resources and contributions. +- [Executions API](https://api.julep.ai/api/docs#tag/executions) \ No newline at end of file diff --git a/agents-api/poetry.lock b/agents-api/poetry.lock index e4cc58c7b..608a8e665 100644 --- a/agents-api/poetry.lock +++ b/agents-api/poetry.lock @@ -2,113 +2,113 @@ [[package]] name = "aiohappyeyeballs" -version = "2.4.2" +version = "2.4.3" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.2-py3-none-any.whl", hash = "sha256:8522691d9a154ba1145b157d6d5c15e5c692527ce6a53c5e5f9876977f6dab2f"}, - {file = "aiohappyeyeballs-2.4.2.tar.gz", hash = "sha256:4ca893e6c5c1f5bf3888b04cb5a3bee24995398efef6e0b9f747b5e89d84fd74"}, + {file = "aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572"}, + {file = "aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586"}, ] [[package]] name = "aiohttp" -version = "3.10.6" +version = "3.10.9" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.10.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:682836fc672972cc3101cc9e30d49c5f7e8f1d010478d46119fe725a4545acfd"}, - {file = "aiohttp-3.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:289fa8a20018d0d5aa9e4b35d899bd51bcb80f0d5f365d9a23e30dac3b79159b"}, - {file = "aiohttp-3.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8617c96a20dd57e7e9d398ff9d04f3d11c4d28b1767273a5b1a018ada5a654d3"}, - {file = "aiohttp-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdbeff1b062751c2a2a55b171f7050fb7073633c699299d042e962aacdbe1a07"}, - {file = "aiohttp-3.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ea35d849cdd4a9268f910bff4497baebbc1aa3f2f625fd8ccd9ac99c860c621"}, - {file = "aiohttp-3.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:473961b3252f3b949bb84873d6e268fb6d8aa0ccc6eb7404fa58c76a326bb8e1"}, - {file = "aiohttp-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d2665c5df629eb2f981dab244c01bfa6cdc185f4ffa026639286c4d56fafb54"}, - {file = "aiohttp-3.10.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25d92f794f1332f656e3765841fc2b7ad5c26c3f3d01e8949eeb3495691cf9f4"}, - {file = "aiohttp-3.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9bd6b2033993d5ae80883bb29b83fb2b432270bbe067c2f53cc73bb57c46065f"}, - {file = "aiohttp-3.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d7f408c43f5e75ea1edc152fb375e8f46ef916f545fb66d4aebcbcfad05e2796"}, - {file = "aiohttp-3.10.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:cf8b8560aa965f87bf9c13bf9fed7025993a155ca0ce8422da74bf46d18c2f5f"}, - {file = "aiohttp-3.10.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14477c4e52e2f17437b99893fd220ffe7d7ee41df5ebf931a92b8ca82e6fd094"}, - {file = "aiohttp-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fb138fbf9f53928e779650f5ed26d0ea1ed8b2cab67f0ea5d63afa09fdc07593"}, - {file = "aiohttp-3.10.6-cp310-cp310-win32.whl", hash = "sha256:9843d683b8756971797be171ead21511d2215a2d6e3c899c6e3107fbbe826791"}, - {file = "aiohttp-3.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:f8b8e49fe02f744d38352daca1dbef462c3874900bd8166516f6ea8e82b5aacf"}, - {file = "aiohttp-3.10.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f52e54fd776ad0da1006708762213b079b154644db54bcfc62f06eaa5b896402"}, - {file = "aiohttp-3.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:995ab1a238fd0d19dc65f2d222e5eb064e409665c6426a3e51d5101c1979ee84"}, - {file = "aiohttp-3.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0749c4d5a08a802dd66ecdf59b2df4d76b900004017468a7bb736c3b5a3dd902"}, - {file = "aiohttp-3.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e05b39158f2af0e2438cc2075cfc271f4ace0c3cc4a81ec95b27a0432e161951"}, - {file = "aiohttp-3.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a9f196c970db2dcde4f24317e06615363349dc357cf4d7a3b0716c20ac6d7bcd"}, - {file = "aiohttp-3.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:47647c8af04a70e07a2462931b0eba63146a13affa697afb4ecbab9d03a480ce"}, - {file = "aiohttp-3.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669c0efe7e99f6d94d63274c06344bd0e9c8daf184ce5602a29bc39e00a18720"}, - {file = "aiohttp-3.10.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9721cdd83a994225352ca84cd537760d41a9da3c0eacb3ff534747ab8fba6d0"}, - {file = "aiohttp-3.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b82c8ebed66ce182893e7c0b6b60ba2ace45b1df104feb52380edae266a4850"}, - {file = "aiohttp-3.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b169f8e755e541b72e714b89a831b315bbe70db44e33fead28516c9e13d5f931"}, - {file = "aiohttp-3.10.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0be3115753baf8b4153e64f9aa7bf6c0c64af57979aa900c31f496301b374570"}, - {file = "aiohttp-3.10.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e1f80cd17d81a404b6e70ef22bfe1870bafc511728397634ad5f5efc8698df56"}, - {file = "aiohttp-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6419728b08fb6380c66a470d2319cafcec554c81780e2114b7e150329b9a9a7f"}, - {file = "aiohttp-3.10.6-cp311-cp311-win32.whl", hash = "sha256:bd294dcdc1afdc510bb51d35444003f14e327572877d016d576ac3b9a5888a27"}, - {file = "aiohttp-3.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:bf861da9a43d282d6dd9dcd64c23a0fccf2c5aa5cd7c32024513c8c79fb69de3"}, - {file = "aiohttp-3.10.6-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:2708baccdc62f4b1251e59c2aac725936a900081f079b88843dabcab0feeeb27"}, - {file = "aiohttp-3.10.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7475da7a5e2ccf1a1c86c8fee241e277f4874c96564d06f726d8df8e77683ef7"}, - {file = "aiohttp-3.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:02108326574ff60267b7b35b17ac5c0bbd0008ccb942ce4c48b657bb90f0b8aa"}, - {file = "aiohttp-3.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:029a019627b37fa9eac5c75cc54a6bb722c4ebbf5a54d8c8c0fb4dd8facf2702"}, - {file = "aiohttp-3.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a637d387db6fdad95e293fab5433b775fd104ae6348d2388beaaa60d08b38c4"}, - {file = "aiohttp-3.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1a16f3fc1944c61290d33c88dc3f09ba62d159b284c38c5331868425aca426"}, - {file = "aiohttp-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b292f37969f9cc54f4643f0be7dacabf3612b3b4a65413661cf6c350226787"}, - {file = "aiohttp-3.10.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0754690a3a26e819173a34093798c155bafb21c3c640bff13be1afa1e9d421f9"}, - {file = "aiohttp-3.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:164ecd32e65467d86843dbb121a6666c3deb23b460e3f8aefdcaacae79eb718a"}, - {file = "aiohttp-3.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:438c5863feb761f7ca3270d48c292c334814459f61cc12bab5ba5b702d7c9e56"}, - {file = "aiohttp-3.10.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ba18573bb1de1063d222f41de64a0d3741223982dcea863b3f74646faf618ec7"}, - {file = "aiohttp-3.10.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:c82a94ddec996413a905f622f3da02c4359952aab8d817c01cf9915419525e95"}, - {file = "aiohttp-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92351aa5363fc3c1f872ca763f86730ced32b01607f0c9662b1fa711087968d0"}, - {file = "aiohttp-3.10.6-cp312-cp312-win32.whl", hash = "sha256:3e15e33bfc73fa97c228f72e05e8795e163a693fd5323549f49367c76a6e5883"}, - {file = "aiohttp-3.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:fe517113fe4d35d9072b826c3e147d63c5f808ca8167d450b4f96c520c8a1d8d"}, - {file = "aiohttp-3.10.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:482f74057ea13d387a7549d7a7ecb60e45146d15f3e58a2d93a0ad2d5a8457cd"}, - {file = "aiohttp-3.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:03fa40d1450ee5196e843315ddf74a51afc7e83d489dbfc380eecefea74158b1"}, - {file = "aiohttp-3.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e52e59ed5f4cc3a3acfe2a610f8891f216f486de54d95d6600a2c9ba1581f4d"}, - {file = "aiohttp-3.10.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b3935a22c9e41a8000d90588bed96cf395ef572dbb409be44c6219c61d900d"}, - {file = "aiohttp-3.10.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bef1480ee50f75abcfcb4b11c12de1005968ca9d0172aec4a5057ba9f2b644f"}, - {file = "aiohttp-3.10.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:671745ea7db19693ce867359d503772177f0b20fa8f6ee1e74e00449f4c4151d"}, - {file = "aiohttp-3.10.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b50b367308ca8c12e0b50cba5773bc9abe64c428d3fd2bbf5cd25aab37c77bf"}, - {file = "aiohttp-3.10.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a504d7cdb431a777d05a124fd0b21efb94498efa743103ea01b1e3136d2e4fb"}, - {file = "aiohttp-3.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66bc81361131763660b969132a22edce2c4d184978ba39614e8f8f95db5c95f8"}, - {file = "aiohttp-3.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:27cf19a38506e2e9f12fc17e55f118f04897b0a78537055d93a9de4bf3022e3d"}, - {file = "aiohttp-3.10.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3468b39f977a11271517c6925b226720e148311039a380cc9117b1e2258a721f"}, - {file = "aiohttp-3.10.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9d26da22a793dfd424be1050712a70c0afd96345245c29aced1e35dbace03413"}, - {file = "aiohttp-3.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:844d48ff9173d0b941abed8b2ea6a412f82b56d9ab1edb918c74000c15839362"}, - {file = "aiohttp-3.10.6-cp313-cp313-win32.whl", hash = "sha256:2dd56e3c43660ed3bea67fd4c5025f1ac1f9ecf6f0b991a6e5efe2e678c490c5"}, - {file = "aiohttp-3.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:c91781d969fbced1993537f45efe1213bd6fccb4b37bfae2a026e20d6fbed206"}, - {file = "aiohttp-3.10.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4407a80bca3e694f2d2a523058e20e1f9f98a416619e04f6dc09dc910352ac8b"}, - {file = "aiohttp-3.10.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1cb045ec5961f51af3e2c08cd6fe523f07cc6e345033adee711c49b7b91bb954"}, - {file = "aiohttp-3.10.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4fabdcdc781a36b8fd7b2ca9dea8172f29a99e11d00ca0f83ffeb50958da84a1"}, - {file = "aiohttp-3.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a9f42efcc2681790595ab3d03c0e52d01edc23a0973ea09f0dc8d295e12b8e"}, - {file = "aiohttp-3.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cca776a440795db437d82c07455761c85bbcf3956221c3c23b8c93176c278ce7"}, - {file = "aiohttp-3.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5582de171f0898139cf51dd9fcdc79b848e28d9abd68e837f0803fc9f30807b1"}, - {file = "aiohttp-3.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:370e2d47575c53c817ee42a18acc34aad8da4dbdaac0a6c836d58878955f1477"}, - {file = "aiohttp-3.10.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:444d1704e2af6b30766debed9be8a795958029e552fe77551355badb1944012c"}, - {file = "aiohttp-3.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40271a2a375812967401c9ca8077de9368e09a43a964f4dce0ff603301ec9358"}, - {file = "aiohttp-3.10.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f3af26f86863fad12e25395805bb0babbd49d512806af91ec9708a272b696248"}, - {file = "aiohttp-3.10.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4752df44df48fd42b80f51d6a97553b482cda1274d9dc5df214a3a1aa5d8f018"}, - {file = "aiohttp-3.10.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2cd5290ab66cfca2f90045db2cc6434c1f4f9fbf97c9f1c316e785033782e7d2"}, - {file = "aiohttp-3.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3427031064b0d5c95647e6369c4aa3c556402f324a3e18107cb09517abe5f962"}, - {file = "aiohttp-3.10.6-cp38-cp38-win32.whl", hash = "sha256:614fc21e86adc28e4165a6391f851a6da6e9cbd7bb232d0df7718b453a89ee98"}, - {file = "aiohttp-3.10.6-cp38-cp38-win_amd64.whl", hash = "sha256:58c5d7318a136a3874c78717dd6de57519bc64f6363c5827c2b1cb775bea71dd"}, - {file = "aiohttp-3.10.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5db26bbca8e7968c4c977a0c640e0b9ce7224e1f4dcafa57870dc6ee28e27de6"}, - {file = "aiohttp-3.10.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3fb4216e3ec0dbc01db5ba802f02ed78ad8f07121be54eb9e918448cc3f61b7c"}, - {file = "aiohttp-3.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a976ef488f26e224079deb3d424f29144c6d5ba4ded313198169a8af8f47fb82"}, - {file = "aiohttp-3.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a86610174de8a85a920e956e2d4f9945e7da89f29a00e95ac62a4a414c4ef4e"}, - {file = "aiohttp-3.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:217791c6a399cc4f2e6577bb44344cba1f5714a2aebf6a0bea04cfa956658284"}, - {file = "aiohttp-3.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ba3662d41abe2eab0eeec7ee56f33ef4e0b34858f38abf24377687f9e1fb00a5"}, - {file = "aiohttp-3.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4dfa5ad4bce9ca30a76117fbaa1c1decf41ebb6c18a4e098df44298941566f9"}, - {file = "aiohttp-3.10.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0009258e97502936d3bd5bf2ced15769629097d0abb81e6495fba1047824fe0"}, - {file = "aiohttp-3.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0a75d5c9fb4f06c41d029ae70ad943c3a844c40c0a769d12be4b99b04f473d3d"}, - {file = "aiohttp-3.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8198b7c002aae2b40b2d16bfe724b9a90bcbc9b78b2566fc96131ef4e382574d"}, - {file = "aiohttp-3.10.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4611db8c907f90fe86be112efdc2398cd7b4c8eeded5a4f0314b70fdea8feab0"}, - {file = "aiohttp-3.10.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ff99ae06eef85c7a565854826114ced72765832ee16c7e3e766c5e4c5b98d20e"}, - {file = "aiohttp-3.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7641920bdcc7cd2d3ddfb8bb9133a6c9536b09dbd49490b79e125180b2d25b93"}, - {file = "aiohttp-3.10.6-cp39-cp39-win32.whl", hash = "sha256:e2e7d5591ea868d5ec82b90bbeb366a198715672841d46281b623e23079593db"}, - {file = "aiohttp-3.10.6-cp39-cp39-win_amd64.whl", hash = "sha256:b504c08c45623bf5c7ca41be380156d925f00199b3970efd758aef4a77645feb"}, - {file = "aiohttp-3.10.6.tar.gz", hash = "sha256:d2578ef941be0c2ba58f6f421a703527d08427237ed45ecb091fed6f83305336"}, + {file = "aiohttp-3.10.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8b3fb28a9ac8f2558760d8e637dbf27aef1e8b7f1d221e8669a1074d1a266bb2"}, + {file = "aiohttp-3.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91aa966858593f64c8a65cdefa3d6dc8fe3c2768b159da84c1ddbbb2c01ab4ef"}, + {file = "aiohttp-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:63649309da83277f06a15bbdc2a54fbe75efb92caa2c25bb57ca37762789c746"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3e7fabedb3fe06933f47f1538df7b3a8d78e13d7167195f51ca47ee12690373"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c070430fda1a550a1c3a4c2d7281d3b8cfc0c6715f616e40e3332201a253067"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:51d0a4901b27272ae54e42067bc4b9a90e619a690b4dc43ea5950eb3070afc32"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fec5fac7aea6c060f317f07494961236434928e6f4374e170ef50b3001e14581"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:172ad884bb61ad31ed7beed8be776eb17e7fb423f1c1be836d5cb357a096bf12"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d646fdd74c25bbdd4a055414f0fe32896c400f38ffbdfc78c68e62812a9e0257"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e86260b76786c28acf0b5fe31c8dca4c2add95098c709b11e8c35b424ebd4f5b"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d7cafc11d70fdd8801abfc2ff276744ae4cb39d8060b6b542c7e44e5f2cfc2"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:fc262c3df78c8ff6020c782d9ce02e4bcffe4900ad71c0ecdad59943cba54442"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:482c85cf3d429844396d939b22bc2a03849cb9ad33344689ad1c85697bcba33a"}, + {file = "aiohttp-3.10.9-cp310-cp310-win32.whl", hash = "sha256:aeebd3061f6f1747c011e1d0b0b5f04f9f54ad1a2ca183e687e7277bef2e0da2"}, + {file = "aiohttp-3.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:fa430b871220dc62572cef9c69b41e0d70fcb9d486a4a207a5de4c1f25d82593"}, + {file = "aiohttp-3.10.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:16e6a51d8bc96b77f04a6764b4ad03eeef43baa32014fce71e882bd71302c7e4"}, + {file = "aiohttp-3.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8bd9125dd0cc8ebd84bff2be64b10fdba7dc6fd7be431b5eaf67723557de3a31"}, + {file = "aiohttp-3.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dcf354661f54e6a49193d0b5653a1b011ba856e0b7a76bda2c33e4c6892f34ea"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42775de0ca04f90c10c5c46291535ec08e9bcc4756f1b48f02a0657febe89b10"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d1e4185c5d7187684d41ebb50c9aeaaaa06ca1875f4c57593071b0409d2444"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2695c61cf53a5d4345a43d689f37fc0f6d3a2dc520660aec27ec0f06288d1f9"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a3f063b41cc06e8d0b3fcbbfc9c05b7420f41287e0cd4f75ce0a1f3d80729e6"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d37f4718002863b82c6f391c8efd4d3a817da37030a29e2682a94d2716209de"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2746d8994ebca1bdc55a1e998feff4e94222da709623bb18f6e5cfec8ec01baf"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6f3c6648aa123bcd73d6f26607d59967b607b0da8ffcc27d418a4b59f4c98c7c"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:558b3d223fd631ad134d89adea876e7fdb4c93c849ef195049c063ada82b7d08"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4e6cb75f8ddd9c2132d00bc03c9716add57f4beff1263463724f6398b813e7eb"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:608cecd8d58d285bfd52dbca5b6251ca8d6ea567022c8a0eaae03c2589cd9af9"}, + {file = "aiohttp-3.10.9-cp311-cp311-win32.whl", hash = "sha256:36d4fba838be5f083f5490ddd281813b44d69685db910907636bc5dca6322316"}, + {file = "aiohttp-3.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:8be1a65487bdfc285bd5e9baf3208c2132ca92a9b4020e9f27df1b16fab998a9"}, + {file = "aiohttp-3.10.9-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4fd16b30567c5b8e167923be6e027eeae0f20cf2b8a26b98a25115f28ad48ee0"}, + {file = "aiohttp-3.10.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:40ff5b7660f903dc587ed36ef08a88d46840182d9d4b5694e7607877ced698a1"}, + {file = "aiohttp-3.10.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4edc3fd701e2b9a0d605a7b23d3de4ad23137d23fc0dbab726aa71d92f11aaaf"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e525b69ee8a92c146ae5b4da9ecd15e518df4d40003b01b454ad694a27f498b5"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5002a02c17fcfd796d20bac719981d2fca9c006aac0797eb8f430a58e9d12431"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4ceeae2fb8cabdd1b71c82bfdd39662473d3433ec95b962200e9e752fb70d0"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6e395c3d1f773cf0651cd3559e25182eb0c03a2777b53b4575d8adc1149c6e9"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbdb8def5268f3f9cd753a265756f49228a20ed14a480d151df727808b4531dd"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f82ace0ec57c94aaf5b0e118d4366cff5889097412c75aa14b4fd5fc0c44ee3e"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6ebdc3b3714afe1b134b3bbeb5f745eed3ecbcff92ab25d80e4ef299e83a5465"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f9ca09414003c0e96a735daa1f071f7d7ed06962ef4fa29ceb6c80d06696d900"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1298b854fd31d0567cbb916091be9d3278168064fca88e70b8468875ef9ff7e7"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:60ad5b8a7452c0f5645c73d4dad7490afd6119d453d302cd5b72b678a85d6044"}, + {file = "aiohttp-3.10.9-cp312-cp312-win32.whl", hash = "sha256:1a0ee6c0d590c917f1b9629371fce5f3d3f22c317aa96fbdcce3260754d7ea21"}, + {file = "aiohttp-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:c46131c6112b534b178d4e002abe450a0a29840b61413ac25243f1291613806a"}, + {file = "aiohttp-3.10.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2bd9f3eac515c16c4360a6a00c38119333901b8590fe93c3257a9b536026594d"}, + {file = "aiohttp-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8cc0d13b4e3b1362d424ce3f4e8c79e1f7247a00d792823ffd640878abf28e56"}, + {file = "aiohttp-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ba1a599255ad6a41022e261e31bc2f6f9355a419575b391f9655c4d9e5df5ff5"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:776e9f3c9b377fcf097c4a04b241b15691e6662d850168642ff976780609303c"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8debb45545ad95b58cc16c3c1cc19ad82cffcb106db12b437885dbee265f0ab5"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2555e4949c8d8782f18ef20e9d39730d2656e218a6f1a21a4c4c0b56546a02e"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c54dc329cd44f7f7883a9f4baaefe686e8b9662e2c6c184ea15cceee587d8d69"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e709d6ac598c5416f879bb1bae3fd751366120ac3fa235a01de763537385d036"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:17c272cfe7b07a5bb0c6ad3f234e0c336fb53f3bf17840f66bd77b5815ab3d16"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c21c82df33b264216abffff9f8370f303dab65d8eee3767efbbd2734363f677"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9331dd34145ff105177855017920dde140b447049cd62bb589de320fd6ddd582"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ac3196952c673822ebed8871cf8802e17254fff2a2ed4835d9c045d9b88c5ec7"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2c33fa6e10bb7ed262e3ff03cc69d52869514f16558db0626a7c5c61dde3c29f"}, + {file = "aiohttp-3.10.9-cp313-cp313-win32.whl", hash = "sha256:a14e4b672c257a6b94fe934ee62666bacbc8e45b7876f9dd9502d0f0fe69db16"}, + {file = "aiohttp-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:a35ed3d03910785f7d9d6f5381f0c24002b2b888b298e6f941b2fc94c5055fcd"}, + {file = "aiohttp-3.10.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f392ef50e22c31fa49b5a46af7f983fa3f118f3eccb8522063bee8bfa6755f8"}, + {file = "aiohttp-3.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d1f5c9169e26db6a61276008582d945405b8316aae2bb198220466e68114a0f5"}, + {file = "aiohttp-3.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8d9d10d10ec27c0d46ddaecc3c5598c4db9ce4e6398ca872cdde0525765caa2f"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d97273a52d7f89a75b11ec386f786d3da7723d7efae3034b4dda79f6f093edc1"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d271f770b52e32236d945911b2082f9318e90ff835d45224fa9e28374303f729"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7003f33f5f7da1eb02f0446b0f8d2ccf57d253ca6c2e7a5732d25889da82b517"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6e00c8a92e7663ed2be6fcc08a2997ff06ce73c8080cd0df10cc0321a3168d7"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a61df62966ce6507aafab24e124e0c3a1cfbe23c59732987fc0fd0d71daa0b88"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:60555211a006d26e1a389222e3fab8cd379f28e0fbf7472ee55b16c6c529e3a6"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d15a29424e96fad56dc2f3abed10a89c50c099f97d2416520c7a543e8fddf066"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:a19caae0d670771ea7854ca30df76f676eb47e0fd9b2ee4392d44708f272122d"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:99f9678bf0e2b1b695e8028fedac24ab6770937932eda695815d5a6618c37e04"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2914caa46054f3b5ff910468d686742ff8cff54b8a67319d75f5d5945fd0a13d"}, + {file = "aiohttp-3.10.9-cp38-cp38-win32.whl", hash = "sha256:0bc059ecbce835630e635879f5f480a742e130d9821fbe3d2f76610a6698ee25"}, + {file = "aiohttp-3.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:e883b61b75ca6efc2541fcd52a5c8ccfe288b24d97e20ac08fdf343b8ac672ea"}, + {file = "aiohttp-3.10.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fcd546782d03181b0b1d20b43d612429a90a68779659ba8045114b867971ab71"}, + {file = "aiohttp-3.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:85711eec2d875cd88c7eb40e734c4ca6d9ae477d6f26bd2b5bb4f7f60e41b156"}, + {file = "aiohttp-3.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:02d1d6610588bcd743fae827bd6f2e47e0d09b346f230824b4c6fb85c6065f9c"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3668d0c2a4d23fb136a753eba42caa2c0abbd3d9c5c87ee150a716a16c6deec1"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7c071235a47d407b0e93aa6262b49422dbe48d7d8566e1158fecc91043dd948"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac74e794e3aee92ae8f571bfeaa103a141e409863a100ab63a253b1c53b707eb"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bbf94d4a0447705b7775417ca8bb8086cc5482023a6e17cdc8f96d0b1b5aba6"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb0b2d5d51f96b6cc19e6ab46a7b684be23240426ae951dcdac9639ab111b45e"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e83dfefb4f7d285c2d6a07a22268344a97d61579b3e0dce482a5be0251d672ab"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f0a44bb40b6aaa4fb9a5c1ee07880570ecda2065433a96ccff409c9c20c1624a"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c2b627d3c8982691b06d89d31093cee158c30629fdfebe705a91814d49b554f8"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:03690541e4cc866eef79626cfa1ef4dd729c5c1408600c8cb9e12e1137eed6ab"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad3675c126f2a95bde637d162f8231cff6bc0bc9fbe31bd78075f9ff7921e322"}, + {file = "aiohttp-3.10.9-cp39-cp39-win32.whl", hash = "sha256:1321658f12b6caffafdc35cfba6c882cb014af86bef4e78c125e7e794dfb927b"}, + {file = "aiohttp-3.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:9fdf5c839bf95fc67be5794c780419edb0dbef776edcfc6c2e5e2ffd5ee755fa"}, + {file = "aiohttp-3.10.9.tar.gz", hash = "sha256:143b0026a9dab07a05ad2dd9e46aa859bffdd6348ddc5967b42161168c24f857"}, ] [package.dependencies] @@ -1189,13 +1189,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.5" +version = "1.0.6" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, + {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, + {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, ] [package.dependencies] @@ -1206,7 +1206,7 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] +trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" @@ -1379,13 +1379,13 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio [[package]] name = "ipython" -version = "8.27.0" +version = "8.28.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" files = [ - {file = "ipython-8.27.0-py3-none-any.whl", hash = "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c"}, - {file = "ipython-8.27.0.tar.gz", hash = "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e"}, + {file = "ipython-8.28.0-py3-none-any.whl", hash = "sha256:530ef1e7bb693724d3cdc37287c80b07ad9b25986c007a53aa1857272dac3f35"}, + {file = "ipython-8.28.0.tar.gz", hash = "sha256:0d0d15ca1e01faeb868ef56bc7ee5a0de5bd66885735682e8a322ae289a13d1a"}, ] [package.dependencies] @@ -1646,6 +1646,25 @@ files = [ [package.dependencies] referencing = ">=0.31.0" +[[package]] +name = "julep" +version = "1.14.0" +description = "The official Python library for the julep API" +optional = false +python-versions = ">=3.7" +files = [ + {file = "julep-1.14.0-py3-none-any.whl", hash = "sha256:a2770e63e94bc3ee21e4408d5b9e1595b0cb70cf20abecf3088f66b649616ece"}, + {file = "julep-1.14.0.tar.gz", hash = "sha256:22446414c66983d7496f5857a8b57e76394d3c2ce204bfee3cf5c6c68c4663a5"}, +] + +[package.dependencies] +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +typing-extensions = ">=4.7,<5" + [[package]] name = "jupyter-client" version = "8.6.3" @@ -1904,13 +1923,13 @@ dev = ["Sphinx (>=5.1.1)", "black (==23.12.1)", "build (>=0.10.0)", "coverage (> [[package]] name = "litellm" -version = "1.48.3" +version = "1.48.16" description = "Library to easily interface with LLM API providers" optional = false python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" files = [ - {file = "litellm-1.48.3-py3-none-any.whl", hash = "sha256:bc6f785ac1ce04ca83e734ccc1982f7cce3ed3ab8d3662baba1b636b6fb6789f"}, - {file = "litellm-1.48.3.tar.gz", hash = "sha256:3be0d1b73240c6956cc9212e476c764e9287abc6fd4c7310b1d18699b5f1be93"}, + {file = "litellm-1.48.16-py3-none-any.whl", hash = "sha256:a7bcce83c97cbacdaf89f24d1c51d81117bcf0af2f0f3a41532656c570d23932"}, + {file = "litellm-1.48.16.tar.gz", hash = "sha256:bda6fc7c8429fcd42c3a80618098678dae833990b2347740aadb84886035b31c"}, ] [package.dependencies] @@ -1919,7 +1938,7 @@ click = "*" importlib-metadata = ">=6.8.0" jinja2 = ">=3.1.2,<4.0.0" jsonschema = ">=4.22.0,<5.0.0" -openai = ">=1.45.0" +openai = ">=1.51.0" pydantic = ">=2.0.0,<3.0.0" python-dotenv = ">=0.2.0" requests = ">=2.31.0,<3.0.0" @@ -2509,13 +2528,13 @@ files = [ [[package]] name = "openai" -version = "1.50.1" +version = "1.51.0" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.50.1-py3-none-any.whl", hash = "sha256:7967fc8372d5e005ad61514586fb286d593facafccedbee00416bc38ee07c2e6"}, - {file = "openai-1.50.1.tar.gz", hash = "sha256:80cbdf275488894c70bfbad711dbba6f31ea71d579b97e364bfd99cdf030158e"}, + {file = "openai-1.51.0-py3-none-any.whl", hash = "sha256:d9affafb7e51e5a27dce78589d4964ce4d6f6d560307265933a94b2e3f3c5d2c"}, + {file = "openai-1.51.0.tar.gz", hash = "sha256:8dc4f9d75ccdd5466fc8c99a952186eddceb9fd6ba694044773f3736a847149d"}, ] [package.dependencies] @@ -3230,25 +3249,29 @@ files = [ [[package]] name = "pywin32" -version = "306" +version = "307" description = "Python for Window Extensions" optional = false python-versions = "*" files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, + {file = "pywin32-307-cp310-cp310-win32.whl", hash = "sha256:f8f25d893c1e1ce2d685ef6d0a481e87c6f510d0f3f117932781f412e0eba31b"}, + {file = "pywin32-307-cp310-cp310-win_amd64.whl", hash = "sha256:36e650c5e5e6b29b5d317385b02d20803ddbac5d1031e1f88d20d76676dd103d"}, + {file = "pywin32-307-cp310-cp310-win_arm64.whl", hash = "sha256:0c12d61e0274e0c62acee79e3e503c312426ddd0e8d4899c626cddc1cafe0ff4"}, + {file = "pywin32-307-cp311-cp311-win32.whl", hash = "sha256:fec5d27cc893178fab299de911b8e4d12c5954e1baf83e8a664311e56a272b75"}, + {file = "pywin32-307-cp311-cp311-win_amd64.whl", hash = "sha256:987a86971753ed7fdd52a7fb5747aba955b2c7fbbc3d8b76ec850358c1cc28c3"}, + {file = "pywin32-307-cp311-cp311-win_arm64.whl", hash = "sha256:fd436897c186a2e693cd0437386ed79f989f4d13d6f353f8787ecbb0ae719398"}, + {file = "pywin32-307-cp312-cp312-win32.whl", hash = "sha256:07649ec6b01712f36debf39fc94f3d696a46579e852f60157a729ac039df0815"}, + {file = "pywin32-307-cp312-cp312-win_amd64.whl", hash = "sha256:00d047992bb5dcf79f8b9b7c81f72e0130f9fe4b22df613f755ab1cc021d8347"}, + {file = "pywin32-307-cp312-cp312-win_arm64.whl", hash = "sha256:b53658acbfc6a8241d72cc09e9d1d666be4e6c99376bc59e26cdb6223c4554d2"}, + {file = "pywin32-307-cp313-cp313-win32.whl", hash = "sha256:ea4d56e48dc1ab2aa0a5e3c0741ad6e926529510516db7a3b6981a1ae74405e5"}, + {file = "pywin32-307-cp313-cp313-win_amd64.whl", hash = "sha256:576d09813eaf4c8168d0bfd66fb7cb3b15a61041cf41598c2db4a4583bf832d2"}, + {file = "pywin32-307-cp313-cp313-win_arm64.whl", hash = "sha256:b30c9bdbffda6a260beb2919f918daced23d32c79109412c2085cbc513338a0a"}, + {file = "pywin32-307-cp37-cp37m-win32.whl", hash = "sha256:5101472f5180c647d4525a0ed289ec723a26231550dbfd369ec19d5faf60e511"}, + {file = "pywin32-307-cp37-cp37m-win_amd64.whl", hash = "sha256:05de55a7c110478dc4b202230e98af5e0720855360d2b31a44bb4e296d795fba"}, + {file = "pywin32-307-cp38-cp38-win32.whl", hash = "sha256:13d059fb7f10792542082f5731d5d3d9645320fc38814759313e5ee97c3fac01"}, + {file = "pywin32-307-cp38-cp38-win_amd64.whl", hash = "sha256:7e0b2f93769d450a98ac7a31a087e07b126b6d571e8b4386a5762eb85325270b"}, + {file = "pywin32-307-cp39-cp39-win32.whl", hash = "sha256:55ee87f2f8c294e72ad9d4261ca423022310a6e79fb314a8ca76ab3f493854c6"}, + {file = "pywin32-307-cp39-cp39-win_amd64.whl", hash = "sha256:e9d5202922e74985b037c9ef46778335c102b74b95cec70f629453dbe7235d87"}, ] [[package]] @@ -3615,13 +3638,13 @@ files = [ [[package]] name = "rich" -version = "13.8.1" +version = "13.9.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "rich-13.8.1-py3-none-any.whl", hash = "sha256:1760a3c0848469b97b558fc61c85233e3dafb69c7a071b4d60c38099d3cd4c06"}, - {file = "rich-13.8.1.tar.gz", hash = "sha256:8260cda28e3db6bf04d2d1ef4dbc03ba80a824c88b0e7668a0f23126a424844a"}, + {file = "rich-13.9.2-py3-none-any.whl", hash = "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"}, + {file = "rich-13.9.2.tar.gz", hash = "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c"}, ] [package.dependencies] @@ -3799,13 +3822,13 @@ win32 = ["pywin32"] [[package]] name = "sentry-sdk" -version = "2.14.0" +version = "2.15.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" files = [ - {file = "sentry_sdk-2.14.0-py2.py3-none-any.whl", hash = "sha256:b8bc3dc51d06590df1291b7519b85c75e2ced4f28d9ea655b6d54033503b5bf4"}, - {file = "sentry_sdk-2.14.0.tar.gz", hash = "sha256:1e0e2eaf6dad918c7d1e0edac868a7bf20017b177f242cefe2a6bcd47955961d"}, + {file = "sentry_sdk-2.15.0-py2.py3-none-any.whl", hash = "sha256:8fb0d1a4e1a640172f31502e4503543765a1fe8a9209779134a4ac52d4677303"}, + {file = "sentry_sdk-2.15.0.tar.gz", hash = "sha256:a599e7d3400787d6f43327b973e55a087b931ba2c592a7a7afa691f8eb5e75e2"}, ] [package.dependencies] @@ -4267,13 +4290,13 @@ files = [ [[package]] name = "tomli" -version = "2.0.1" +version = "2.0.2" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, + {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, ] [[package]] @@ -4361,13 +4384,13 @@ files = [ [[package]] name = "types-python-dateutil" -version = "2.9.0.20240906" +version = "2.9.0.20241003" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.8" files = [ - {file = "types-python-dateutil-2.9.0.20240906.tar.gz", hash = "sha256:9706c3b68284c25adffc47319ecc7947e5bb86b3773f843c73906fd598bc176e"}, - {file = "types_python_dateutil-2.9.0.20240906-py3-none-any.whl", hash = "sha256:27c8cc2d058ccb14946eebcaaa503088f4f6dbc4fb6093d3d456a49aef2753f6"}, + {file = "types-python-dateutil-2.9.0.20241003.tar.gz", hash = "sha256:58cb85449b2a56d6684e41aeefb4c4280631246a0da1a719bdbe6f3fb0317446"}, + {file = "types_python_dateutil-2.9.0.20241003-py3-none-any.whl", hash = "sha256:250e1d8e80e7bbc3a6c99b907762711d1a1cdd00e978ad39cb5940f6f0a87f3d"}, ] [[package]] @@ -4664,4 +4687,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "04ddd9ac6f88a4b8339b1d4fb7e44ea0574b340672542a4f6c4725dd7b23d998" +content-hash = "62fd7359138dfd660b6601064b7c3e732e436fbbc9c9281b42ad3e46ff3a6c04" diff --git a/agents-api/pyproject.toml b/agents-api/pyproject.toml index 3904ae394..2ed126d6f 100644 --- a/agents-api/pyproject.toml +++ b/agents-api/pyproject.toml @@ -51,6 +51,7 @@ jupyterlab = "^4.2.4" ipywidgets = "^8.1.3" wat-inspector = "^0.2.1" +julep = ">=1.0,<2.0" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/cookbooks/01-Website_Crawler_using_Spider.py b/cookbooks/01-Website_Crawler_using_Spider.py new file mode 100644 index 000000000..978fd3286 --- /dev/null +++ b/cookbooks/01-Website_Crawler_using_Spider.py @@ -0,0 +1,71 @@ +import os +import uuid +import yaml +from julep import Client + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = os.getenv("JULEP_API_KEY") +if not api_key: + raise ValueError("JULEP_API_KEY not found in environment variables") + +client = Client(api_key=api_key, environment="dev") + +# Creating an "agent" +name = "Jarvis" +about = "The original AI conscious the Iron Man." + +# Create the agent +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name=name, + about=about, + model="gpt-4o", +) + +# Defining a Task +task_def = yaml.safe_load(""" +name: Agent Crawler + +tools: +- name: spider_crawler + type: integration + integration: + provider: spider + setup: + spider_api_key: "{{SPIDER_API_KEY}}" + +main: +- tool: spider_crawler + arguments: + url: '"https://spider.cloud"' +""") + +# Creating/Updating a task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Creating an Execution +execution = client.executions.create( + task_id=TASK_UUID, + input={} +) + +# Getting the execution details +execution = client.executions.get(execution.id) +print("Execution output:", execution.output) + +# Listing all the steps of a defined task +transitions = client.executions.transitions.list(execution_id=execution.id).items +print("Execution transitions:", transitions) + +# Streaming the execution steps +print("Streaming execution transitions:") +for transition in client.executions.transitions.stream(execution_id=execution.id): + print(transition) \ No newline at end of file diff --git a/cookbooks/02-Sarcastic_News_Headline_Generator.py b/cookbooks/02-Sarcastic_News_Headline_Generator.py new file mode 100644 index 000000000..c658a6569 --- /dev/null +++ b/cookbooks/02-Sarcastic_News_Headline_Generator.py @@ -0,0 +1,89 @@ +import os +import uuid +import yaml +from julep import Client + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Create Julep Client with the API Key +api_key = os.getenv("JULEP_API_KEY") +if not api_key: + raise ValueError("JULEP_API_KEY not found in environment variables") + +client = Client(api_key=api_key, environment="dev") + +# Define agent properties +name = "Sarcastic News Bot" +about = "An AI agent specialized in generating sarcastic news headlines." +default_settings = { + "temperature": 0.7, + "top_p": 1, + "min_p": 0.01, + "presence_penalty": 0, + "frequency_penalty": 0, + "length_penalty": 1.0, + "max_tokens": 150, +} + +# Create the agent +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name=name, + about=about, + model="gpt-4o", +) + +# Define the task +task_def = yaml.safe_load(""" +name: Sarcasm Headline Generator + +tools: +- name: brave_search + type: integration + integration: + provider: brave + setup: + api_key: "YOUR_BRAVE_API_KEY" + +main: +- tool: brave_search + arguments: + query: "_.topic + ' funny'" + +- prompt: + - role: system + content: >- + You are a sarcastic news headline writer. Generate a witty and sarcastic headline + for the topic {{inputs[0].topic}}. Use the following information for context: {{_}} + unwrap: true +""") + +# Creating/Updating a task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Creating an Execution +execution = client.executions.create( + task_id=TASK_UUID, + input={ + "topic": "elon musk" + } +) + +# Getting the execution details +execution = client.executions.get(execution.id) +print("Execution output:", execution.output) + +# Listing all the steps of a defined task +transitions = client.executions.transitions.list(execution_id=execution.id).items +print("Execution transitions:", transitions) + +# Stream the steps of the defined task +print("Streaming execution transitions:") +for transition in client.executions.transitions.stream(execution_id=execution.id): + print(transition) diff --git a/cookbooks/03-SmartResearcher_With_WebSearch.py b/cookbooks/03-SmartResearcher_With_WebSearch.py new file mode 100644 index 000000000..9996a5dd5 --- /dev/null +++ b/cookbooks/03-SmartResearcher_With_WebSearch.py @@ -0,0 +1,104 @@ +import uuid +from julep import Client +import yaml + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an "agent" +name = "Jarvis" +about = "The original AI conscious the Iron Man." +default_settings = { + "temperature": 0.7, + "top_p": 1, + "min_p": 0.01, + "presence_penalty": 0, + "frequency_penalty": 0, + "length_penalty": 1.0, + "max_tokens": 150, +} + +# Create the agent +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name=name, + about=about, + model="gpt-4o", +) + +# Defining a Task +task_def = yaml.safe_load(""" +name: Research Assistant to find Wikipedia Keywords + +input_schema: + type: object + properties: + topics: + type: array + items: + type: string + description: The topics to search for. + +tools: +- name: brave_search + type: integration + integration: + provider: brave + setup: + api_key: "YOUR_API_KEY" + +main: +- over: _.topics + map: + tool: brave_search + arguments: + query: "'the latest news about ' + _" + +- over: _ + parallelism: 2 + map: + prompt: + - role: system + content: >- + You are a research assistant. + I need you to do in-depth research on topics trending in the news currently. + Based on the following latest html news snippet, come up with a list of wikipedia keywords to search: + "{{_}}" + Your response should be a list of keywords, separated by commas. Do not add any other text. + Example: `KEYWORDS: keyword1, keyword2, keyword3` + + unwrap: true +""") + +# Creating/Updating a task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Creating an Execution +execution = client.executions.create( + task_id=task.id, + input={ + "topics": ["Burger King Cup on the Ground Behind a Wendy's", "Forbidden Chemical X", "Finger Bracelets", "Amusing Notions"] + } +) + +print(execution.id) + +# Getting the execution details +execution = client.executions.get(execution.id) +print(execution.output) + +# Listing all the steps of a defined task +transitions = client.executions.transitions.list(execution_id=execution.id).items +print(transitions) + +# Streaming the execution steps +client.executions.transitions.stream(execution_id=execution.id) \ No newline at end of file diff --git a/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py b/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py new file mode 100644 index 000000000..cde5d71a6 --- /dev/null +++ b/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py @@ -0,0 +1,123 @@ +import uuid +import yaml +from julep import Client + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an "agent" +name = "Jarvis" +about = "The original AI conscious the Iron Man." +default_settings = { + "temperature": 0.7, + "top_p": 1, + "min_p": 0.01, + "presence_penalty": 0, + "frequency_penalty": 0, + "length_penalty": 1.0, + "max_tokens": 150, +} + +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name=name, + about=about, + model="gpt-4o", +) + +# Defining a Task +task_def = yaml.safe_load(""" +name: Tourist Plan With Weather And Attractions + +input_schema: + type: object + properties: + locations: + type: array + items: + type: string + description: The locations to search for. + +tools: +- name: wikipedia + type: integration + integration: + provider: wikipedia + +- name: weather + type: integration + integration: + provider: weather + setup: + openweathermap_api_key: "YOUR_API_KEY" + +main: +- over: inputs[0].locations + map: + tool: weather + arguments: + location: _ + +- over: inputs[0].locations + map: + tool: wikipedia + arguments: + query: "_ + ' tourist attractions'" + +- evaluate: + zipped: "list(zip(inputs[0].locations, [output['result'] for output in outputs[0]], [output['documents'][0]['page_content'] for output in outputs[1]]))" # [(location, weather, attractions)] + +- over: _['zipped'] + parallelism: 3 + map: + prompt: + - role: system + content: >- + You are a travel assistant. Your task is to create a detailed itinerary for visiting tourist attractions in "{{_[0]}}" based on the weather conditions and the top tourist attractions provided. + + Current weather condition at "{{_[0]}}": + "{{_[1]}}" + + Top tourist attractions in "{{_[0]}}": + "{{_[2]}}" + + Suggest outdoor or indoor activities based on the above information. + unwrap: true +""") + +# Creating/Updating a task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Creating an Execution +execution = client.executions.create( + task_id=task.id, + input={ + "locations": ["New York", "London", "Paris", "Tokyo", "Sydney"] + } +) + +print(f"Execution ID: {execution.id}") + +# Getting the execution details +execution = client.executions.get(execution.id) +print("Execution Output:") +print(execution.output) + +# List all steps of the executed task +print("Execution Steps:") +for item in client.executions.transitions.list(execution_id=execution.id).items: + print(item) + +# Stream the execution steps in real-time +print("Streaming Execution Steps:") +for step in client.executions.transitions.stream(execution_id=execution.id): + print(step) \ No newline at end of file diff --git a/cookbooks/05-Basic_Agent_Creation_and_Interaction.py b/cookbooks/05-Basic_Agent_Creation_and_Interaction.py new file mode 100644 index 000000000..c701471f7 --- /dev/null +++ b/cookbooks/05-Basic_Agent_Creation_and_Interaction.py @@ -0,0 +1,71 @@ +import uuid +from julep import Client + +# Global UUID is generated for agent +AGENT_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an "agent" +name = "Jarvis" +about = "A friendly and knowledgeable AI assistant." +default_settings = { + "temperature": 0.7, + "top_p": 1, + "min_p": 0.01, + "presence_penalty": 0, + "frequency_penalty": 0, + "length_penalty": 1.0, + "max_tokens": 150, +} + +# Create the agent +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name=name, + about=about, + model="gpt-4-turbo", +) + +print(f"Agent created with ID: {agent.id}") + +# Create a session for interaction +session = client.sessions.create( + agent=agent.id, + context_overflow="adaptive" +) + +print(f"Session created with ID: {session.id}") + +# Function to chat with the agent +def chat_with_agent(message): + message = { + "role": "user", + "content": message, + } + # TODO: message validation error + response = client.sessions.chat( + session_id=session.id, + messages=[message], + ) + return response.choices[0].message.content + +# Demonstrate basic interaction +print("Agent: Hello! I'm Jarvis, your AI assistant. How can I help you today?") + +while True: + user_input = input("You: ") + if user_input.lower() in ['exit', 'quit', 'bye']: + print("Agent: Goodbye! It was nice chatting with you.") + break + + response = chat_with_agent(user_input) + print(f"Agent: {response}") + +# Optional: Retrieve chat history +history = client.sessions.messages.list(session_id=session.id) +print("\nChat History:") +for message in history.items: + print(f"{message.role}: {message.content}") \ No newline at end of file diff --git a/cookbooks/06-Designing_Multi-Step_Tasks.py b/cookbooks/06-Designing_Multi-Step_Tasks.py new file mode 100644 index 000000000..395f409cf --- /dev/null +++ b/cookbooks/06-Designing_Multi-Step_Tasks.py @@ -0,0 +1,138 @@ +import uuid +import yaml +from julep import Client + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an "agent" +name = "Multi-Step Task Agent" +about = "An agent capable of executing complex multi-step tasks." +default_settings = { + "temperature": 0.7, + "top_p": 1, + "min_p": 0.01, + "presence_penalty": 0, + "frequency_penalty": 0, + "length_penalty": 1.0, + "max_tokens": 150, +} + +# Create the agent +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name=name, + about=about, + model="gpt-4-turbo", +) + +# Add a web search tool to the agent +client.agents.tools.create( + agent_id=AGENT_UUID, + name="web_search", + description="Search the web for information.", + integration={ + "provider": "brave", + "method": "search", + "setup": {"api_key": "your_brave_api_key"}, + }, +) + +# Defining a Task with various step types +task_def = yaml.safe_load(""" +name: Multi-Step Task Demonstration + +input_schema: + type: object + properties: + topic: + type: string + description: The topic to research and summarize. + +tools: +- name: web_search + type: integration + integration: + provider: brave + setup: + api_key: "your_api_key" + +main: +# Step 1: Prompt - Initial research question +- prompt: + - role: system + content: "You are a research assistant. Your task is to formulate three specific research questions about the given topic: {{inputs[0].topic}}" + unwrap: true + +# Step 2: Tool Call - Web search for each question +- foreach: + in: "_.split('\n')" + do: + tool: web_search + arguments: + query: _ + +# Step 3: Evaluate - Extract relevant information +- evaluate: + relevant_info: "[output for output in _]" + +# Step 4: Conditional Logic - Check if enough information is gathered +- if: "len(_.relevant_info) >= 3" + then: + prompt: + - role: system + content: "Summarize the following information about {{inputs[0].topic}}:\n{{_.relevant_info}}" + unwrap: true + else: + prompt: + - role: system + content: "Not enough information gathered. Please provide a brief overview of {{inputs[0].topic}} based on your knowledge." + unwrap: true + +# Step 5: Log - Record the summary +- log: "Summary for {{inputs[0].topic}}: {{_}}" + +# Step 6: Return - Final output +- return: + summary: "_" + topic: "inputs[0].topic" + +""") + +# Creating/Updating a task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Creating an Execution +execution = client.executions.create( + task_id=TASK_UUID, + input={ + "topic": "Artificial Intelligence in Healthcare" + } +) + +print(f"Execution ID: {execution.id}") + +# Getting the execution details +execution = client.executions.get(execution.id) +print("Execution Output:") +print(execution.output) + +# Listing all the steps of a defined task +transitions = client.executions.transitions.list(execution_id=execution.id).items +print("Execution Steps:") +for transition in transitions: + print(transition) + +# Streaming the execution steps +print("Streaming Execution Steps:") +for transition in client.executions.transitions.stream(execution_id=execution.id): + print(transition) \ No newline at end of file diff --git a/cookbooks/07-Integrating_External_Tools_and_APIs.py b/cookbooks/07-Integrating_External_Tools_and_APIs.py new file mode 100644 index 000000000..fa93f687a --- /dev/null +++ b/cookbooks/07-Integrating_External_Tools_and_APIs.py @@ -0,0 +1,126 @@ +import uuid +import yaml +from julep import Client + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an "agent" +name = "Multi-Tool Analyst" +about = "An AI agent capable of using multiple external tools and APIs to gather and analyze information." + +# Create the agent +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name=name, + about=about, + model="gpt-4-turbo", +) + +# Defining a Task +task_def = yaml.safe_load(""" +name: Comprehensive Analysis Report + +input_schema: + type: object + properties: + topic: + type: string + description: The main topic to analyze. + location: + type: string + description: A location related to the topic for weather and news analysis. + +tools: +- name: brave_search + type: integration + integration: + provider: brave + setup: + api_key: "YOUR_BRAVE_API_KEY" + +- name: weather + type: integration + integration: + provider: weather + setup: + openweathermap_api_key: "YOUR_OPENWEATHERMAP_API_KEY" + +- name: wikipedia + type: integration + integration: + provider: wikipedia + +main: +- tool: brave_search + arguments: + query: "{{inputs[0].topic}} latest developments" + +- tool: weather + arguments: + location: "{{inputs[0].location}}" + +- tool: wikipedia + arguments: + query: "{{inputs[0].topic}}" + +- prompt: + - role: system + content: >- + You are a comprehensive analyst. Your task is to create a detailed report on the topic "{{inputs[0].topic}}" + using the information gathered from various sources. Include the following sections in your report: + + 1. Overview (based on Wikipedia data) + 2. Latest Developments (based on Brave Search results) + 3. Weather Impact (if applicable, based on weather data for {{inputs[0].location}}) + 4. Analysis and Conclusions + + Use the following data for your report: + + Brave Search Results: {{outputs[0]}} + Weather Data: {{outputs[1]}} + Wikipedia Data: {{outputs[2]}} + + Provide a well-structured, informative report that synthesizes information from all these sources. + unwrap: true + +- return: _ +""") + +# Creating/Updating a task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Creating an Execution +execution = client.executions.create( + task_id=task.id, + input={ + "topic": "Renewable Energy", + "location": "Berlin, Germany" + } +) + +print(f"Execution ID: {execution.id}") + +# Getting the execution details +execution = client.executions.get(execution.id) +print("Execution Output:") +print(execution.output) + +# List all steps of the executed task +print("Execution Steps:") +for item in client.executions.transitions.list(execution_id=execution.id).items: + print(item) + +# Stream the execution steps in real-time +print("Streaming Execution Steps:") +for step in client.executions.transitions.stream(execution_id=execution.id): + print(step) \ No newline at end of file diff --git a/cookbooks/08-Managing_Persistent_Sessions.py b/cookbooks/08-Managing_Persistent_Sessions.py new file mode 100644 index 000000000..40077b7df --- /dev/null +++ b/cookbooks/08-Managing_Persistent_Sessions.py @@ -0,0 +1,137 @@ +# Managing Persistent Sessions Cookbook +# +# Plan: +# 1. Import necessary libraries and set up the Julep client +# 2. Create an agent for handling persistent sessions +# 3. Define a task for managing user context +# 4. Create a function to simulate user interactions +# 5. Implement a loop to demonstrate persistent sessions with context management +# 6. Show how to handle context overflow +# 7. Display the session history and context at the end + +import uuid +import yaml +from julep import Client +import time + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an agent for handling persistent sessions +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name="Session Manager", + about="An AI agent specialized in managing persistent sessions and context.", + model="gpt-4-turbo", +) + +# Defining a task for managing user context +task_def = yaml.safe_load(""" +name: Manage User Context + +input_schema: + type: object + properties: + user_input: + type: string + session_context: + type: object + +main: +- prompt: + role: system + content: >- + You are a session management agent. Your task is to maintain context + across user interactions. Here's the current context: {{inputs[0].session_context}} + + User input: {{inputs[0].user_input}} + + Respond to the user and update the context with any new relevant information. + unwrap: true + +- evaluate: + updated_context: >- + {**inputs[0].session_context, + 'last_interaction': inputs[0].user_input, + 'agent_response': _} + +- return: + response: _ + context: outputs[1].updated_context +""") + +# Creating the task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Function to simulate user interactions +def user_interaction(prompt): + return input(prompt) + +# Create a session +session = client.sessions.create( + agent_id=AGENT_UUID, + context_overflow="adaptive" # Use adaptive context management +) + +# Initialize session context +context = {} + +# Simulate a conversation with persistent context +for i in range(5): + user_input = user_interaction(f"User (Interaction {i+1}): ") + + # Execute the task with user input and current context + execution = client.executions.create( + task_id=TASK_UUID, + input={ + "user_input": user_input, + "session_context": context + } + ) + + # Get the execution result + result = client.executions.get(execution.id) + + # Update the context and print the response + context = result.output['context'] + print(f"Agent: {result.output['response']}") + print(f"Updated Context: {context}") + print() + + # Simulate a delay between interactions + time.sleep(1) + +# Display final session information +print("Final Session Information:") +print(f"Session ID: {session.id}") +print(f"Final Context: {context}") + +# Demonstrate context overflow handling +print("\nDemonstrating Context Overflow Handling:") +large_input = "This is a very large input " * 1000 # Create a large input to trigger overflow +overflow_execution = client.executions.create( + task_id=TASK_UUID, + input={ + "user_input": large_input, + "session_context": context + } +) + +overflow_result = client.executions.get(overflow_execution.id) +print(f"Agent response to large input: {overflow_result.output['response']}") +print(f"Updated context after overflow: {overflow_result.output['context']}") + +# Display session history +print("\nSession History:") +history = client.sessions.messages.list(session_id=session.id) +for message in history.items: + print(f"{message.role}: {message.content}") \ No newline at end of file diff --git a/cookbooks/09-User_Management_and_Personalization.py b/cookbooks/09-User_Management_and_Personalization.py new file mode 100644 index 000000000..18f9df238 --- /dev/null +++ b/cookbooks/09-User_Management_and_Personalization.py @@ -0,0 +1,188 @@ +# User Management and Personalization Cookbook +# +# Plan: +# 1. Import necessary libraries and set up the Julep client +# 2. Create an agent for handling user management and personalization +# 3. Define a task for user registration and profile creation +# 4. Define a task for personalized content recommendation +# 5. Create sample users with different preferences +# 6. Demonstrate user registration and profile creation +# 7. Show personalized content recommendations for different users +# 8. Implement a function to update user preferences +# 9. Display updated personalized recommendations after preference changes + +import uuid +import yaml +from julep import Client + +# Global UUIDs for agent and tasks +AGENT_UUID = uuid.uuid4() +REGISTRATION_TASK_UUID = uuid.uuid4() +RECOMMENDATION_TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an agent for user management and personalization +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name="Personalization Assistant", + about="An AI agent specialized in user management and personalized content recommendations.", + model="gpt-4-turbo", +) + +# Defining a task for user registration and profile creation +registration_task_def = yaml.safe_load(""" +name: User Registration and Profile Creation + +input_schema: + type: object + properties: + username: + type: string + interests: + type: array + items: + type: string + +main: +- prompt: + role: system + content: >- + You are a user registration assistant. Create a user profile based on the following information: + Username: {{inputs[0].username}} + Interests: {{inputs[0].interests}} + + Generate a brief bio and suggest some initial content preferences based on the user's interests. + unwrap: true + +- evaluate: + user_profile: >- + { + "username": inputs[0].username, + "interests": inputs[0].interests, + "bio": _.split('\n\n')[0], + "content_preferences": _.split('\n\n')[1] + } + +- return: outputs[1].user_profile +""") + +# Creating the registration task +registration_task = client.tasks.create_or_update( + task_id=REGISTRATION_TASK_UUID, + agent_id=AGENT_UUID, + **registration_task_def +) + +# Defining a task for personalized content recommendation +recommendation_task_def = yaml.safe_load(""" +name: Personalized Content Recommendation + +input_schema: + type: object + properties: + user_profile: + type: object + +tools: +- name: content_database + type: integration + integration: + provider: mock + setup: + data: [ + {"id": 1, "title": "Introduction to AI", "category": "Technology"}, + {"id": 2, "title": "Healthy Eating Habits", "category": "Health"}, + {"id": 3, "title": "Financial Planning 101", "category": "Finance"}, + {"id": 4, "title": "The Art of Photography", "category": "Art"}, + {"id": 5, "title": "Beginner's Guide to Yoga", "category": "Fitness"} + ] + +main: +- tool: content_database + arguments: {} + +- prompt: + role: system + content: >- + You are a content recommendation system. Based on the user's profile and the available content, + recommend 3 pieces of content that best match the user's interests and preferences. + + User Profile: + {{inputs[0].user_profile}} + + Available Content: + {{outputs[0]}} + + Provide your recommendations in the following format: + 1. [Content ID] - [Content Title] - Reason for recommendation + 2. [Content ID] - [Content Title] - Reason for recommendation + 3. [Content ID] - [Content Title] - Reason for recommendation + unwrap: true + +- return: _ +""") + +# Creating the recommendation task +recommendation_task = client.tasks.create_or_update( + task_id=RECOMMENDATION_TASK_UUID, + agent_id=AGENT_UUID, + **recommendation_task_def +) + +# Function to register a user and create their profile +def register_user(username, interests): + execution = client.executions.create( + task_id=REGISTRATION_TASK_UUID, + input={ + "username": username, + "interests": interests + } + ) + result = client.executions.get(execution.id) + return result.output + +# Function to get personalized content recommendations +def get_recommendations(user_profile): + execution = client.executions.create( + task_id=RECOMMENDATION_TASK_UUID, + input={ + "user_profile": user_profile + } + ) + result = client.executions.get(execution.id) + return result.output + +# Function to update user preferences +def update_user_preferences(user_profile, new_interests): + user_profile["interests"] = list(set(user_profile["interests"] + new_interests)) + return user_profile + +# Demonstrate user registration and personalization +print("Demonstrating User Management and Personalization:") + +# Register users +user1 = register_user("alice", ["technology", "finance"]) +user2 = register_user("bob", ["health", "fitness"]) + +print("\nUser Profiles:") +print(f"Alice: {user1}") +print(f"Bob: {user2}") + +# Get personalized recommendations +print("\nPersonalized Recommendations:") +print("Alice's Recommendations:") +print(get_recommendations(user1)) +print("\nBob's Recommendations:") +print(get_recommendations(user2)) + +# Update user preferences +print("\nUpdating User Preferences:") +updated_alice = update_user_preferences(user1, ["art"]) +print(f"Alice's Updated Profile: {updated_alice}") + +# Get updated recommendations +print("\nUpdated Personalized Recommendations for Alice:") +print(get_recommendations(updated_alice)) \ No newline at end of file diff --git a/cookbooks/10-Document_Management_and_Search.py b/cookbooks/10-Document_Management_and_Search.py new file mode 100644 index 000000000..87cc492aa --- /dev/null +++ b/cookbooks/10-Document_Management_and_Search.py @@ -0,0 +1,156 @@ +# Document Management and Search Cookbook +# +# Plan: +# 1. Import necessary libraries and set up the Julep client +# 2. Create an agent for document management +# 3. Define a task for document upload and indexing +# 4. Define a task for document search +# 5. Create sample documents +# 6. Execute the document upload and indexing task +# 7. Execute the document search task +# 8. Display the search results + +import uuid +import yaml +from julep import Client + +# Global UUID is generated for agent and tasks +AGENT_UUID = uuid.uuid4() +UPLOAD_TASK_UUID = uuid.uuid4() +SEARCH_TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an agent for document management +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name="Document Manager", + about="An AI agent specialized in document management and search.", + model="gpt-4o", +) + +# Defining a task for document upload and indexing +upload_task_def = yaml.safe_load(""" +name: Document Upload and Indexing + +input_schema: + type: object + properties: + documents: + type: array + items: + type: object + properties: + content: + type: string + metadata: + type: object + +main: +- over: inputs[0].documents + map: + tool: document_upload + arguments: + content: _.content + metadata: _.metadata + +- prompt: + role: system + content: >- + You have successfully uploaded and indexed {{len(outputs[0])}} documents. + Provide a summary of the uploaded documents. +""") + +# Creating the upload task +upload_task = client.tasks.create_or_update( + task_id=UPLOAD_TASK_UUID, + agent_id=AGENT_UUID, + **upload_task_def +) + +# Defining a task for document search +search_task_def = yaml.safe_load(""" +name: Document Search + +input_schema: + type: object + properties: + query: + type: string + filters: + type: object + +main: +- tool: document_search + arguments: + query: inputs[0].query + filters: inputs[0].filters + +- prompt: + role: system + content: >- + Based on the search results, provide a summary of the most relevant documents found. + Search query: {{inputs[0].query}} + Number of results: {{len(outputs[0])}} + + Results: + {{outputs[0]}} +""") + +# Creating the search task +search_task = client.tasks.create_or_update( + task_id=SEARCH_TASK_UUID, + agent_id=AGENT_UUID, + **search_task_def +) + +# Sample documents +sample_documents = [ + { + "content": "Artificial Intelligence (AI) is revolutionizing various industries, including healthcare, finance, and transportation.", + "metadata": {"category": "technology", "author": "John Doe"} + }, + { + "content": "Climate change is a pressing global issue that requires immediate action from governments, businesses, and individuals.", + "metadata": {"category": "environment", "author": "Jane Smith"} + }, + { + "content": "The COVID-19 pandemic has accelerated the adoption of remote work and digital technologies across many organizations.", + "metadata": {"category": "business", "author": "Alice Johnson"} + } +] + +# Execute the document upload and indexing task +upload_execution = client.executions.create( + task_id=UPLOAD_TASK_UUID, + input={"documents": sample_documents} +) + +print("Uploading and indexing documents...") +upload_result = client.executions.get(upload_execution.id) +print(upload_result.output) + +# Execute the document search task +search_execution = client.executions.create( + task_id=SEARCH_TASK_UUID, + input={ + "query": "impact of technology on society", + "filters": {"category": "technology"} + } +) + +print("\nSearching documents...") +search_result = client.executions.get(search_execution.id) +print(search_result.output) + +# Display the search results +print("\nSearch Results:") +for transition in client.executions.transitions.list(execution_id=search_execution.id).items: + if transition.type == "tool_call" and transition.tool == "document_search": + for doc in transition.output: + print(f"- {doc['content']} (Score: {doc['score']})") + +print("\nSearch Summary:") +print(search_result.output) \ No newline at end of file diff --git a/cookbooks/11-Advanced_Chat_Interactions.py b/cookbooks/11-Advanced_Chat_Interactions.py new file mode 100644 index 000000000..692112be1 --- /dev/null +++ b/cookbooks/11-Advanced_Chat_Interactions.py @@ -0,0 +1,177 @@ +# Advanced Chat Interactions Cookbook +# +# Plan: +# 1. Import necessary libraries and set up the Julep client +# 2. Create an agent for advanced chat interactions +# 3. Define a task for handling complex conversations with context management +# 4. Implement a function to simulate user input +# 5. Create a chat session and demonstrate advanced interactions: +# a. Multi-turn conversation with context retention +# b. Handling context overflow +# c. Conditional responses based on user input +# d. Integrating external information during the conversation +# 6. Display the chat history and any relevant metrics + +import uuid +import yaml +import os +from julep import Client +import time + +# Global UUIDs for agent and task +AGENT_UUID = uuid.uuid4() +CHAT_TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = os.getenv("JULEP_API_KEY") +if not api_key: + raise ValueError("JULEP_API_KEY not found in environment variables") + +client = Client(api_key=api_key, environment="dev") + +# Creating an agent for advanced chat interactions +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name="Advanced Chat Assistant", + about="An AI agent capable of handling complex conversations with context management and external integrations.", + model="gpt-4-turbo", +) + +# Add a web search tool to the agent +client.agents.tools.create( + agent_id=AGENT_UUID, + name="web_search", + description="Search the web for information.", + integration={ + "provider": "brave", + "method": "search", + "setup": {"api_key": "YOUR_BRAVE_API_KEY"}, + }, +) + +# Defining a task for handling complex conversations +chat_task_def = yaml.safe_load(""" +name: Advanced Chat Interaction + +input_schema: + type: object + properties: + user_input: + type: string + chat_history: + type: array + items: + type: object + properties: + role: + type: string + content: + type: string + +tools: +- name: weather_api + type: integration + integration: + provider: weather + setup: + api_key: "YOUR_WEATHER_API_KEY" + +main: +- evaluate: + context_length: len(inputs[0].chat_history) + +- if: + condition: _.context_length > 10 + then: + - evaluate: + summarized_history: "Summarize the following chat history: " + str(inputs[0].chat_history[-10:]) + - prompt: + role: system + content: >- + You are an advanced chat assistant. Here's a summary of the recent conversation: + {{outputs[1].summarized_history}} + + Now, respond to the user's latest input: {{inputs[0].user_input}} + else: + - prompt: + role: system + content: >- + You are an advanced chat assistant. Here's the conversation history: + {{inputs[0].chat_history}} + + Now, respond to the user's latest input: {{inputs[0].user_input}} + +- if: + condition: "weather" in inputs[0].user_input.lower() + then: + - tool: weather_api + arguments: + location: "New York" + - prompt: + role: system + content: >- + The user mentioned weather. Here's the current weather information for New York: + {{outputs[3]}} + + Incorporate this information into your response. + +- return: _ +""") + +# Creating the chat task +chat_task = client.tasks.create_or_update( + task_id=CHAT_TASK_UUID, + agent_id=AGENT_UUID, + **chat_task_def +) + +# Function to simulate user input +def get_user_input(): + return input("User: ") + +# Function to display chat history +def display_chat_history(chat_history): + for message in chat_history: + print(f"{message['role'].capitalize()}: {message['content']}") + +# Main chat loop +def run_chat_session(): + chat_history = [] + print("Starting advanced chat session. Type 'exit' to end the conversation.") + + session = client.sessions.create(agent_id=AGENT_UUID) + + while True: + user_input = get_user_input() + if user_input.lower() == 'exit': + break + + chat_history.append({"role": "user", "content": user_input}) + + execution = client.executions.create( + task_id=CHAT_TASK_UUID, + input={ + "user_input": user_input, + "chat_history": chat_history + } + ) + + result = client.executions.get(execution.id) + assistant_response = result.output + + chat_history.append({"role": "assistant", "content": assistant_response}) + print(f"Assistant: {assistant_response}") + + # Simulate a delay for a more natural conversation flow + time.sleep(1) + + print("\nChat session ended. Here's the complete chat history:") + display_chat_history(chat_history) + +# Run the chat session +run_chat_session() + +# Display execution metrics (optional) +print("\nExecution Metrics:") +for transition in client.executions.transitions.list(execution_id=execution.id).items: + print(f"Step: {transition.type}, Duration: {transition.duration_ms}ms") \ No newline at end of file diff --git a/cookbooks/12-Monitoring_Task_Executions.py b/cookbooks/12-Monitoring_Task_Executions.py new file mode 100644 index 000000000..7e5f576a0 --- /dev/null +++ b/cookbooks/12-Monitoring_Task_Executions.py @@ -0,0 +1,160 @@ +# Monitoring Task Executions Cookbook +# +# Plan: +# 1. Import necessary libraries and set up the Julep client +# 2. Create an agent for task execution monitoring +# 3. Define a multi-step task that simulates a complex workflow +# 4. Implement functions for: +# a. Starting task execution +# b. Monitoring execution progress +# c. Handling execution status updates +# d. Logging execution metrics +# 5. Execute the task and demonstrate real-time monitoring +# 6. Display execution summary and metrics + +import uuid +import yaml +from julep import Client +import time + +# Global UUIDs for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an agent for task execution monitoring +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name="Task Execution Monitor", + about="An AI agent designed to monitor and manage complex task executions.", + model="gpt-4-turbo", +) + +# Defining a multi-step task that simulates a complex workflow +task_def = yaml.safe_load(""" +name: Complex Workflow Simulation + +input_schema: + type: object + properties: + project_name: + type: string + data_size: + type: integer + +tools: +- name: data_processor + type: integration + integration: + provider: mock + setup: + processing_time: 5 # Simulated processing time in seconds + +- name: report_generator + type: integration + integration: + provider: mock + setup: + generation_time: 3 # Simulated generation time in seconds + +main: +- prompt: + role: system + content: >- + Initiating project '{{inputs[0].project_name}}' with data size {{inputs[0].data_size}} units. + Prepare for data processing and report generation. + unwrap: true + +- tool: data_processor + arguments: + data_size: inputs[0].data_size + +- evaluate: + processed_data: "Processed " + str(inputs[0].data_size) + " units of data" + +- tool: report_generator + arguments: + data: outputs[2].processed_data + +- prompt: + role: system + content: >- + Project '{{inputs[0].project_name}}' completed. + Data processed: {{outputs[2].processed_data}} + Report generated: {{outputs[3]}} + + Summarize the project results. + unwrap: true + +- return: _ +""") + +# Creating the task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +def start_task_execution(project_name, data_size): + """Start the task execution and return the execution object.""" + execution = client.executions.create( + task_id=TASK_UUID, + input={ + "project_name": project_name, + "data_size": data_size + } + ) + print(f"Task execution started for project '{project_name}'") + return execution + +def monitor_execution_progress(execution_id): + """Monitor the execution progress in real-time.""" + print("Monitoring execution progress:") + for transition in client.executions.transitions.stream(execution_id=execution_id): + print(f"Step: {transition.type}, Status: {transition.status}") + if transition.status == "completed": + print(f" Output: {transition.output}") + elif transition.status == "failed": + print(f" Error: {transition.error}") + time.sleep(1) # Add a small delay to simulate real-time monitoring + +def get_execution_status(execution_id): + """Get the current status of the execution.""" + execution = client.executions.get(execution_id) + return execution.status + +def log_execution_metrics(execution_id): + """Log and display execution metrics.""" + print("\nExecution Metrics:") + transitions = client.executions.transitions.list(execution_id=execution_id).items + total_duration = sum(t.duration_ms for t in transitions) + for transition in transitions: + print(f"Step: {transition.type}, Duration: {transition.duration_ms}ms") + print(f"Total Execution Time: {total_duration}ms") + +# Main execution flow +def run_task_monitoring_demo(): + project_name = "Data Analysis Project" + data_size = 1000 + + print(f"Starting task execution for '{project_name}' with {data_size} units of data") + execution = start_task_execution(project_name, data_size) + + monitor_execution_progress(execution.id) + + final_status = get_execution_status(execution.id) + print(f"\nFinal Execution Status: {final_status}") + + if final_status == "completed": + result = client.executions.get(execution.id) + print("\nExecution Result:") + print(result.output) + + log_execution_metrics(execution.id) + +# Run the task monitoring demo +run_task_monitoring_demo() \ No newline at end of file diff --git a/cookbooks/13-Error_Handling_and_Recovery.py b/cookbooks/13-Error_Handling_and_Recovery.py new file mode 100644 index 000000000..b45732ed5 --- /dev/null +++ b/cookbooks/13-Error_Handling_and_Recovery.py @@ -0,0 +1,163 @@ +# Error Handling and Recovery Cookbook +# +# Plan: +# 1. Import necessary libraries and set up the Julep client +# 2. Create an agent for error handling demonstration +# 3. Define a task with potential errors and recovery mechanisms +# 4. Execute the task and demonstrate error handling +# 5. Implement a retry mechanism for failed steps +# 6. Show how to log and report errors +# 7. Demonstrate graceful degradation when a step fails + +import uuid +import yaml +import time +from julep import Client + +# Global UUID is generated for agent and task +AGENT_UUID = uuid.uuid4() +TASK_UUID = uuid.uuid4() + +# Creating Julep Client with the API Key +api_key = "" # Your API key here +client = Client(api_key=api_key, environment="dev") + +# Creating an agent for error handling demonstration +agent = client.agents.create_or_update( + agent_id=AGENT_UUID, + name="Error Handler", + about="An AI agent specialized in demonstrating error handling and recovery mechanisms.", + model="gpt-4-turbo", +) + +# Defining a task with potential errors and recovery mechanisms +task_def = yaml.safe_load(""" +name: Error Handling Demo + +input_schema: + type: object + properties: + operation: + type: string + enum: ["divide", "api_call", "process_data"] + value: + type: number + +tools: +- name: divide + type: function + function: + name: divide + description: Divide 100 by the given number + parameters: + type: object + properties: + divisor: + type: number + +- name: api_call + type: integration + integration: + provider: httpbin + method: get + +- name: process_data + type: function + function: + name: process_data + description: Process the given data + parameters: + type: object + properties: + data: + type: string + +main: +- switch: + value: inputs[0].operation + cases: + divide: + - tool: divide + arguments: + divisor: inputs[0].value + on_error: + retry: + max_attempts: 3 + delay: 2 + fallback: + return: "Error: Division by zero or invalid input" + api_call: + - tool: api_call + arguments: + endpoint: "/status/{{inputs[0].value}}" + on_error: + retry: + max_attempts: 3 + delay: 5 + fallback: + return: "Error: API call failed after multiple attempts" + process_data: + - evaluate: + data: "'Sample data: ' + str(inputs[0].value)" + - tool: process_data + arguments: + data: _.data + on_error: + log: "Error occurred while processing data" + return: "Error: Data processing failed" + +- prompt: + role: system + content: >- + Summarize the result of the operation: + Operation: {{inputs[0].operation}} + Result: {{_}} +""") + +# Creating the task +task = client.tasks.create_or_update( + task_id=TASK_UUID, + agent_id=AGENT_UUID, + **task_def +) + +# Function to execute task and handle errors +def execute_task_with_error_handling(operation, value): + try: + execution = client.executions.create( + task_id=TASK_UUID, + input={"operation": operation, "value": value} + ) + + print(f"Executing {operation} with value {value}...") + + # Stream execution to show progress and potential retries + for step in client.executions.transitions.stream(execution_id=execution.id): + if step.type == "tool_call": + print(f"Step: {step.tool}") + if step.status == "error": + print(f"Error occurred: {step.error}") + if step.retry: + print(f"Retrying... (Attempt {step.retry.attempt})") + elif step.type == "error": + print(f"Task error: {step.error}") + + # Get final execution result + result = client.executions.get(execution.id) + print(f"Final result: {result.output}") + + except Exception as e: + print(f"An unexpected error occurred: {str(e)}") + +# Demonstrate error handling for different scenarios +print("1. Division by zero (with retry and fallback):") +execute_task_with_error_handling("divide", 0) + +print("\n2. API call with server error (with retry):") +execute_task_with_error_handling("api_call", 500) + +print("\n3. Data processing error (with logging):") +execute_task_with_error_handling("process_data", "invalid_data") + +print("\n4. Successful operation:") +execute_task_with_error_handling("divide", 4) \ No newline at end of file diff --git a/cookbooks/IDEAS.md b/cookbooks/IDEAS.md new file mode 100644 index 000000000..83d6d58d4 --- /dev/null +++ b/cookbooks/IDEAS.md @@ -0,0 +1,1377 @@ +# Expanded Implementation Scenarios for Julep + +Below are detailed implementation plans for each of the 50 scenarios using Julep's **docs**, **sessions**, **tasks**, and **executions** features. Each scenario includes a complexity rating from **1 (easiest)** to **5 (most complex)**. + +--- + +### 1. Automated Customer Support Agent + +**Implementation Using Julep:** + +- **Docs:** + - Store customer data, FAQs, and troubleshooting guides. + - Integrate CRM documentation for accessing and updating customer information. + +- **Sessions:** + - Create a persistent session for each customer to maintain conversation context. + - Track interaction history to personalize support. + +- **Tasks:** + - Define tasks for handling common inquiries (e.g., order status, billing issues). + - Implement escalation tasks for complex issues that require human intervention. + - Automate ticket creation and update processes. + +- **Executions:** + - Execute tasks based on customer inputs. + - Monitor task executions to ensure timely responses and issue resolutions. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integrating with external CRM systems, handling diverse query types, and maintaining contextual sessions, which increases complexity. + +--- + +### 2. Smart Research Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store access to academic databases and research papers. + - Include summarization templates and research methodologies. + +- **Sessions:** + - Manage user-specific research sessions to track ongoing projects and queries. + - Maintain context for multi-step research tasks. + +- **Tasks:** + - Create tasks for searching databases, summarizing articles, and compiling reports. + - Implement conditional steps based on research findings. + +- **Executions:** + - Execute research tasks sequentially or in parallel. + - Stream execution results to provide real-time updates to the user. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with academic databases, advanced summarization capabilities, and managing complex multi-step workflows. + +--- + +### 3. Personal Finance Manager + +**Implementation Using Julep:** + +- **Docs:** + - Store user financial data, budgeting templates, and investment information. + - Integrate banking API documentation for transaction fetching. + +- **Sessions:** + - Create persistent sessions to track user financial activities over time. + - Maintain context for budgeting goals and financial plans. + +- **Tasks:** + - Define tasks for expense tracking, budget creation, and investment monitoring. + - Automate alerts for budget limits and investment opportunities. + +- **Executions:** + - Execute financial tasks based on user interactions and predefined schedules. + - Monitor executions to provide real-time financial advice and updates. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Needs secure integration with banking APIs, real-time data processing, and robust budgeting logic. + +--- + +### 4. Content Creation Workflow + +**Implementation Using Julep:** + +- **Docs:** + - Store SEO guidelines, content templates, and style guides. + - Include access to keyword research tools. + +- **Sessions:** + - Manage content creation sessions to track progress and drafts. + - Maintain context for ongoing content projects. + +- **Tasks:** + - Create multi-step tasks for topic ideation, content drafting, SEO optimization, and scheduling. + - Integrate tools for grammar checking and SEO analysis. + +- **Executions:** + - Automate the execution of content creation tasks. + - Schedule publishing according to editorial calendars. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves coordinating multiple tools and steps but remains manageable with clear task definitions. + +--- + +### 5. E-commerce Order Processing System + +**Implementation Using Julep:** + +- **Docs:** + - Store product catalogs, inventory data, and order processing guidelines. + - Integrate with shipping provider APIs. + +- **Sessions:** + - Create sessions for each order to track its lifecycle. + - Maintain context for customer preferences and order history. + +- **Tasks:** + - Define tasks for order validation, inventory updates, payment processing, and shipment tracking. + - Automate customer notifications at each stage. + +- **Executions:** + - Execute order processing tasks in sequence. + - Monitor executions to handle exceptions like payment failures or inventory shortages. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires robust integrations with payment gateways, inventory systems, and shipping providers, along with handling various order states. + +--- + +### 6. AI-Powered Personal Trainer + +**Implementation Using Julep:** + +- **Docs:** + - Store workout routines, nutritional plans, and progress tracking templates. + - Include integration details for fitness tracking APIs. + +- **Sessions:** + - Create individual sessions for each user to track their fitness journey. + - Maintain context for user goals and progress. + +- **Tasks:** + - Define tasks for generating personalized workout plans, tracking progress, and adjusting routines. + - Automate reminders and motivational messages. + +- **Executions:** + - Execute fitness tasks based on user inputs and scheduled routines. + - Monitor executions to provide real-time feedback and adjustments. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves personalization and integration with fitness data sources, but achievable with well-defined task workflows. + +--- + +### 7. Automated Email Marketing Campaigns + +**Implementation Using Julep:** + +- **Docs:** + - Store email templates, segmentation criteria, and campaign schedules. + - Integrate with email marketing platforms (e.g., SendGrid, Mailchimp). + +- **Sessions:** + - Manage campaign-specific sessions to track interactions and responses. + - Maintain context for ongoing and past campaigns. + +- **Tasks:** + - Create tasks for email creation, scheduling, sending, and performance analysis. + - Automate A/B testing and content personalization. + +- **Executions:** + - Execute email campaigns based on predefined schedules and triggers. + - Monitor execution performance and adjust strategies accordingly. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with email platforms and managing dynamic content delivery, but is straightforward with clear task definitions. + +--- + +### 8. Intelligent Recruitment Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store job descriptions, candidate profiles, and evaluation criteria. + - Integrate with HR systems and job boards. + +- **Sessions:** + - Create sessions for each recruitment process to track candidate interactions. + - Maintain context for candidate status and feedback. + +- **Tasks:** + - Define tasks for resume screening, interview scheduling, and candidate communications. + - Automate feedback collection and report generation. + +- **Executions:** + - Execute recruitment tasks based on candidate actions and application stages. + - Monitor executions to ensure timely processing and compliance. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves complex integrations with HR systems, handling diverse candidate data, and ensuring compliance with recruitment processes. + +--- + +### 9. Smart Home Automation Controller + +**Implementation Using Julep:** + +- **Docs:** + - Store device configurations, automation rules, and user preferences. + - Integrate with smart home device APIs (e.g., Philips Hue, Nest). + +- **Sessions:** + - Manage user-specific sessions to track home automation settings. + - Maintain context for user routines and preferences. + +- **Tasks:** + - Create tasks for device control, routine scheduling, and energy monitoring. + - Automate actions based on triggers like time, occupancy, or environmental changes. + +- **Executions:** + - Execute home automation tasks in real-time or based on schedules. + - Monitor executions to ensure devices respond correctly and adjust settings as needed. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with multiple smart devices and managing dynamic automation rules, increasing system complexity. + +--- + +### 10. Automated Legal Document Analyzer + +**Implementation Using Julep:** + +- **Docs:** + - Store legal templates, compliance guidelines, and case studies. + - Integrate with legal databases and document repositories. + +- **Sessions:** + - Create sessions for each document analysis to track progress and findings. + - Maintain context for specific legal requirements and clauses. + +- **Tasks:** + - Define tasks for document ingestion, key information extraction, compliance checking, and summarization. + - Automate flagging of non-compliant sections and suggest necessary amendments. + +- **Executions:** + - Execute document analysis tasks sequentially or in parallel. + - Monitor executions to ensure accuracy and compliance with legal standards. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves advanced natural language processing, integration with legal databases, and ensuring compliance with intricate legal standards. + +--- + +### 11. Personalized Learning Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store educational content, learning paths, and assessment criteria. + - Integrate with educational platforms and resources. + +- **Sessions:** + - Create individual learning sessions to track user progress and preferences. + - Maintain context for personalized learning paths and goals. + +- **Tasks:** + - Define tasks for content recommendation, quiz generation, progress tracking, and feedback provision. + - Automate adjustments to learning paths based on performance. + +- **Executions:** + - Execute learning tasks based on user interactions and progress. + - Monitor executions to provide real-time feedback and adjust learning strategies. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires personalization algorithms, integration with educational content sources, and dynamic adaptation to user progress. + +--- + +### 12. AI-Driven Social Media Manager + +**Implementation Using Julep:** + +- **Docs:** + - Store social media strategies, content calendars, and engagement guidelines. + - Integrate with social media APIs (e.g., Twitter, Facebook, LinkedIn). + +- **Sessions:** + - Manage campaign-specific sessions to track posts, engagements, and analytics. + - Maintain context for ongoing and scheduled campaigns. + +- **Tasks:** + - Create tasks for content creation, scheduling, posting, and performance analysis. + - Automate engagement responses and A/B testing of content. + +- **Executions:** + - Execute social media tasks based on schedules and real-time engagement triggers. + - Monitor executions to optimize performance and adjust strategies. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with multiple social media platforms, dynamic content management, and real-time engagement handling. + +--- + +### 13. Automated Travel Itinerary Planner + +**Implementation Using Julep:** + +- **Docs:** + - Store travel guides, destination information, and booking APIs. + - Integrate with flight, hotel, and transportation service APIs. + +- **Sessions:** + - Create travel-specific sessions to track itinerary progress and user preferences. + - Maintain context for personalized travel plans and updates. + +- **Tasks:** + - Define tasks for destination research, booking accommodations and transportation, and itinerary scheduling. + - Automate real-time updates and notifications during trips. + +- **Executions:** + - Execute travel planning tasks based on user inputs and predefined schedules. + - Monitor executions to handle changes and provide timely updates. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with travel service APIs and managing dynamic itinerary changes, which adds moderate complexity. + +--- + +### 14. AI-Powered Inventory Management System + +**Implementation Using Julep:** + +- **Docs:** + - Store inventory data, supplier information, and reordering guidelines. + - Integrate with inventory tracking systems and supplier APIs. + +- **Sessions:** + - Manage inventory sessions to monitor stock levels and reorder statuses. + - Maintain context for inventory forecasts and demand trends. + +- **Tasks:** + - Create tasks for stock monitoring, demand forecasting, automatic reordering, and supplier communication. + - Automate alerts for low stock levels and order confirmations. + +- **Executions:** + - Execute inventory management tasks in real-time or based on schedules. + - Monitor executions to ensure accurate stock levels and timely reorders. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires real-time inventory tracking, predictive analytics for demand forecasting, and reliable integration with supplier systems. + +--- + +### 15. Intelligent Health Monitoring System + +**Implementation Using Julep:** + +- **Docs:** + - Store health metrics templates, medical guidelines, and user health data. + - Integrate with health tracking devices and APIs (e.g., Fitbit, Apple Health). + +- **Sessions:** + - Create sessions for each user to track their health metrics and progress. + - Maintain context for personalized health goals and alerts. + +- **Tasks:** + - Define tasks for data collection, health metric analysis, trend monitoring, and alert notifications. + - Automate health insights and recommendations based on data. + +- **Executions:** + - Execute health monitoring tasks continuously or at scheduled intervals. + - Monitor executions to provide real-time health alerts and advice. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with diverse health tracking devices, real-time data processing, and ensuring data privacy and accuracy. + +--- + +### 16. Automated Content Moderation Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store community guidelines, content policies, and moderation rules. + - Integrate with content platforms (e.g., forums, social media). + +- **Sessions:** + - Manage moderation sessions to track content reviews and decisions. + - Maintain context for specific moderation cases and user histories. + +- **Tasks:** + - Create tasks for content ingestion, automated screening, manual review, and action enforcement. + - Automate flagging of inappropriate content and notifying users of violations. + +- **Executions:** + - Execute content moderation tasks in real-time or batch processing. + - Monitor executions to ensure compliance and handle escalations. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves sophisticated content analysis, balancing automation with manual oversight, and ensuring adherence to diverse content policies. + +--- + +### 17. AI-Powered Resume Builder + +**Implementation Using Julep:** + +- **Docs:** + - Store resume templates, industry-specific keywords, and formatting guidelines. + - Integrate with LinkedIn and other professional platforms for data fetching. + +- **Sessions:** + - Create user-specific sessions to track resume building progress. + - Maintain context for personalized content and formatting preferences. + +- **Tasks:** + - Define tasks for data collection, content suggestion, resume formatting, and final export. + - Automate style checks and consistency validations. + +- **Executions:** + - Execute resume building tasks based on user inputs and selections. + - Monitor executions to provide real-time feedback and suggestions. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with professional data sources and implementing dynamic content generation and formatting. + +--- + +### 18. Smart Event Management System + +**Implementation Using Julep:** + +- **Docs:** + - Store event templates, scheduling guidelines, and registration forms. + - Integrate with calendar and email platforms. + +- **Sessions:** + - Manage event-specific sessions to track registrations, schedules, and attendee interactions. + - Maintain context for event updates and follow-ups. + +- **Tasks:** + - Create tasks for event creation, attendee registration, schedule management, and post-event follow-ups. + - Automate reminders, notifications, and feedback collection. + +- **Executions:** + - Execute event management tasks based on schedules and attendee actions. + - Monitor executions to handle registrations and event logistics seamlessly. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves coordinating multiple aspects of event planning, handling real-time registrations, and ensuring smooth execution logistics. + +--- + +### 19. Automated Survey Analyzer + +**Implementation Using Julep:** + +- **Docs:** + - Store survey templates, question types, and analysis methodologies. + - Integrate with survey distribution platforms (e.g., SurveyMonkey, Google Forms). + +- **Sessions:** + - Create sessions for each survey to track responses and analysis progress. + - Maintain context for specific survey objectives and parameters. + +- **Tasks:** + - Define tasks for survey distribution, data collection, sentiment analysis, and report generation. + - Automate data visualization and trend identification. + +- **Executions:** + - Execute survey analysis tasks upon survey completion. + - Monitor executions to provide timely and accurate insights. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with survey platforms and implementing effective data analysis and visualization techniques. + +--- + +### 20. AI-Driven Project Management Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store project templates, task guidelines, and progress tracking tools. + - Integrate with project management platforms (e.g., Jira, Trello). + +- **Sessions:** + - Manage project-specific sessions to track tasks, milestones, and team interactions. + - Maintain context for project goals and progress updates. + +- **Tasks:** + - Create tasks for task breakdown, assignment, progress tracking, and status reporting. + - Automate notifications for deadlines and task completions. + +- **Executions:** + - Execute project management tasks based on project timelines and team inputs. + - Monitor executions to ensure projects stay on track and within scope. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with diverse project management tools, handling dynamic task assignments, and ensuring effective progress tracking. + +--- + +### 21. Intelligent Document Summarizer + +**Implementation Using Julep:** + +- **Docs:** + - Store access to large documents, research papers, and reports. + - Include summarization algorithms and templates. + +- **Sessions:** + - Create sessions for each document summarization task. + - Maintain context for document sections and summarization preferences. + +- **Tasks:** + - Define tasks for document ingestion, key point extraction, and summary generation. + - Automate quality checks and user-specific summary adjustments. + +- **Executions:** + - Execute document summarization tasks efficiently. + - Monitor executions to ensure accurate and concise summaries. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires advanced natural language processing capabilities and efficient handling of large document data. + +--- + +### 22. Automated Feedback Collection and Analysis + +**Implementation Using Julep:** + +- **Docs:** + - Store feedback forms, analysis templates, and reporting guidelines. + - Integrate with feedback collection platforms (e.g., Typeform, Google Forms). + +- **Sessions:** + - Manage feedback-specific sessions to track responses and analysis progress. + - Maintain context for feedback sources and analysis objectives. + +- **Tasks:** + - Create tasks for feedback distribution, data collection, sentiment analysis, and insight generation. + - Automate categorization and prioritization of feedback. + +- **Executions:** + - Execute feedback analysis tasks promptly upon data collection. + - Monitor executions to provide actionable insights and improvement strategies. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integrating with feedback platforms and implementing effective sentiment analysis and categorization. + +--- + +### 23. AI-Powered Language Translator + +**Implementation Using Julep:** + +- **Docs:** + - Store language dictionaries, translation models, and formatting guidelines. + - Integrate with translation APIs (e.g., Google Translate, DeepL). + +- **Sessions:** + - Create translation-specific sessions to track user preferences and translation history. + - Maintain context for ongoing translation projects. + +- **Tasks:** + - Define tasks for text ingestion, language detection, translation processing, and quality assurance. + - Automate post-translation formatting and localization adjustments. + +- **Executions:** + - Execute translation tasks in real-time or batch mode. + - Monitor executions to ensure accuracy and contextual relevance. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with robust translation APIs and handling nuances of different languages and contexts. + +--- + +### 24. Smart Appointment Scheduler + +**Implementation Using Julep:** + +- **Docs:** + - Store scheduling templates, availability guidelines, and notification templates. + - Integrate with calendar platforms (e.g., Google Calendar, Outlook). + +- **Sessions:** + - Manage appointment-specific sessions to track scheduling progress and attendee interactions. + - Maintain context for user availability and preferences. + +- **Tasks:** + - Create tasks for availability checking, meeting scheduling, sending reminders, and handling cancellations. + - Automate conflict detection and resolution. + +- **Executions:** + - Execute scheduling tasks based on user inputs and calendar data. + - Monitor executions to ensure appointments are set correctly and notifications are sent. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integration with calendar systems and implementing conflict resolution logic, which adds moderate complexity. + +--- + +### 25. Automated Inventory Auditor + +**Implementation Using Julep:** + +- **Docs:** + - Store inventory audit templates, reconciliation guidelines, and reporting formats. + - Integrate with inventory management systems and databases. + +- **Sessions:** + - Create auditing sessions to track audit schedules and findings. + - Maintain context for different inventory categories and audit criteria. + +- **Tasks:** + - Define tasks for data extraction, discrepancy detection, reconciliation processes, and report generation. + - Automate audit scheduling and notification of audit results. + +- **Executions:** + - Execute inventory audit tasks periodically or on-demand. + - Monitor executions to ensure accurate and timely audits. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires reliable data integration and robust discrepancy detection mechanisms to handle complex inventory data. + +--- + +### 26. AI-Driven Competitive Analysis Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store competitor profiles, market analysis frameworks, and data sources. + - Integrate with market research APIs and competitor websites. + +- **Sessions:** + - Manage competitive analysis sessions to track data collection and analysis progress. + - Maintain context for specific market segments and competitive factors. + +- **Tasks:** + - Create tasks for data scraping, trend analysis, SWOT analysis, and report generation. + - Automate the aggregation and visualization of competitive data. + +- **Executions:** + - Execute competitive analysis tasks on a scheduled basis. + - Monitor executions to provide up-to-date insights and strategic recommendations. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves complex data scraping, accurate trend analysis, and maintaining up-to-date competitive insights, increasing overall complexity. + +--- + +### 27. Smart Recipe Generator + +**Implementation Using Julep:** + +- **Docs:** + - Store ingredient databases, recipe templates, and dietary guidelines. + - Integrate with nutrition APIs and grocery databases. + +- **Sessions:** + - Create user-specific sessions to track dietary preferences and past recipes. + - Maintain context for ingredient availability and nutritional goals. + +- **Tasks:** + - Define tasks for ingredient analysis, recipe generation, nutritional calculation, and grocery list creation. + - Automate recipe suggestions based on user inputs and constraints. + +- **Executions:** + - Execute recipe generation tasks in real-time based on user requests. + - Monitor executions to ensure recipe accuracy and adherence to dietary needs. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with nutrition and grocery APIs and implementing intelligent recipe generation logic. + +--- + +### 28. Automated Video Content Creator + +**Implementation Using Julep:** + +- **Docs:** + - Store video script templates, editing guidelines, and publishing schedules. + - Integrate with video editing and hosting platforms (e.g., Adobe Premiere, YouTube). + +- **Sessions:** + - Manage video creation sessions to track script development, editing stages, and publishing. + - Maintain context for ongoing video projects and collaboration. + +- **Tasks:** + - Create tasks for script generation, video editing, thumbnail creation, and publishing. + - Automate content review and approval workflows. + +- **Executions:** + - Execute video creation tasks based on project timelines. + - Monitor executions to ensure timely releases and quality standards. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with multiple video tools, managing creative workflows, and ensuring high-quality content production. + +--- + +### 29. AI-Powered News Aggregator + +**Implementation Using Julep:** + +- **Docs:** + - Store news source lists, categorization templates, and summarization guidelines. + - Integrate with news APIs (e.g., NewsAPI, RSS feeds). + +- **Sessions:** + - Create user-specific sessions to track news preferences and reading history. + - Maintain context for personalized news feeds and topics of interest. + +- **Tasks:** + - Define tasks for news scraping, categorization, summarization, and personalization. + - Automate feed generation and delivery based on user preferences. + +- **Executions:** + - Execute news aggregation tasks periodically. + - Monitor executions to ensure timely and relevant news delivery. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires efficient news scraping, accurate categorization, and personalized summarization, but is manageable with clear task workflows. + +--- + +### 30. Intelligent Appointment Follow-Up System + +**Implementation Using Julep:** + +- **Docs:** + - Store follow-up templates, feedback forms, and communication guidelines. + - Integrate with CRM and email platforms. + +- **Sessions:** + - Manage follow-up sessions to track appointments and subsequent communications. + - Maintain context for previous interactions and follow-up actions. + +- **Tasks:** + - Create tasks for sending follow-up emails, collecting feedback, and scheduling future appointments. + - Automate reminder notifications and feedback analysis. + +- **Executions:** + - Execute follow-up tasks based on appointment completions. + - Monitor executions to ensure timely and effective communications. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integration with CRM systems and implementing automated communication workflows, adding moderate complexity. + +--- + +### 31. Automated Compliance Monitoring Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store regulatory guidelines, compliance checklists, and reporting templates. + - Integrate with internal systems and regulatory databases. + +- **Sessions:** + - Create compliance-specific sessions to track monitoring activities and audit trails. + - Maintain context for various compliance standards and organizational policies. + +- **Tasks:** + - Define tasks for continuous monitoring, policy enforcement, and compliance reporting. + - Automate detection of non-compliant activities and trigger corrective actions. + +- **Executions:** + - Execute compliance monitoring tasks in real-time. + - Monitor executions to ensure ongoing adherence to regulations and standards. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Requires comprehensive integration with organizational systems, robust monitoring mechanisms, and ensuring adherence to multifaceted regulatory requirements. + +--- + +### 32. AI-Powered Personal Shopper + +**Implementation Using Julep:** + +- **Docs:** + - Store product catalogs, user preference data, and recommendation algorithms. + - Integrate with e-commerce APIs (e.g., Amazon, Shopify). + +- **Sessions:** + - Manage shopping sessions to track user preferences and purchase history. + - Maintain context for personalized product recommendations. + +- **Tasks:** + - Create tasks for product suggestion, wishlist management, and deal notifications. + - Automate price comparisons and availability checks. + +- **Executions:** + - Execute personal shopping tasks based on user inputs and behavior. + - Monitor executions to provide timely recommendations and alerts. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with multiple e-commerce platforms, implementing personalized recommendation logic, and handling real-time deal tracking. + +--- + +### 33. Smart Content Personalization Engine + +**Implementation Using Julep:** + +- **Docs:** + - Store content variants, personalization rules, and user segmentation data. + - Integrate with website CMS and analytics platforms. + +- **Sessions:** + - Create user-specific sessions to track interactions and preferences. + - Maintain context for personalized content delivery. + +- **Tasks:** + - Define tasks for content analysis, user behavior tracking, and personalized content delivery. + - Automate A/B testing and content optimization based on performance metrics. + +- **Executions:** + - Execute content personalization tasks in real-time. + - Monitor executions to adjust personalization strategies dynamically. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires real-time user behavior tracking, dynamic content delivery, and continuous optimization based on analytics, increasing system complexity. + +--- + +### 34. Automated Debt Collection Agent + +**Implementation Using Julep:** + +- **Docs:** + - Store debt agreements, payment schedules, and communication templates. + - Integrate with financial systems and payment gateways. + +- **Sessions:** + - Manage debt collection sessions to track debtor interactions and payment statuses. + - Maintain context for individual debtors and their payment histories. + +- **Tasks:** + - Create tasks for sending payment reminders, negotiating payment plans, and issuing notifications. + - Automate follow-ups and escalation procedures for delinquent accounts. + +- **Executions:** + - Execute debt collection tasks based on payment statuses and schedules. + - Monitor executions to ensure effective communication and resolution. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves sensitive financial data handling, integration with payment systems, and implementing automated negotiation workflows. + +--- + +### 35. AI-Driven Talent Matching System + +**Implementation Using Julep:** + +- **Docs:** + - Store job descriptions, candidate profiles, and matching criteria. + - Integrate with job boards and professional networking platforms. + +- **Sessions:** + - Create sessions for each matching process to track candidate-job pairings. + - Maintain context for specific job requirements and candidate qualifications. + +- **Tasks:** + - Define tasks for candidate screening, skills matching, and recommendation generation. + - Automate notifications to both candidates and employers regarding match statuses. + +- **Executions:** + - Execute talent matching tasks based on incoming job postings and candidate applications. + - Monitor executions to ensure accurate and timely matches. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Requires sophisticated matching algorithms, integration with diverse data sources, and handling dynamic job and candidate data. + +--- + +### 36. Intelligent Expense Reporting Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store expense categories, reimbursement policies, and reporting templates. + - Integrate with financial systems and expense tracking APIs. + +- **Sessions:** + - Manage expense reporting sessions to track submissions and approvals. + - Maintain context for individual employee expenses and budget limits. + +- **Tasks:** + - Create tasks for expense submission, approval workflows, and reimbursement processing. + - Automate validation checks and compliance with policies. + +- **Executions:** + - Execute expense reporting tasks based on submission triggers and approval workflows. + - Monitor executions to ensure timely reimbursements and policy adherence. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with financial systems, implementing approval workflows, and ensuring compliance with expense policies. + +--- + +### 37. Automated Meeting Minutes Recorder + +**Implementation Using Julep:** + +- **Docs:** + - Store meeting agendas, transcription templates, and summary guidelines. + - Integrate with audio transcription services (e.g., Otter.ai, Google Speech-to-Text). + +- **Sessions:** + - Create meeting-specific sessions to track transcription and summarization progress. + - Maintain context for meeting topics and participant interactions. + +- **Tasks:** + - Define tasks for audio ingestion, transcription, summary generation, and distribution. + - Automate the extraction of action items and key decisions. + +- **Executions:** + - Execute transcription and summarization tasks in real-time or post-meeting. + - Monitor executions to ensure accurate recordings and timely distribution. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires reliable audio transcription integration and effective summarization techniques, but manageable with clear task definitions. + +--- + +### 38. AI-Driven Content Recommendation System + +**Implementation Using Julep:** + +- **Docs:** + - Store user profiles, content metadata, and recommendation algorithms. + - Integrate with content management systems and user behavior analytics. + +- **Sessions:** + - Manage user-specific sessions to track interactions and preference changes. + - Maintain context for personalized content delivery. + +- **Tasks:** + - Define tasks for content analysis, user behavior tracking, and recommendation generation. + - Automate personalization based on real-time user interactions. + +- **Executions:** + - Execute content recommendation tasks in real-time. + - Monitor executions to refine recommendation accuracy and relevance. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves real-time data processing, advanced recommendation algorithms, and integration with multiple content sources. + +--- + +### 39. Smart Time Tracking Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store time tracking templates, productivity guidelines, and reporting formats. + - Integrate with productivity tools (e.g., Toggl, Clockify). + +- **Sessions:** + - Create user-specific sessions to track time spent on tasks and projects. + - Maintain context for task prioritization and productivity goals. + +- **Tasks:** + - Define tasks for time logging, productivity analysis, and report generation. + - Automate reminders for time tracking and productivity tips based on usage patterns. + +- **Executions:** + - Execute time tracking tasks continuously or based on user actions. + - Monitor executions to provide real-time productivity insights and suggestions. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with time tracking tools and implementing effective productivity analysis logic. + +--- + +### 40. Automated Webinar Hosting Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store webinar schedules, registration forms, and hosting guidelines. + - Integrate with webinar platforms (e.g., Zoom, WebinarJam). + +- **Sessions:** + - Manage webinar-specific sessions to track registrations, attendee interactions, and follow-ups. + - Maintain context for webinar topics and participant engagement. + +- **Tasks:** + - Create tasks for webinar scheduling, participant management, live interactions, and post-webinar follow-ups. + - Automate reminders, thank-you emails, and feedback collection. + +- **Executions:** + - Execute webinar hosting tasks based on schedules and participant actions. + - Monitor executions to ensure smooth webinar operations and effective follow-ups. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with webinar platforms, managing live interactions, and handling post-event processes seamlessly. + +--- + +### 41. AI-Powered Inventory Forecasting Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store sales data, forecasting models, and inventory guidelines. + - Integrate with sales and inventory tracking systems. + +- **Sessions:** + - Create forecasting sessions to track sales trends and inventory predictions. + - Maintain context for seasonal factors and market conditions affecting inventory. + +- **Tasks:** + - Define tasks for data collection, trend analysis, prediction model execution, and report generation. + - Automate alerts for predicted stock shortages or surpluses. + +- **Executions:** + - Execute forecasting tasks periodically based on sales data updates. + - Monitor executions to refine prediction accuracy and adjust inventory strategies. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires advanced predictive analytics, integration with sales systems, and handling dynamic market conditions influencing inventory. + +--- + +### 42. Smart Contract Management System + +**Implementation Using Julep:** + +- **Docs:** + - Store smart contract templates, execution guidelines, and compliance rules. + - Integrate with blockchain platforms (e.g., Ethereum, Hyperledger). + +- **Sessions:** + - Manage contract-specific sessions to track creation, execution, and monitoring. + - Maintain context for contract terms and participant interactions. + +- **Tasks:** + - Create tasks for contract creation, deployment, execution monitoring, and compliance checks. + - Automate notifications for contract milestones and compliance alerts. + +- **Executions:** + - Execute smart contract tasks based on blockchain events and predefined triggers. + - Monitor executions to ensure contract integrity and compliance. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves blockchain integration, ensuring smart contract security, and managing complex execution and compliance workflows. + +--- + +### 43. Automated Knowledge Base Updater + +**Implementation Using Julep:** + +- **Docs:** + - Store knowledge base articles, update guidelines, and categorization rules. + - Integrate with content management systems and information sources. + +- **Sessions:** + - Create knowledge base sessions to track updates, revisions, and user queries. + - Maintain context for content accuracy and relevance. + +- **Tasks:** + - Define tasks for content ingestion, information extraction, categorization, and publishing. + - Automate periodic reviews and updates based on new information sources. + +- **Executions:** + - Execute knowledge base update tasks as new content becomes available. + - Monitor executions to ensure timely and accurate information updates. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires efficient content ingestion, accurate information extraction, and seamless integration with knowledge management systems. + +--- + +### 44. AI-Driven Fraud Detection System + +**Implementation Using Julep:** + +- **Docs:** + - Store fraud detection algorithms, monitoring guidelines, and incident response protocols. + - Integrate with financial transaction systems and security APIs. + +- **Sessions:** + - Manage fraud detection sessions to track suspicious activities and investigations. + - Maintain context for user behavior patterns and anomaly detection. + +- **Tasks:** + - Create tasks for real-time transaction monitoring, anomaly detection, incident logging, and alerting. + - Automate response actions like freezing accounts or notifying security teams. + +- **Executions:** + - Execute fraud detection tasks continuously based on transaction flows. + - Monitor executions to ensure timely detection and response to fraudulent activities. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves real-time data processing, sophisticated anomaly detection algorithms, and ensuring robust security measures. + +--- + +### 45. Intelligent Personal Diary Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store diary templates, emotional analysis guidelines, and reflection prompts. + - Integrate with sentiment analysis APIs. + +- **Sessions:** + - Create user-specific sessions to track daily entries and emotional states. + - Maintain context for personal growth and mood trends. + +- **Tasks:** + - Define tasks for daily entry prompts, sentiment analysis, and insight generation. + - Automate privacy controls and data encryption for secure diary storage. + +- **Executions:** + - Execute diary assistant tasks daily based on user inputs. + - Monitor executions to provide personalized insights and growth tracking. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with sentiment analysis tools and ensuring secure data handling, but manageable with well-defined workflows. + +--- + +### 46. Automated Language Learning Tutor + +**Implementation Using Julep:** + +- **Docs:** + - Store language lessons, exercise templates, and feedback guidelines. + - Integrate with language processing APIs and educational resources. + +- **Sessions:** + - Manage learning sessions to track user progress and performance. + - Maintain context for personalized lesson plans and feedback. + +- **Tasks:** + - Create tasks for lesson delivery, exercise generation, progress tracking, and feedback provision. + - Automate adaptive learning paths based on user performance. + +- **Executions:** + - Execute language learning tasks based on user interactions and learning schedules. + - Monitor executions to adjust learning strategies and provide real-time feedback. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves adaptive learning algorithms, integration with language processing tools, and personalized content delivery. + +--- + +### 47. AI-Powered Budgeting Tool for Businesses + +**Implementation Using Julep:** + +- **Docs:** + - Store budgeting templates, financial guidelines, and reporting formats. + - Integrate with accounting systems and financial data sources. + +- **Sessions:** + - Create budgeting sessions to track financial planning and expenditure. + - Maintain context for organizational financial goals and constraints. + +- **Tasks:** + - Define tasks for budget creation, expenditure tracking, financial forecasting, and report generation. + - Automate alerts for budget overruns and financial goal assessments. + +- **Executions:** + - Execute budgeting tasks based on financial data updates and planning cycles. + - Monitor executions to ensure accurate financial tracking and reporting. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with accounting systems, accurate financial forecasting, and robust budgeting logic to handle business complexities. + +--- + +### 48. Smart Compliance Documentation Generator + +**Implementation Using Julep:** + +- **Docs:** + - Store compliance templates, regulatory guidelines, and documentation standards. + - Integrate with regulatory databases and internal policy systems. + +- **Sessions:** + - Manage compliance documentation sessions to track document creation and updates. + - Maintain context for specific regulatory requirements and organizational policies. + +- **Tasks:** + - Create tasks for document generation, compliance checking, format validation, and publishing. + - Automate updates based on regulatory changes and policy revisions. + +- **Executions:** + - Execute compliance documentation tasks as needed or on a schedule. + - Monitor executions to ensure documents meet all compliance standards. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves dynamic document generation, adherence to detailed regulatory standards, and ensuring continuous updates based on regulatory changes. + +--- + +### 49. Automated Product Recommendation Engine + +**Implementation Using Julep:** + +- **Docs:** + - Store product catalogs, user behavior data, and recommendation algorithms. + - Integrate with e-commerce platforms and user analytics tools. + +- **Sessions:** + - Create user-specific sessions to track interactions and preferences. + - Maintain context for personalized recommendation accuracy. + +- **Tasks:** + - Define tasks for data collection, behavior analysis, recommendation generation, and user feedback integration. + - Automate real-time recommendations based on user actions and trends. + +- **Executions:** + - Execute recommendation tasks in real-time to provide instant suggestions. + - Monitor executions to refine algorithms and improve recommendation relevance. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires sophisticated recommendation algorithms, real-time data processing, and continuous refinement based on user feedback. + +--- + +### 50. Intelligent Event Feedback Analyzer + +**Implementation Using Julep:** + +- **Docs:** + - Store feedback forms, analysis templates, and reporting standards. + - Integrate with event platforms and feedback collection tools. + +- **Sessions:** + - Manage feedback-specific sessions to track responses and analysis progress. + - Maintain context for event-specific feedback and improvement areas. + +- **Tasks:** + - Create tasks for feedback collection, sentiment analysis, trend identification, and report generation. + - Automate the extraction of actionable insights and improvement suggestions. + +- **Executions:** + - Execute feedback analysis tasks post-event. + - Monitor executions to ensure accurate and timely feedback processing and reporting. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integrating with feedback collection tools and implementing effective sentiment analysis and trend identification mechanisms. + +--- + +# Complexity and Difficulty Ratings + +The scenarios have been rated based on the number of integrated features, required integrations, and overall system complexity. Here's a quick overview: + +- **★☆☆☆☆ (1/5): Easiest** +- **★★☆☆☆ (2/5): Low Complexity** +- **★★★☆☆ (3/5): Moderate Complexity** +- **★★★★☆ (4/5): High Complexity** +- **★★★★★ (5/5): Most Complex** + +| **Scenario** | **Complexity Rating** | +|---------------------------------------------------|-----------------------| +| 1. Automated Customer Support Agent | ★★★★☆ | +| 2. Smart Research Assistant | ★★★★☆ | +| 3. Personal Finance Manager | ★★★☆☆ | +| 4. Content Creation Workflow | ★★★☆☆ | +| 5. E-commerce Order Processing System | ★★★★☆ | +| 6. AI-Powered Personal Trainer | ★★★☆☆ | +| 7. Automated Email Marketing Campaigns | ★★★☆☆ | +| 8. Intelligent Recruitment Assistant | ★★★★★ | +| 9. Smart Home Automation Controller | ★★★★☆ | +| 10. Automated Legal Document Analyzer | ★★★★★ | +| 11. Personalized Learning Assistant | ★★★★☆ | +| 12. AI-Driven Social Media Manager | ★★★★☆ | +| 13. Automated Travel Itinerary Planner | ★★★☆☆ | +| 14. AI-Powered Inventory Management System | ★★★★☆ | +| 15. Intelligent Health Monitoring System | ★★★★☆ | +| 16. Automated Content Moderation Tool | ★★★★★ | +| 17. AI-Powered Resume Builder | ★★★☆☆ | +| 18. Smart Event Management System | ★★★★☆ | +| 19. Automated Survey Analyzer | ★★★☆☆ | +| 20. AI-Driven Project Management Assistant | ★★★★☆ | +| 21. Intelligent Document Summarizer | ★★★★☆ | +| 22. Automated Feedback Collection and Analysis | ★★★☆☆ | +| 23. AI-Powered Language Translator | ★★★☆☆ | +| 24. Smart Appointment Scheduler | ★★★☆☆ | +| 25. Automated Inventory Auditor | ★★★★☆ | +| 26. AI-Driven Competitive Analysis Tool | ★★★★☆ | +| 27. Smart Recipe Generator | ★★★☆☆ | +| 28. Automated Video Content Creator | ★★★★☆ | +| 29. AI-Powered News Aggregator | ★★★☆☆ | +| 30. Intelligent Appointment Follow-Up System | ★★★☆☆ | +| 31. Automated Compliance Monitoring Tool | ★★★★★ | +| 32. AI-Powered Personal Shopper | ★★★★☆ | +| 33. Smart Content Personalization Engine | ★★★★☆ | +| 34. Automated Debt Collection Agent | ★★★★☆ | +| 35. AI-Driven Talent Matching System | ★★★★★ | +| 36. Intelligent Expense Reporting Tool | ★★★★☆ | +| 37. Automated Meeting Minutes Recorder | ★★★☆☆ | +| 38. AI-Driven Content Recommendation System | ★★★★☆ | +| 39. Smart Time Tracking Assistant | ★★★☆☆ | +| 40. Automated Webinar Hosting Assistant | ★★★★☆ | +| 41. AI-Powered Inventory Forecasting Tool | ★★★★☆ | +| 42. Smart Contract Management System | ★★★★★ | +| 43. Automated Knowledge Base Updater | ★★★★☆ | +| 44. AI-Driven Fraud Detection System | ★★★★★ | +| 45. Intelligent Personal Diary Assistant | ★★★☆☆ | +| 46. Automated Language Learning Tutor | ★★★★☆ | +| 47. AI-Powered Budgeting Tool for Businesses | ★★★★☆ | +| 48. Smart Compliance Documentation Generator | ★★★★☆ | +| 49. Automated Product Recommendation Engine | ★★★★☆ | +| 50. Intelligent Event Feedback Analyzer | ★★★☆☆ | + +--- + +# Conclusion + +These 50 scenarios showcase the versatility and power of Julep's **docs**, **sessions**, **tasks**, and **executions** features in automating and enhancing various business and personal workflows. Depending on your specific needs and available integrations, these scenarios can be tailored to create efficient, intelligent, and scalable solutions. + +Feel free to explore these scenarios, adapt them to your use cases, and contribute to expanding Julep's capabilities further! \ No newline at end of file diff --git a/cookbooks/README.md b/cookbooks/README.md index e7a6bfa89..7af36aff6 100644 --- a/cookbooks/README.md +++ b/cookbooks/README.md @@ -23,7 +23,6 @@ Each notebook explores a unique use case, demonstrating different aspects of Jul | `11-Advanced_Chat_Interactions.ipynb` | [Colab Link](https://colab.research.google.com/github/julep-ai/julep/blob/dev/cookbooks/11-Advanced_Chat_Interactions.ipynb) | Covers advanced chat features and context handling. | No | | `12-Monitoring_Task_Executions.ipynb` | [Colab Link](https://colab.research.google.com/github/julep-ai/julep/blob/dev/cookbooks/12-Monitoring_Task_Executions.ipynb) | Shows how to monitor and manage task executions. | No | | `13-Error_Handling_and_Recovery.ipynb` | [Colab Link](https://colab.research.google.com/github/julep-ai/julep/blob/dev/cookbooks/13-Error_Handling_and_Recovery.ipynb) | Demonstrates implementing error handling and recovery in tasks. | No | -| `14-API_Versioning_and_Configurations.ipynb` | [Colab Link](https://colab.research.google.com/github/julep-ai/julep/blob/dev/cookbooks/14-API_Versioning_and_Configurations.ipynb) | Explores API versioning and server configuration options. | No | ## Potential Cookbooks for Contributors @@ -134,15 +133,9 @@ These notebooks showcase various features of Julep. Here's an overview of the ke - Streaming execution progress - Monitoring task lifecycle -9. **API Versioning** - - Support for different API versions - -10. **Authentication** +9. **Authentication** - API Key authentication -11. **Server Configuration** - - Configurable server environments - We encourage contributors to create new notebooks that demonstrate these features in various combinations and use cases. ### Additional Information diff --git a/sdks/node-sdk b/sdks/node-sdk index 1317978f9..2685cfe51 160000 --- a/sdks/node-sdk +++ b/sdks/node-sdk @@ -1 +1 @@ -Subproject commit 1317978f98661b5ae5b23d9c47a0a8d18f6f5718 +Subproject commit 2685cfe512d6b2907e6bdd1b3294175e20aece99 diff --git a/sdks/python-sdk b/sdks/python-sdk index 1b8c9fc9c..aaa88a204 160000 --- a/sdks/python-sdk +++ b/sdks/python-sdk @@ -1 +1 @@ -Subproject commit 1b8c9fc9c7b1fd2dc5eb60bbc908283bce99a1b2 +Subproject commit aaa88a204bb85b7903f79b8fb5cca0c3e6882c73 From 282896257a798ead2755f76fab549c00f2f50922 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 04:46:19 +0530 Subject: [PATCH 04/23] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 37baacbc6..801da2a7c 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,8 @@ main: > [!TIP] > Julep is really useful when you want to build AI agents that can maintain context and state over long-term interactions. It's great for designing complex, multi-step workflows and integrating various tools and APIs directly into your agent's processes. - +> +> Imagine you want to build an AI agent that can do more than just answer simple queries—it needs to handle complex tasks, remember past interactions, and maybe even integrate with other tools or APIs. That's where Julep comes in. ## Key Features @@ -750,4 +751,4 @@ Explore our comprehensive API documentation to learn more about agents, tasks, a - [Agents API](https://api.julep.ai/api/docs#tag/agents) - [Tasks API](https://api.julep.ai/api/docs#tag/tasks) -- [Executions API](https://api.julep.ai/api/docs#tag/executions) \ No newline at end of file +- [Executions API](https://api.julep.ai/api/docs#tag/executions) From c9883f7b3ad1d109efb265aeda543e75ba8a2b3c Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 04:46:49 +0530 Subject: [PATCH 05/23] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 801da2a7c..fa10d20b2 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,6 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓 Julep is a platform for creating AI agents that maintain state and execute complex workflows. It offers long-term context and orchestrates multi-step tasks. -Imagine you want to build an AI agent that can do more than just answer simple queries—it needs to handle complex tasks, remember past interactions, and maybe even integrate with other tools or APIs. That's where Julep comes in. - Julep lets you define multi-step tasks that can include conditional logic, loops, parallel processing, and built-in integration with 100s of external tools and APIs. Typically AI applications tend to be linear and have simple chains of a handful of prompts and API calls without much branching or decision-making. Imagine a Research AI agent that can do the following: From 8b9b65ada9969e709a1f97da4636dec2d2c97e1e Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 04:48:58 +0530 Subject: [PATCH 06/23] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fa10d20b2..cca058021 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓
-## Quick Intro +## Introduction @@ -88,6 +88,9 @@ Julep is a platform for creating AI agents that maintain state and execute compl Julep lets you define multi-step tasks that can include conditional logic, loops, parallel processing, and built-in integration with 100s of external tools and APIs. Typically AI applications tend to be linear and have simple chains of a handful of prompts and API calls without much branching or decision-making. + +## Quick Example + Imagine a Research AI agent that can do the following: 1. Take a topic, 2. Come up with 100 search queries for that topic, From bb90f95db300b095eee7669896704c8e02a3988a Mon Sep 17 00:00:00 2001 From: creatorrr Date: Sun, 6 Oct 2024 23:19:12 +0000 Subject: [PATCH 07/23] chore(docs): update TOC --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cca058021..d4f5bd4ba 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,8 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓
📖 Table of Contents -- [Quick Intro](#quick-intro) +- [Introduction](#introduction) +- [Quick Example](#quick-example) - [Key Features](#key-features) - [Why Julep vs. LangChain?](#why-julep-vs-langchain) - [Installation](#installation) From a6ca52826d41c967d34cb34adc8844026401c37b Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 04:51:41 +0530 Subject: [PATCH 08/23] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d4f5bd4ba..187f88702 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,8 @@ Julep is a platform for creating AI agents that maintain state and execute compl Julep lets you define multi-step tasks that can include conditional logic, loops, parallel processing, and built-in integration with 100s of external tools and APIs. Typically AI applications tend to be linear and have simple chains of a handful of prompts and API calls without much branching or decision-making. +> [!TIP] +> Imagine you want to build an AI agent that can do more than just answer simple queries—it needs to handle complex tasks, remember past interactions, and maybe even integrate with other tools or APIs. That's where Julep comes in. ## Quick Example @@ -211,8 +213,6 @@ main: > [!TIP] > Julep is really useful when you want to build AI agents that can maintain context and state over long-term interactions. It's great for designing complex, multi-step workflows and integrating various tools and APIs directly into your agent's processes. -> -> Imagine you want to build an AI agent that can do more than just answer simple queries—it needs to handle complex tasks, remember past interactions, and maybe even integrate with other tools or APIs. That's where Julep comes in. ## Key Features From 0de4c0256e6dcdedc982614b5a455c0d3eeaccac Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 04:53:13 +0530 Subject: [PATCH 09/23] Update and rename doctoc-on-dev-push.yml to doctoc-on-push.yml --- .../workflows/{doctoc-on-dev-push.yml => doctoc-on-push.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{doctoc-on-dev-push.yml => doctoc-on-push.yml} (90%) diff --git a/.github/workflows/doctoc-on-dev-push.yml b/.github/workflows/doctoc-on-push.yml similarity index 90% rename from .github/workflows/doctoc-on-dev-push.yml rename to .github/workflows/doctoc-on-push.yml index f70807245..d28821895 100644 --- a/.github/workflows/doctoc-on-dev-push.yml +++ b/.github/workflows/doctoc-on-push.yml @@ -9,7 +9,7 @@ jobs: - uses: technote-space/toc-generator@v4 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAX_HEADER_LEVEL: 2 + MAX_HEADER_LEVEL: 3 TOC_TITLE: '📖 Table of Contents' FOLDING: true From a0a296c5da6d60e85ed155da66b693db118534a6 Mon Sep 17 00:00:00 2001 From: creatorrr Date: Sun, 6 Oct 2024 23:23:24 +0000 Subject: [PATCH 10/23] chore(docs): update TOC --- README-CN.md | 16 ++++++++++++++++ README-JP.md | 16 ++++++++++++++++ README.md | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/README-CN.md b/README-CN.md index 55ea307ca..abac03f01 100644 --- a/README-CN.md +++ b/README-CN.md @@ -68,9 +68,25 @@ - [特性](#%E7%89%B9%E6%80%A7) - [安装](#%E5%AE%89%E8%A3%85) - [快速入门指南](#%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97) + - [步骤 1:导入 Julep](#%E6%AD%A5%E9%AA%A4-1%E5%AF%BC%E5%85%A5-julep) + - [步骤 2:初始化代理](#%E6%AD%A5%E9%AA%A4-2%E5%88%9D%E5%A7%8B%E5%8C%96%E4%BB%A3%E7%90%86) + - [步骤 3:与代理聊天](#%E6%AD%A5%E9%AA%A4-3%E4%B8%8E%E4%BB%A3%E7%90%86%E8%81%8A%E5%A4%A9) + - [步骤 4:创建多步骤任务](#%E6%AD%A5%E9%AA%A4-4%E5%88%9B%E5%BB%BA%E5%A4%9A%E6%AD%A5%E9%AA%A4%E4%BB%BB%E5%8A%A1) + - [步骤 5:执行任务](#%E6%AD%A5%E9%AA%A4-5%E6%89%A7%E8%A1%8C%E4%BB%BB%E5%8A%A1) - [概念](#%E6%A6%82%E5%BF%B5) + - [代理](#%E4%BB%A3%E7%90%86) + - [用户](#%E7%94%A8%E6%88%B7) + - [会话](#%E4%BC%9A%E8%AF%9D) + - [任务](#%E4%BB%BB%E5%8A%A1) + - [工具](#%E5%B7%A5%E5%85%B7) + - [文档](#%E6%96%87%E6%A1%A3) + - [执行](#%E6%89%A7%E8%A1%8C) - [理解任务](#%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%B1%BB%E5%9E%8B) - [高级功能](#%E9%AB%98%E7%BA%A7%E5%8A%9F%E8%83%BD) + - [为代理添加工具](#%E4%B8%BA%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%E5%92%8C%E6%90%9C%E7%B4%A2) - [SDK 参考](#sdk-%E5%8F%82%E8%80%83) - [API 参考](#api-%E5%8F%82%E8%80%83) - [示例和教程](#%E7%A4%BA%E4%BE%8B%E5%92%8C%E6%95%99%E7%A8%8B) diff --git a/README-JP.md b/README-JP.md index 8f9e49cc2..6cc0885e1 100644 --- a/README-JP.md +++ b/README-JP.md @@ -68,9 +68,25 @@ Julepプロジェクトに新しいコントリビューターを歓迎します - [特徴](#%E7%89%B9%E5%BE%B4) - [インストール](#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%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%E3%82%AC%E3%82%A4%E3%83%89) + - [ステップ1:Julepをインポートする](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%971julep%E3%82%92%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B) + - [ステップ2:エージェントを初期化する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%972%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%82%92%E5%88%9D%E6%9C%9F%E5%8C%96%E3%81%99%E3%82%8B) + - [ステップ3:エージェントとチャットする](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%973%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) + - [ステップ4:多段階タスクを作成する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%974%E5%A4%9A%E6%AE%B5%E9%9A%8E%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B) + - [ステップ5:タスクを実行する](#%E3%82%B9%E3%83%86%E3%83%83%E3%83%975%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B) - [概念](#%E6%A6%82%E5%BF%B5) + - [エージェント](#%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88) + - [ユーザー](#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC) + - [セッション](#%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3) + - [タスク](#%E3%82%BF%E3%82%B9%E3%82%AF) + - [ツール](#%E3%83%84%E3%83%BC%E3%83%AB) + - [ドキュメント](#%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88) + - [実行](#%E5%AE%9F%E8%A1%8C) - [タスクの理解](#%E3%82%BF%E3%82%B9%E3%82%AF%E3%81%AE%E7%90%86%E8%A7%A3) + - [ワークフローステップの種類](#%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) - [高度な機能](#%E9%AB%98%E5%BA%A6%E3%81%AA%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%AB%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B) + - [セッションとユーザーの管理](#%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) - [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) - [例とチュートリアル](#%E4%BE%8B%E3%81%A8%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB) diff --git a/README.md b/README.md index 187f88702..d194f6cf7 100644 --- a/README.md +++ b/README.md @@ -68,13 +68,29 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓 - [Quick Example](#quick-example) - [Key Features](#key-features) - [Why Julep vs. LangChain?](#why-julep-vs-langchain) + - [Different Use Cases](#different-use-cases) + - [Different Form Factor](#different-form-factor) + - [In Summary](#in-summary) - [Installation](#installation) - [Python Quick Start 🐍](#python-quick-start-) + - [Step 1: Create an Agent](#step-1-create-an-agent) + - [Step 2: Create a Task that generates a story and comic strip](#step-2-create-a-task-that-generates-a-story-and-comic-strip) + - [Step 3: Execute the Task](#step-3-execute-the-task) + - [Step 4: Chat with the Agent](#step-4-chat-with-the-agent) - [Node.js Quick Start 🟩](#nodejs-quick-start-) + - [Step 1: Create an Agent](#step-1-create-an-agent-1) + - [Step 2: Create a Task that generates a story and comic strip](#step-2-create-a-task-that-generates-a-story-and-comic-strip-1) + - [Step 3: Execute the Task](#step-3-execute-the-task-1) + - [Step 4: Chat with the Agent](#step-4-chat-with-the-agent-1) - [Components](#components) + - [Mental Model](#mental-model) - [Concepts](#concepts) - [Understanding Tasks](#understanding-tasks) + - [Types of Workflow Steps](#types-of-workflow-steps) - [Advanced Features](#advanced-features) + - [Adding Tools to Agents](#adding-tools-to-agents) + - [Managing Sessions and Users](#managing-sessions-and-users) + - [Document Integration and Search](#document-integration-and-search) - [SDK Reference](#sdk-reference) - [API Reference](#api-reference) From 3a15afcdb7b4c60ab258b2f1b9610ff9354c1d05 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 04:56:00 +0530 Subject: [PATCH 11/23] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d194f6cf7..f10493155 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,11 @@ ***** -> [!TIP] +> [!NOTE] > 👨‍💻 Here for the devfest.ai event? Join our [Discord](https://discord.com/invite/JTSBGRZrzj) and check out the details below.
-🌟 Contributors and DevFest.AI Participants +🌟 Contributors and DevFest.AI Participants (Click to expand) ## 🌟 Call for Contributors! @@ -62,7 +62,7 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓
-📖 Table of Contents +

📖 Table of Contents

- [Introduction](#introduction) - [Quick Example](#quick-example) From 100eba8c1091c3d0a959924af15cc8eb3df861c3 Mon Sep 17 00:00:00 2001 From: creatorrr Date: Sun, 6 Oct 2024 23:26:13 +0000 Subject: [PATCH 12/23] chore(docs): update TOC --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f10493155..5cff0a8c3 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓
-

📖 Table of Contents

+📖 Table of Contents - [Introduction](#introduction) - [Quick Example](#quick-example) From 94cd57c8c18c01b05ac97e5bf1b2a426a8302950 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 05:02:39 +0530 Subject: [PATCH 13/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5cff0a8c3..fc56b90d4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ English | [中文翻译](/README-CN.md) | [日本語翻訳](/README-JP.md)
- julep + julep

From d8494872203f2716b56e55602cf4191bb9f4ec29 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 05:04:40 +0530 Subject: [PATCH 14/23] Update doctoc-on-push.yml --- .github/workflows/doctoc-on-push.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/doctoc-on-push.yml b/.github/workflows/doctoc-on-push.yml index d28821895..c0dfdf2c6 100644 --- a/.github/workflows/doctoc-on-push.yml +++ b/.github/workflows/doctoc-on-push.yml @@ -10,6 +10,5 @@ jobs: with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MAX_HEADER_LEVEL: 3 - TOC_TITLE: '📖 Table of Contents' + TOC_TITLE: '

📖 Table of Contents

' FOLDING: true - From 024b4ec758e3e9662e4ccbf95fbdaa843a019aa6 Mon Sep 17 00:00:00 2001 From: creatorrr Date: Sun, 6 Oct 2024 23:34:53 +0000 Subject: [PATCH 15/23] chore(docs): update TOC --- README-CN.md | 2 +- README-JP.md | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README-CN.md b/README-CN.md index abac03f01..d5cb2c2de 100644 --- a/README-CN.md +++ b/README-CN.md @@ -62,7 +62,7 @@
-📖 Table of Contents +

📖 Table of Contents

- [简介](#%E7%AE%80%E4%BB%8B) - [特性](#%E7%89%B9%E6%80%A7) diff --git a/README-JP.md b/README-JP.md index 6cc0885e1..8cd716ade 100644 --- a/README-JP.md +++ b/README-JP.md @@ -62,7 +62,7 @@ Julepプロジェクトに新しいコントリビューターを歓迎します
-📖 Table of Contents +

📖 Table of Contents

- [紹介](#%E7%B4%B9%E4%BB%8B) - [特徴](#%E7%89%B9%E5%BE%B4) diff --git a/README.md b/README.md index fc56b90d4..bd4b90626 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓
-📖 Table of Contents +

📖 Table of Contents

- [Introduction](#introduction) - [Quick Example](#quick-example) From ae238ee8d715a6547cc92b2c64ce88425326158f Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 05:09:24 +0530 Subject: [PATCH 16/23] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index bd4b90626..5bbf5fe21 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,8 @@ main: > [!TIP] > Julep is really useful when you want to build AI agents that can maintain context and state over long-term interactions. It's great for designing complex, multi-step workflows and integrating various tools and APIs directly into your agent's processes. +> +> In this example, Julep will automatically manage parallel executions, retry failed steps, resend api requests, and keep the workflows running reliably until completion. ## Key Features From 0b8e2d7886cde0e46f23ed81846c16220b5fdc76 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 05:20:26 +0530 Subject: [PATCH 17/23] Update README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5bbf5fe21..e3a212efb 100644 --- a/README.md +++ b/README.md @@ -617,14 +617,17 @@ Julep is built on several key technical components that work together to create ```mermaid graph TD - User[User] --> Session[Session] + User[User] ==> Session[Session] Session --> Agent[Agent] Agent --> Tasks[Tasks] Agent --> LLM[Large Language Model] Tasks --> Tools[Tools] - Tasks --> Documents[Documents] + Agent --> Documents[Documents] Documents --> VectorDB[Vector Database] - Agent --> Executions[Executions] + Tasks --> Executions[Executions] + + classDef client fill:#9ff,stroke:#333,stroke-width:1px; + class User client; classDef core fill:#f9f,stroke:#333,stroke-width:2px; class Agent,Tasks,Session core; From 46c0a23cdb7ba33790ec1ac4ef7f6cb6b723de6b Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Sun, 6 Oct 2024 23:34:50 -0400 Subject: [PATCH 18/23] feat: Email provider integration tool (#602) --- agents-api/agents_api/autogen/Tasks.py | 70 ---- agents-api/agents_api/autogen/Tools.py | 2 + .../agents_api/autogen/openapi_model.py | 5 - .../workflows/task_execution/__init__.py | 16 - agents-api/poetry.lock | 140 +++---- agents-api/pyproject.toml | 2 +- .../integrations/models/__init__.py | 1 + .../integrations/models/base_models.py | 6 +- .../integrations/models/email.py | 25 ++ .../integrations/models/execution.py | 4 + .../integrations/providers.py | 20 + .../integrations/utils/execute_integration.py | 9 +- .../utils/integrations/__init__.py | 1 + .../integrations/utils/integrations/email.py | 27 ++ integrations-service/poetry.lock | 341 +++++++++++------- integrations-service/pyproject.toml | 5 +- typespec/common/scalars.tsp | 19 - typespec/tasks/steps.tsp | 30 -- typespec/tools/models.tsp | 21 ++ .../@typespec/openapi3/openapi-0.4.0.yaml | 116 +----- .../@typespec/openapi3/openapi-1.0.0.yaml | 116 +----- 21 files changed, 394 insertions(+), 582 deletions(-) create mode 100644 integrations-service/integrations/models/email.py create mode 100644 integrations-service/integrations/utils/integrations/email.py diff --git a/agents-api/agents_api/autogen/Tasks.py b/agents-api/agents_api/autogen/Tasks.py index 83fde00da..c7067ea0c 100644 --- a/agents-api/agents_api/autogen/Tasks.py +++ b/agents-api/agents_api/autogen/Tasks.py @@ -9,12 +9,6 @@ from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, StrictBool from .Chat import ChatSettings -from .Docs import ( - EmbedQueryRequest, - HybridDocSearchRequest, - TextOnlyDocSearchRequest, - VectorDocSearchRequest, -) from .Tools import CreateToolRequest, NamedToolChoice @@ -33,8 +27,6 @@ class CaseThen(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -61,8 +53,6 @@ class CaseThenUpdateItem(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -128,8 +118,6 @@ class CreateTaskRequest(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -161,22 +149,6 @@ class CreateTaskRequest(BaseModel): metadata: dict[str, Any] | None = None -class EmbedStep(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - kind_: Annotated[ - Literal["embed"], Field("embed", json_schema_extra={"readOnly": True}) - ] - """ - The kind of step - """ - embed: EmbedQueryRequest - """ - The text to embed - """ - - class ErrorWorkflowStep(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -225,8 +197,6 @@ class ForeachDo(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep ) """ @@ -250,8 +220,6 @@ class ForeachDoUpdateItem(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep ) """ @@ -324,8 +292,6 @@ class IfElseWorkflowStep(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -342,8 +308,6 @@ class IfElseWorkflowStep(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -376,8 +340,6 @@ class IfElseWorkflowStepUpdateItem(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -394,8 +356,6 @@ class IfElseWorkflowStepUpdateItem(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -462,8 +422,6 @@ class Main(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep ) """ @@ -504,8 +462,6 @@ class MainModel(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep ) """ @@ -545,8 +501,6 @@ class ParallelStep(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep ], Field(max_length=100), @@ -572,8 +526,6 @@ class ParallelStepUpdateItem(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep ], Field(max_length=100), @@ -600,8 +552,6 @@ class PatchTaskRequest(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -762,22 +712,6 @@ class ReturnStep(BaseModel): """ -class SearchStep(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - kind_: Annotated[ - Literal["search"], Field("search", json_schema_extra={"readOnly": True}) - ] - """ - The kind of step - """ - search: VectorDocSearchRequest | TextOnlyDocSearchRequest | HybridDocSearchRequest - """ - The search query - """ - - class SetStep(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -878,8 +812,6 @@ class Task(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep @@ -1013,8 +945,6 @@ class UpdateTaskRequest(BaseModel): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep | ReturnStep | SleepStep diff --git a/agents-api/agents_api/autogen/Tools.py b/agents-api/agents_api/autogen/Tools.py index ffe10302c..423896e89 100644 --- a/agents-api/agents_api/autogen/Tools.py +++ b/agents-api/agents_api/autogen/Tools.py @@ -223,6 +223,7 @@ class IntegrationDef(BaseModel): "spider", "brave", "browserbase", + "email", ] | str ) @@ -260,6 +261,7 @@ class IntegrationDefUpdate(BaseModel): "spider", "brave", "browserbase", + "email", ] | str | None diff --git a/agents-api/agents_api/autogen/openapi_model.py b/agents-api/agents_api/autogen/openapi_model.py index 0d9390816..fd06f38a8 100644 --- a/agents-api/agents_api/autogen/openapi_model.py +++ b/agents-api/agents_api/autogen/openapi_model.py @@ -12,7 +12,6 @@ computed_field, field_validator, model_validator, - validator, ) from ..common.utils.datetime import utcnow @@ -401,8 +400,6 @@ def from_model_input( | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | ReturnStep | SleepStep | ErrorWorkflowStep @@ -475,8 +472,6 @@ class Task(_Task): | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | ReturnStep | SleepStep | ErrorWorkflowStep diff --git a/agents-api/agents_api/workflows/task_execution/__init__.py b/agents-api/agents_api/workflows/task_execution/__init__.py index d26a3d999..edf54fb12 100644 --- a/agents-api/agents_api/workflows/task_execution/__init__.py +++ b/agents-api/agents_api/workflows/task_execution/__init__.py @@ -16,7 +16,6 @@ from ...activities.execute_system import execute_system from ...autogen.openapi_model import ( ApiCallDef, - EmbedStep, ErrorWorkflowStep, EvaluateStep, ForeachDo, @@ -29,7 +28,6 @@ ParallelStep, PromptStep, ReturnStep, - SearchStep, SetStep, SleepFor, SleepStep, @@ -72,8 +70,6 @@ # | GetStep # ✅ # | SetStep # ✅ # | LogStep # ✅ -# | EmbedStep # ❌ -# | SearchStep # ❌ # | ReturnStep # ✅ # | SleepStep # ✅ # | ErrorWorkflowStep # ✅ @@ -455,18 +451,6 @@ async def run( state = PartialTransition(output=value) - case EmbedStep(), _: - # FIXME: Implement EmbedStep - # SCRUM-19 - workflow.logger.error("EmbedStep not yet implemented") - raise ApplicationError("Not implemented") - - case SearchStep(), _: - # FIXME: Implement SearchStep - # SCRUM-18 - workflow.logger.error("SearchStep not yet implemented") - raise ApplicationError("Not implemented") - case ParallelStep(), _: # FIXME: Implement ParallelStep # SCRUM-17 diff --git a/agents-api/poetry.lock b/agents-api/poetry.lock index 608a8e665..907669721 100644 --- a/agents-api/poetry.lock +++ b/agents-api/poetry.lock @@ -837,21 +837,21 @@ files = [ [[package]] name = "dnspython" -version = "2.6.1" +version = "2.7.0" description = "DNS toolkit" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, - {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, + {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, + {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, ] [package.extras] -dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] -dnssec = ["cryptography (>=41)"] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "hypercorn (>=0.16.0)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "quart-trio (>=0.11.0)", "sphinx (>=7.2.0)", "sphinx-rtd-theme (>=2.0.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=43)"] doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] -doq = ["aioquic (>=0.9.25)"] -idna = ["idna (>=3.6)"] +doq = ["aioquic (>=1.0.0)"] +idna = ["idna (>=3.7)"] trio = ["trio (>=0.23)"] wmi = ["wmi (>=1.5.1)"] @@ -1923,13 +1923,13 @@ dev = ["Sphinx (>=5.1.1)", "black (==23.12.1)", "build (>=0.10.0)", "coverage (> [[package]] name = "litellm" -version = "1.48.16" +version = "1.48.17" description = "Library to easily interface with LLM API providers" optional = false python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" files = [ - {file = "litellm-1.48.16-py3-none-any.whl", hash = "sha256:a7bcce83c97cbacdaf89f24d1c51d81117bcf0af2f0f3a41532656c570d23932"}, - {file = "litellm-1.48.16.tar.gz", hash = "sha256:bda6fc7c8429fcd42c3a80618098678dae833990b2347740aadb84886035b31c"}, + {file = "litellm-1.48.17-py3-none-any.whl", hash = "sha256:f3c25b8bcdbe2c65fbe492a674574461c200040e9e633073108c9517630469b6"}, + {file = "litellm-1.48.17.tar.gz", hash = "sha256:5b5039b39c4a9f748af8253895eec76b3458960533d1e038d1aec409d550ee37"}, ] [package.dependencies] @@ -2466,64 +2466,64 @@ test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync" [[package]] name = "numpy" -version = "2.1.1" +version = "2.1.2" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" files = [ - {file = "numpy-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a0e34993b510fc19b9a2ce7f31cb8e94ecf6e924a40c0c9dd4f62d0aac47d9"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7dd86dfaf7c900c0bbdcb8b16e2f6ddf1eb1fe39c6c8cca6e94844ed3152a8fd"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5889dd24f03ca5a5b1e8a90a33b5a0846d8977565e4ae003a63d22ecddf6782f"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:59ca673ad11d4b84ceb385290ed0ebe60266e356641428c845b39cd9df6713ab"}, - {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13ce49a34c44b6de5241f0b38b07e44c1b2dcacd9e36c30f9c2fcb1bb5135db7"}, - {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913cc1d311060b1d409e609947fa1b9753701dac96e6581b58afc36b7ee35af6"}, - {file = "numpy-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:caf5d284ddea7462c32b8d4a6b8af030b6c9fd5332afb70e7414d7fdded4bfd0"}, - {file = "numpy-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:57eb525e7c2a8fdee02d731f647146ff54ea8c973364f3b850069ffb42799647"}, - {file = "numpy-2.1.1-cp310-cp310-win32.whl", hash = "sha256:9a8e06c7a980869ea67bbf551283bbed2856915f0a792dc32dd0f9dd2fb56728"}, - {file = "numpy-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d10c39947a2d351d6d466b4ae83dad4c37cd6c3cdd6d5d0fa797da56f710a6ae"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d07841fd284718feffe7dd17a63a2e6c78679b2d386d3e82f44f0108c905550"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5613cfeb1adfe791e8e681128f5f49f22f3fcaa942255a6124d58ca59d9528f"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0b8cc2715a84b7c3b161f9ebbd942740aaed913584cae9cdc7f8ad5ad41943d0"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b49742cdb85f1f81e4dc1b39dcf328244f4d8d1ded95dea725b316bd2cf18c95"}, - {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d5f8a8e3bc87334f025194c6193e408903d21ebaeb10952264943a985066ca"}, - {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d51fc141ddbe3f919e91a096ec739f49d686df8af254b2053ba21a910ae518bf"}, - {file = "numpy-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:98ce7fb5b8063cfdd86596b9c762bf2b5e35a2cdd7e967494ab78a1fa7f8b86e"}, - {file = "numpy-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:24c2ad697bd8593887b019817ddd9974a7f429c14a5469d7fad413f28340a6d2"}, - {file = "numpy-2.1.1-cp311-cp311-win32.whl", hash = "sha256:397bc5ce62d3fb73f304bec332171535c187e0643e176a6e9421a6e3eacef06d"}, - {file = "numpy-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:ae8ce252404cdd4de56dcfce8b11eac3c594a9c16c231d081fb705cf23bd4d9e"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521"}, - {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b"}, - {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201"}, - {file = "numpy-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a"}, - {file = "numpy-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313"}, - {file = "numpy-2.1.1-cp312-cp312-win32.whl", hash = "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed"}, - {file = "numpy-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0"}, - {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb"}, - {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df"}, - {file = "numpy-2.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78"}, - {file = "numpy-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556"}, - {file = "numpy-2.1.1-cp313-cp313-win32.whl", hash = "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b"}, - {file = "numpy-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468"}, - {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef"}, - {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f"}, - {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c"}, - {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7be6a07520b88214ea85d8ac8b7d6d8a1839b0b5cb87412ac9f49fa934eb15d5"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:52ac2e48f5ad847cd43c4755520a2317f3380213493b9d8a4c5e37f3b87df504"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a95ca3560a6058d6ea91d4629a83a897ee27c00630aed9d933dff191f170cd"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:99f4a9ee60eed1385a86e82288971a51e71df052ed0b2900ed30bc840c0f2e39"}, - {file = "numpy-2.1.1.tar.gz", hash = "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd"}, + {file = "numpy-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30d53720b726ec36a7f88dc873f0eec8447fbc93d93a8f079dfac2629598d6ee"}, + {file = "numpy-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d3ca0a72dd8846eb6f7dfe8f19088060fcb76931ed592d29128e0219652884"}, + {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:fc44e3c68ff00fd991b59092a54350e6e4911152682b4782f68070985aa9e648"}, + {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:7c1c60328bd964b53f8b835df69ae8198659e2b9302ff9ebb7de4e5a5994db3d"}, + {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cdb606a7478f9ad91c6283e238544451e3a95f30fb5467fbf715964341a8a86"}, + {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d666cb72687559689e9906197e3bec7b736764df6a2e58ee265e360663e9baf7"}, + {file = "numpy-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6eef7a2dbd0abfb0d9eaf78b73017dbfd0b54051102ff4e6a7b2980d5ac1a03"}, + {file = "numpy-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12edb90831ff481f7ef5f6bc6431a9d74dc0e5ff401559a71e5e4611d4f2d466"}, + {file = "numpy-2.1.2-cp310-cp310-win32.whl", hash = "sha256:a65acfdb9c6ebb8368490dbafe83c03c7e277b37e6857f0caeadbbc56e12f4fb"}, + {file = "numpy-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:860ec6e63e2c5c2ee5e9121808145c7bf86c96cca9ad396c0bd3e0f2798ccbe2"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b42a1a511c81cc78cbc4539675713bbcf9d9c3913386243ceff0e9429ca892fe"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:faa88bc527d0f097abdc2c663cddf37c05a1c2f113716601555249805cf573f1"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c82af4b2ddd2ee72d1fc0c6695048d457e00b3582ccde72d8a1c991b808bb20f"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:13602b3174432a35b16c4cfb5de9a12d229727c3dd47a6ce35111f2ebdf66ff4"}, + {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ebec5fd716c5a5b3d8dfcc439be82a8407b7b24b230d0ad28a81b61c2f4659a"}, + {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2b49c3c0804e8ecb05d59af8386ec2f74877f7ca8fd9c1e00be2672e4d399b1"}, + {file = "numpy-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cbba4b30bf31ddbe97f1c7205ef976909a93a66bb1583e983adbd155ba72ac2"}, + {file = "numpy-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e00ea6fc82e8a804433d3e9cedaa1051a1422cb6e443011590c14d2dea59146"}, + {file = "numpy-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5006b13a06e0b38d561fab5ccc37581f23c9511879be7693bd33c7cd15ca227c"}, + {file = "numpy-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1eb068ead09f4994dec71c24b2844f1e4e4e013b9629f812f292f04bd1510d9"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7bf0a4f9f15b32b5ba53147369e94296f5fffb783db5aacc1be15b4bf72f43b"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b1d0fcae4f0949f215d4632be684a539859b295e2d0cb14f78ec231915d644db"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f751ed0a2f250541e19dfca9f1eafa31a392c71c832b6bb9e113b10d050cb0f1"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bd33f82e95ba7ad632bc57837ee99dba3d7e006536200c4e9124089e1bf42426"}, + {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8cde4f11f0a975d1fd59373b32e2f5a562ade7cde4f85b7137f3de8fbb29a0"}, + {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df"}, + {file = "numpy-2.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ab4754d432e3ac42d33a269c8567413bdb541689b02d93788af4131018cbf366"}, + {file = "numpy-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e585c8ae871fd38ac50598f4763d73ec5497b0de9a0ab4ef5b69f01c6a046142"}, + {file = "numpy-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9c6c754df29ce6a89ed23afb25550d1c2d5fdb9901d9c67a16e0b16eaf7e2550"}, + {file = "numpy-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a84498e0d0a1174f2b3ed769b67b656aa5460c92c9554039e11f20a05650f00d"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d6ec0d4222e8ffdab1744da2560f07856421b367928026fb540e1945f2eeeaf"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:259ec80d54999cc34cd1eb8ded513cb053c3bf4829152a2e00de2371bd406f5e"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:675c741d4739af2dc20cd6c6a5c4b7355c728167845e3c6b0e824e4e5d36a6c3"}, + {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8"}, + {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43cca367bf94a14aca50b89e9bc2061683116cfe864e56740e083392f533ce7a"}, + {file = "numpy-2.1.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:76322dcdb16fccf2ac56f99048af32259dcc488d9b7e25b51e5eca5147a3fb98"}, + {file = "numpy-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e16a03138cabe0cb28e1007ee82264296ac0983714094380b408097a418cfe"}, + {file = "numpy-2.1.2-cp313-cp313-win32.whl", hash = "sha256:242b39d00e4944431a3cd2db2f5377e15b5785920421993770cddb89992c3f3a"}, + {file = "numpy-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f2ded8d9b6f68cc26f8425eda5d3877b47343e68ca23d0d0846f4d312ecaa445"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ffef621c14ebb0188a8633348504a35c13680d6da93ab5cb86f4e54b7e922b5"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ad369ed238b1959dfbade9018a740fb9392c5ac4f9b5173f420bd4f37ba1f7a0"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d82075752f40c0ddf57e6e02673a17f6cb0f8eb3f587f63ca1eaab5594da5b17"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:1600068c262af1ca9580a527d43dc9d959b0b1d8e56f8a05d830eea39b7c8af6"}, + {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a26ae94658d3ba3781d5e103ac07a876b3e9b29db53f68ed7df432fd033358a8"}, + {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13311c2db4c5f7609b462bc0f43d3c465424d25c626d95040f073e30f7570e35"}, + {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:2abbf905a0b568706391ec6fa15161fad0fb5d8b68d73c461b3c1bab6064dd62"}, + {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ef444c57d664d35cac4e18c298c47d7b504c66b17c2ea91312e979fcfbdfb08a"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bdd407c40483463898b84490770199d5714dcc9dd9b792f6c6caccc523c00952"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:da65fb46d4cbb75cb417cddf6ba5e7582eb7bb0b47db4b99c9fe5787ce5d91f5"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c193d0b0238638e6fc5f10f1b074a6993cb13b0b431f64079a509d63d3aa8b7"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a7d80b2e904faa63068ead63107189164ca443b42dd1930299e0d1cb041cec2e"}, + {file = "numpy-2.1.2.tar.gz", hash = "sha256:13532a088217fa624c99b843eeb54640de23b3414b14aa66d023805eb731066c"}, ] [[package]] @@ -4057,13 +4057,13 @@ test = ["pytest", "tornado (>=4.5)", "typeguard"] [[package]] name = "termcolor" -version = "2.4.0" +version = "2.5.0" description = "ANSI color formatting for output in terminal" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"}, - {file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"}, + {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"}, + {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"}, ] [package.extras] @@ -4687,4 +4687,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "62fd7359138dfd660b6601064b7c3e732e436fbbc9c9281b42ad3e46ff3a6c04" +content-hash = "04b888dec8224adfc326c796eda70f96df1ab93905cbfe3ebda00330b2740e48" diff --git a/agents-api/pyproject.toml b/agents-api/pyproject.toml index 2ed126d6f..1701a45cd 100644 --- a/agents-api/pyproject.toml +++ b/agents-api/pyproject.toml @@ -18,7 +18,7 @@ openai = "^1.41.0" httpx = "^0.27.0" sentry-sdk = {extras = ["fastapi"], version = "^2.13.0"} temporalio = "^1.7.0" -pydantic = {extras = ["email"], version = "^2.8.2"} +pydantic = {extras = ["email"], version = "^2.9.2"} arrow = "^1.3.0" jinja2 = "^3.1.4" jinja2schema = "^0.1.4" diff --git a/integrations-service/integrations/models/__init__.py b/integrations-service/integrations/models/__init__.py index 9f7fb6992..902a4a044 100644 --- a/integrations-service/integrations/models/__init__.py +++ b/integrations-service/integrations/models/__init__.py @@ -12,6 +12,7 @@ BrowserBaseLoadOutput, BrowserBaseSetup, ) +from .email import EmailArguments, EmailOutput, EmailSetup from .hacker_news import HackerNewsFetchArguments, HackerNewsFetchOutput from .spider import SpiderFetchArguments, SpiderFetchOutput, SpiderSetup from .weather import WeatherGetArguments, WeatherGetOutput, WeatherSetup diff --git a/integrations-service/integrations/models/base_models.py b/integrations-service/integrations/models/base_models.py index 72e250365..9f119d460 100644 --- a/integrations-service/integrations/models/base_models.py +++ b/integrations-service/integrations/models/base_models.py @@ -16,9 +16,9 @@ class BaseOutput(BaseModel): ... class ProviderInfo(BaseModel): - url: Optional[Url] - docs: Optional[Url] - icon: Optional[Url] + url: Optional[Url] = None + docs: Optional[Url] = None + icon: Optional[Url] = None friendly_name: str diff --git a/integrations-service/integrations/models/email.py b/integrations-service/integrations/models/email.py new file mode 100644 index 000000000..cab794a7d --- /dev/null +++ b/integrations-service/integrations/models/email.py @@ -0,0 +1,25 @@ +from pydantic import EmailStr, Field + +from .base_models import ( + BaseArguments, + BaseOutput, + BaseSetup, +) + + +class EmailSetup(BaseSetup): + host: str = Field(..., description="The host of the email server") + port: int = Field(..., description="The port of the email server") + user: str = Field(..., description="The username of the email server") + password: str = Field(..., description="The password of the email server") + + +class EmailArguments(BaseArguments): + to: EmailStr = Field(..., description="The email address to send the email to") + from_: EmailStr = Field(..., alias="from", description="The email address to send the email from") + subject: str = Field(..., description="The subject of the email") + body: str = Field(..., description="The body of the email") + + +class EmailOutput(BaseOutput): + success: bool = Field(..., description="Whether the email was sent successfully") diff --git a/integrations-service/integrations/models/execution.py b/integrations-service/integrations/models/execution.py index ff9290d6a..db1ef801f 100644 --- a/integrations-service/integrations/models/execution.py +++ b/integrations-service/integrations/models/execution.py @@ -8,12 +8,14 @@ BrowserBaseLoadOutput, BrowserBaseSetup, ) +from .email import EmailArguments, EmailOutput, EmailSetup from .hacker_news import HackerNewsFetchArguments, HackerNewsFetchOutput from .spider import SpiderFetchArguments, SpiderFetchOutput, SpiderSetup from .weather import WeatherGetArguments, WeatherGetOutput, WeatherSetup from .wikipedia import WikipediaSearchArguments, WikipediaSearchOutput ExecutionSetup = Union[ + EmailSetup, SpiderSetup, WeatherSetup, BraveSearchSetup, @@ -23,6 +25,7 @@ ExecutionArguments = Union[ SpiderFetchArguments, WeatherGetArguments, + EmailArguments, HackerNewsFetchArguments, WikipediaSearchArguments, BraveSearchArguments, @@ -32,6 +35,7 @@ ExecutionResponse = Union[ SpiderFetchOutput, WeatherGetOutput, + EmailOutput, HackerNewsFetchOutput, WikipediaSearchOutput, BraveSearchOutput, diff --git a/integrations-service/integrations/providers.py b/integrations-service/integrations/providers.py index 4bce7a2ba..41b5bf757 100644 --- a/integrations-service/integrations/providers.py +++ b/integrations-service/integrations/providers.py @@ -7,6 +7,9 @@ BrowserBaseLoadArguments, BrowserBaseLoadOutput, BrowserBaseSetup, + EmailArguments, + EmailOutput, + EmailSetup, HackerNewsFetchArguments, HackerNewsFetchOutput, ProviderInfo, @@ -134,6 +137,22 @@ ), ) +email = BaseProvider( + provider="email", + setup=EmailSetup, + methods=[ + BaseProviderMethod( + method="send", + description="Send an email", + arguments=EmailArguments, + output=EmailOutput, + ), + ], + info=ProviderInfo( + friendly_name="Email", + ), +) + providers = { "wikipedia": wikipedia, "weather": weather, @@ -141,4 +160,5 @@ "spider": spider, "brave": brave, "browserbase": browserbase, + "email": email, } diff --git a/integrations-service/integrations/utils/execute_integration.py b/integrations-service/integrations/utils/execute_integration.py index fdc6d23d0..ab1907885 100644 --- a/integrations-service/integrations/utils/execute_integration.py +++ b/integrations-service/integrations/utils/execute_integration.py @@ -26,10 +26,15 @@ async def execute_integration( if setup: setup_class = provider.setup - if setup_class: + if setup_class and not isinstance(setup, setup_class): setup = setup_class(**setup.model_dump()) + arguments_class = next(m for m in provider.methods if m.method == method).arguments - parsed_arguments = arguments_class(**arguments.model_dump()) + + if not isinstance(arguments, arguments_class): + parsed_arguments = arguments_class(**arguments.model_dump()) + else: + parsed_arguments = arguments if setup: return await execution_function(setup=setup, arguments=parsed_arguments) diff --git a/integrations-service/integrations/utils/integrations/__init__.py b/integrations-service/integrations/utils/integrations/__init__.py index dc123fd4c..238dacfd3 100644 --- a/integrations-service/integrations/utils/integrations/__init__.py +++ b/integrations-service/integrations/utils/integrations/__init__.py @@ -1,5 +1,6 @@ from .brave import search from .browserbase import load +from .email import send from .hacker_news import fetch from .spider import crawl from .weather import get diff --git a/integrations-service/integrations/utils/integrations/email.py b/integrations-service/integrations/utils/integrations/email.py new file mode 100644 index 000000000..b0ced9ff5 --- /dev/null +++ b/integrations-service/integrations/utils/integrations/email.py @@ -0,0 +1,27 @@ +from email.message import EmailMessage +from smtplib import SMTP + +from beartype import beartype + +from ...models import EmailArguments, EmailOutput, EmailSetup + + +# @beartype +async def send( + setup: EmailSetup, arguments: EmailArguments +) -> EmailOutput: + """ + Sends an email with the provided details. + """ + + message = EmailMessage() + message.set_content(arguments.body) + message["Subject"] = arguments.subject + message["From"] = arguments.from_ + message["To"] = arguments.to + + with SMTP(setup.host, setup.port) as server: + server.login(setup.user, setup.password) + server.send_message(message) + + return EmailOutput(success=True) diff --git a/integrations-service/poetry.lock b/integrations-service/poetry.lock index e56fd28cd..bc294a56f 100644 --- a/integrations-service/poetry.lock +++ b/integrations-service/poetry.lock @@ -2,113 +2,113 @@ [[package]] name = "aiohappyeyeballs" -version = "2.4.2" +version = "2.4.3" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.2-py3-none-any.whl", hash = "sha256:8522691d9a154ba1145b157d6d5c15e5c692527ce6a53c5e5f9876977f6dab2f"}, - {file = "aiohappyeyeballs-2.4.2.tar.gz", hash = "sha256:4ca893e6c5c1f5bf3888b04cb5a3bee24995398efef6e0b9f747b5e89d84fd74"}, + {file = "aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572"}, + {file = "aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586"}, ] [[package]] name = "aiohttp" -version = "3.10.8" +version = "3.10.9" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.10.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a1ba7bc139592339ddeb62c06486d0fa0f4ca61216e14137a40d626c81faf10c"}, - {file = "aiohttp-3.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:85e4d7bd05d18e4b348441e7584c681eff646e3bf38f68b2626807f3add21aa2"}, - {file = "aiohttp-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:69de056022e7abf69cb9fec795515973cc3eeaff51e3ea8d72a77aa933a91c52"}, - {file = "aiohttp-3.10.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee3587506898d4a404b33bd19689286ccf226c3d44d7a73670c8498cd688e42c"}, - {file = "aiohttp-3.10.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe285a697c851734285369614443451462ce78aac2b77db23567507484b1dc6f"}, - {file = "aiohttp-3.10.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10c7932337285a6bfa3a5fe1fd4da90b66ebfd9d0cbd1544402e1202eb9a8c3e"}, - {file = "aiohttp-3.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd9716ef0224fe0d0336997eb242f40619f9f8c5c57e66b525a1ebf9f1d8cebe"}, - {file = "aiohttp-3.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ceacea31f8a55cdba02bc72c93eb2e1b77160e91f8abd605969c168502fd71eb"}, - {file = "aiohttp-3.10.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9721554bfa9e15f6e462da304374c2f1baede3cb06008c36c47fa37ea32f1dc4"}, - {file = "aiohttp-3.10.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:22cdeb684d8552490dd2697a5138c4ecb46f844892df437aaf94f7eea99af879"}, - {file = "aiohttp-3.10.8-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e56bb7e31c4bc79956b866163170bc89fd619e0581ce813330d4ea46921a4881"}, - {file = "aiohttp-3.10.8-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:3a95d2686bc4794d66bd8de654e41b5339fab542b2bca9238aa63ed5f4f2ce82"}, - {file = "aiohttp-3.10.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d82404a0e7b10e0d7f022cf44031b78af8a4f99bd01561ac68f7c24772fed021"}, - {file = "aiohttp-3.10.8-cp310-cp310-win32.whl", hash = "sha256:4e10b04542d27e21538e670156e88766543692a0a883f243ba8fad9ddea82e53"}, - {file = "aiohttp-3.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:680dbcff5adc7f696ccf8bf671d38366a1f620b5616a1d333d0cb33956065395"}, - {file = "aiohttp-3.10.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:33a68011a38020ed4ff41ae0dbf4a96a202562ecf2024bdd8f65385f1d07f6ef"}, - {file = "aiohttp-3.10.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c7efa6616a95e3bd73b8a69691012d2ef1f95f9ea0189e42f338fae080c2fc6"}, - {file = "aiohttp-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddb9b9764cfb4459acf01c02d2a59d3e5066b06a846a364fd1749aa168efa2be"}, - {file = "aiohttp-3.10.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7f270f4ca92760f98a42c45a58674fff488e23b144ec80b1cc6fa2effed377"}, - {file = "aiohttp-3.10.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6984dda9d79064361ab58d03f6c1e793ea845c6cfa89ffe1a7b9bb400dfd56bd"}, - {file = "aiohttp-3.10.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f6d47e392c27206701565c8df4cac6ebed28fdf6dcaea5b1eea7a4631d8e6db"}, - {file = "aiohttp-3.10.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a72f89aea712c619b2ca32c6f4335c77125ede27530ad9705f4f349357833695"}, - {file = "aiohttp-3.10.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36074b26f3263879ba8e4dbd33db2b79874a3392f403a70b772701363148b9f"}, - {file = "aiohttp-3.10.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e32148b4a745e70a255a1d44b5664de1f2e24fcefb98a75b60c83b9e260ddb5b"}, - {file = "aiohttp-3.10.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5aa1a073514cf59c81ad49a4ed9b5d72b2433638cd53160fd2f3a9cfa94718db"}, - {file = "aiohttp-3.10.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d3a79200a9d5e621c4623081ddb25380b713c8cf5233cd11c1aabad990bb9381"}, - {file = "aiohttp-3.10.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e45fdfcb2d5bcad83373e4808825b7512953146d147488114575780640665027"}, - {file = "aiohttp-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f78e2a78432c537ae876a93013b7bc0027ba5b93ad7b3463624c4b6906489332"}, - {file = "aiohttp-3.10.8-cp311-cp311-win32.whl", hash = "sha256:f8179855a4e4f3b931cb1764ec87673d3fbdcca2af496c8d30567d7b034a13db"}, - {file = "aiohttp-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:ef9b484604af05ca745b6108ca1aaa22ae1919037ae4f93aaf9a37ba42e0b835"}, - {file = "aiohttp-3.10.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ab2d6523575fc98896c80f49ac99e849c0b0e69cc80bf864eed6af2ae728a52b"}, - {file = "aiohttp-3.10.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f5d5d5401744dda50b943d8764508d0e60cc2d3305ac1e6420935861a9d544bc"}, - {file = "aiohttp-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de23085cf90911600ace512e909114385026b16324fa203cc74c81f21fd3276a"}, - {file = "aiohttp-3.10.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4618f0d2bf523043866a9ff8458900d8eb0a6d4018f251dae98e5f1fb699f3a8"}, - {file = "aiohttp-3.10.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21c1925541ca84f7b5e0df361c0a813a7d6a56d3b0030ebd4b220b8d232015f9"}, - {file = "aiohttp-3.10.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:497a7d20caea8855c5429db3cdb829385467217d7feb86952a6107e033e031b9"}, - {file = "aiohttp-3.10.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c887019dbcb4af58a091a45ccf376fffe800b5531b45c1efccda4bedf87747ea"}, - {file = "aiohttp-3.10.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40d2d719c3c36a7a65ed26400e2b45b2d9ed7edf498f4df38b2ae130f25a0d01"}, - {file = "aiohttp-3.10.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:57359785f27394a8bcab0da6dcd46706d087dfebf59a8d0ad2e64a4bc2f6f94f"}, - {file = "aiohttp-3.10.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a961ee6f2cdd1a2be4735333ab284691180d40bad48f97bb598841bfcbfb94ec"}, - {file = "aiohttp-3.10.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:fe3d79d6af839ffa46fdc5d2cf34295390894471e9875050eafa584cb781508d"}, - {file = "aiohttp-3.10.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9a281cba03bdaa341c70b7551b2256a88d45eead149f48b75a96d41128c240b3"}, - {file = "aiohttp-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c6769d71bfb1ed60321363a9bc05e94dcf05e38295ef41d46ac08919e5b00d19"}, - {file = "aiohttp-3.10.8-cp312-cp312-win32.whl", hash = "sha256:a3081246bab4d419697ee45e555cef5cd1def7ac193dff6f50be761d2e44f194"}, - {file = "aiohttp-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:ab1546fc8e00676febc81c548a876c7bde32f881b8334b77f84719ab2c7d28dc"}, - {file = "aiohttp-3.10.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b1a012677b8e0a39e181e218de47d6741c5922202e3b0b65e412e2ce47c39337"}, - {file = "aiohttp-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2df786c96c57cd6b87156ba4c5f166af7b88f3fc05f9d592252fdc83d8615a3c"}, - {file = "aiohttp-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8885ca09d3a9317219c0831276bfe26984b17b2c37b7bf70dd478d17092a4772"}, - {file = "aiohttp-3.10.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dbf252ac19860e0ab56cd480d2805498f47c5a2d04f5995d8d8a6effd04b48c"}, - {file = "aiohttp-3.10.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b2036479b6b94afaaca7d07b8a68dc0e67b0caf5f6293bb6a5a1825f5923000"}, - {file = "aiohttp-3.10.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:365783e1b7c40b59ed4ce2b5a7491bae48f41cd2c30d52647a5b1ee8604c68ad"}, - {file = "aiohttp-3.10.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:270e653b5a4b557476a1ed40e6b6ce82f331aab669620d7c95c658ef976c9c5e"}, - {file = "aiohttp-3.10.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8960fabc20bfe4fafb941067cda8e23c8c17c98c121aa31c7bf0cdab11b07842"}, - {file = "aiohttp-3.10.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f21e8f2abed9a44afc3d15bba22e0dfc71e5fa859bea916e42354c16102b036f"}, - {file = "aiohttp-3.10.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fecd55e7418fabd297fd836e65cbd6371aa4035a264998a091bbf13f94d9c44d"}, - {file = "aiohttp-3.10.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:badb51d851358cd7535b647bb67af4854b64f3c85f0d089c737f75504d5910ec"}, - {file = "aiohttp-3.10.8-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e860985f30f3a015979e63e7ba1a391526cdac1b22b7b332579df7867848e255"}, - {file = "aiohttp-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:71462f8eeca477cbc0c9700a9464e3f75f59068aed5e9d4a521a103692da72dc"}, - {file = "aiohttp-3.10.8-cp313-cp313-win32.whl", hash = "sha256:177126e971782769b34933e94fddd1089cef0fe6b82fee8a885e539f5b0f0c6a"}, - {file = "aiohttp-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:98a4eb60e27033dee9593814ca320ee8c199489fbc6b2699d0f710584db7feb7"}, - {file = "aiohttp-3.10.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ffef3d763e4c8fc97e740da5b4d0f080b78630a3914f4e772a122bbfa608c1db"}, - {file = "aiohttp-3.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:597128cb7bc5f068181b49a732961f46cb89f85686206289d6ccb5e27cb5fbe2"}, - {file = "aiohttp-3.10.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f23a6c1d09de5de89a33c9e9b229106cb70dcfdd55e81a3a3580eaadaa32bc92"}, - {file = "aiohttp-3.10.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da57af0c54a302b7c655fa1ccd5b1817a53739afa39924ef1816e7b7c8a07ccb"}, - {file = "aiohttp-3.10.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7a6af57091056a79a35104d6ec29d98ec7f1fb7270ad9c6fff871b678d1ff8"}, - {file = "aiohttp-3.10.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32710d6b3b6c09c60c794d84ca887a3a2890131c0b02b3cefdcc6709a2260a7c"}, - {file = "aiohttp-3.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b91f4f62ad39a8a42d511d66269b46cb2fb7dea9564c21ab6c56a642d28bff5"}, - {file = "aiohttp-3.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:471a8c47344b9cc309558b3fcc469bd2c12b49322b4b31eb386c4a2b2d44e44a"}, - {file = "aiohttp-3.10.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fc0e7f91705445d79beafba9bb3057dd50830e40fe5417017a76a214af54e122"}, - {file = "aiohttp-3.10.8-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:85431c9131a9a0f65260dc7a65c800ca5eae78c4c9931618f18c8e0933a0e0c1"}, - {file = "aiohttp-3.10.8-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:b91557ee0893da52794b25660d4f57bb519bcad8b7df301acd3898f7197c5d81"}, - {file = "aiohttp-3.10.8-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:4954e6b06dd0be97e1a5751fc606be1f9edbdc553c5d9b57d72406a8fbd17f9d"}, - {file = "aiohttp-3.10.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a087c84b4992160ffef7afd98ef24177c8bd4ad61c53607145a8377457385100"}, - {file = "aiohttp-3.10.8-cp38-cp38-win32.whl", hash = "sha256:e1f0f7b27171b2956a27bd8f899751d0866ddabdd05cbddf3520f945130a908c"}, - {file = "aiohttp-3.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:c4916070e12ae140110aa598031876c1bf8676a36a750716ea0aa5bd694aa2e7"}, - {file = "aiohttp-3.10.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5284997e3d88d0dfb874c43e51ae8f4a6f4ca5b90dcf22995035187253d430db"}, - {file = "aiohttp-3.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9443d9ebc5167ce1fbb552faf2d666fb22ef5716a8750be67efd140a7733738c"}, - {file = "aiohttp-3.10.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b667e2a03407d79a76c618dc30cedebd48f082d85880d0c9c4ec2faa3e10f43e"}, - {file = "aiohttp-3.10.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98fae99d5c2146f254b7806001498e6f9ffb0e330de55a35e72feb7cb2fa399b"}, - {file = "aiohttp-3.10.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8296edd99d0dd9d0eb8b9e25b3b3506eef55c1854e9cc230f0b3f885f680410b"}, - {file = "aiohttp-3.10.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ce46dfb49cfbf9e92818be4b761d4042230b1f0e05ffec0aad15b3eb162b905"}, - {file = "aiohttp-3.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c38cfd355fd86c39b2d54651bd6ed7d63d4fe3b5553f364bae3306e2445f847"}, - {file = "aiohttp-3.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:713dff3f87ceec3bde4f3f484861464e722cf7533f9fa6b824ec82bb5a9010a7"}, - {file = "aiohttp-3.10.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:21a72f4a9c69a8567a0aca12042f12bba25d3139fd5dd8eeb9931f4d9e8599cd"}, - {file = "aiohttp-3.10.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6d1ad868624f6cea77341ef2877ad4e71f7116834a6cd7ec36ec5c32f94ee6ae"}, - {file = "aiohttp-3.10.8-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a78ba86d5a08207d1d1ad10b97aed6ea48b374b3f6831d02d0b06545ac0f181e"}, - {file = "aiohttp-3.10.8-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:aff048793d05e1ce05b62e49dccf81fe52719a13f4861530706619506224992b"}, - {file = "aiohttp-3.10.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d088ca05381fd409793571d8e34eca06daf41c8c50a05aeed358d2d340c7af81"}, - {file = "aiohttp-3.10.8-cp39-cp39-win32.whl", hash = "sha256:ee97c4e54f457c366e1f76fbbf3e8effee9de57dae671084a161c00f481106ce"}, - {file = "aiohttp-3.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:d95ae4420669c871667aad92ba8cce6251d61d79c1a38504621094143f94a8b4"}, - {file = "aiohttp-3.10.8.tar.gz", hash = "sha256:21f8225f7dc187018e8433c9326be01477fb2810721e048b33ac49091b19fb4a"}, + {file = "aiohttp-3.10.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8b3fb28a9ac8f2558760d8e637dbf27aef1e8b7f1d221e8669a1074d1a266bb2"}, + {file = "aiohttp-3.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91aa966858593f64c8a65cdefa3d6dc8fe3c2768b159da84c1ddbbb2c01ab4ef"}, + {file = "aiohttp-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:63649309da83277f06a15bbdc2a54fbe75efb92caa2c25bb57ca37762789c746"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3e7fabedb3fe06933f47f1538df7b3a8d78e13d7167195f51ca47ee12690373"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c070430fda1a550a1c3a4c2d7281d3b8cfc0c6715f616e40e3332201a253067"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:51d0a4901b27272ae54e42067bc4b9a90e619a690b4dc43ea5950eb3070afc32"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fec5fac7aea6c060f317f07494961236434928e6f4374e170ef50b3001e14581"}, + {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:172ad884bb61ad31ed7beed8be776eb17e7fb423f1c1be836d5cb357a096bf12"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d646fdd74c25bbdd4a055414f0fe32896c400f38ffbdfc78c68e62812a9e0257"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e86260b76786c28acf0b5fe31c8dca4c2add95098c709b11e8c35b424ebd4f5b"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d7cafc11d70fdd8801abfc2ff276744ae4cb39d8060b6b542c7e44e5f2cfc2"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:fc262c3df78c8ff6020c782d9ce02e4bcffe4900ad71c0ecdad59943cba54442"}, + {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:482c85cf3d429844396d939b22bc2a03849cb9ad33344689ad1c85697bcba33a"}, + {file = "aiohttp-3.10.9-cp310-cp310-win32.whl", hash = "sha256:aeebd3061f6f1747c011e1d0b0b5f04f9f54ad1a2ca183e687e7277bef2e0da2"}, + {file = "aiohttp-3.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:fa430b871220dc62572cef9c69b41e0d70fcb9d486a4a207a5de4c1f25d82593"}, + {file = "aiohttp-3.10.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:16e6a51d8bc96b77f04a6764b4ad03eeef43baa32014fce71e882bd71302c7e4"}, + {file = "aiohttp-3.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8bd9125dd0cc8ebd84bff2be64b10fdba7dc6fd7be431b5eaf67723557de3a31"}, + {file = "aiohttp-3.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dcf354661f54e6a49193d0b5653a1b011ba856e0b7a76bda2c33e4c6892f34ea"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42775de0ca04f90c10c5c46291535ec08e9bcc4756f1b48f02a0657febe89b10"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d1e4185c5d7187684d41ebb50c9aeaaaa06ca1875f4c57593071b0409d2444"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2695c61cf53a5d4345a43d689f37fc0f6d3a2dc520660aec27ec0f06288d1f9"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a3f063b41cc06e8d0b3fcbbfc9c05b7420f41287e0cd4f75ce0a1f3d80729e6"}, + {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d37f4718002863b82c6f391c8efd4d3a817da37030a29e2682a94d2716209de"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2746d8994ebca1bdc55a1e998feff4e94222da709623bb18f6e5cfec8ec01baf"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6f3c6648aa123bcd73d6f26607d59967b607b0da8ffcc27d418a4b59f4c98c7c"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:558b3d223fd631ad134d89adea876e7fdb4c93c849ef195049c063ada82b7d08"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4e6cb75f8ddd9c2132d00bc03c9716add57f4beff1263463724f6398b813e7eb"}, + {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:608cecd8d58d285bfd52dbca5b6251ca8d6ea567022c8a0eaae03c2589cd9af9"}, + {file = "aiohttp-3.10.9-cp311-cp311-win32.whl", hash = "sha256:36d4fba838be5f083f5490ddd281813b44d69685db910907636bc5dca6322316"}, + {file = "aiohttp-3.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:8be1a65487bdfc285bd5e9baf3208c2132ca92a9b4020e9f27df1b16fab998a9"}, + {file = "aiohttp-3.10.9-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4fd16b30567c5b8e167923be6e027eeae0f20cf2b8a26b98a25115f28ad48ee0"}, + {file = "aiohttp-3.10.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:40ff5b7660f903dc587ed36ef08a88d46840182d9d4b5694e7607877ced698a1"}, + {file = "aiohttp-3.10.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4edc3fd701e2b9a0d605a7b23d3de4ad23137d23fc0dbab726aa71d92f11aaaf"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e525b69ee8a92c146ae5b4da9ecd15e518df4d40003b01b454ad694a27f498b5"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5002a02c17fcfd796d20bac719981d2fca9c006aac0797eb8f430a58e9d12431"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4ceeae2fb8cabdd1b71c82bfdd39662473d3433ec95b962200e9e752fb70d0"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6e395c3d1f773cf0651cd3559e25182eb0c03a2777b53b4575d8adc1149c6e9"}, + {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbdb8def5268f3f9cd753a265756f49228a20ed14a480d151df727808b4531dd"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f82ace0ec57c94aaf5b0e118d4366cff5889097412c75aa14b4fd5fc0c44ee3e"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6ebdc3b3714afe1b134b3bbeb5f745eed3ecbcff92ab25d80e4ef299e83a5465"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f9ca09414003c0e96a735daa1f071f7d7ed06962ef4fa29ceb6c80d06696d900"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1298b854fd31d0567cbb916091be9d3278168064fca88e70b8468875ef9ff7e7"}, + {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:60ad5b8a7452c0f5645c73d4dad7490afd6119d453d302cd5b72b678a85d6044"}, + {file = "aiohttp-3.10.9-cp312-cp312-win32.whl", hash = "sha256:1a0ee6c0d590c917f1b9629371fce5f3d3f22c317aa96fbdcce3260754d7ea21"}, + {file = "aiohttp-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:c46131c6112b534b178d4e002abe450a0a29840b61413ac25243f1291613806a"}, + {file = "aiohttp-3.10.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2bd9f3eac515c16c4360a6a00c38119333901b8590fe93c3257a9b536026594d"}, + {file = "aiohttp-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8cc0d13b4e3b1362d424ce3f4e8c79e1f7247a00d792823ffd640878abf28e56"}, + {file = "aiohttp-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ba1a599255ad6a41022e261e31bc2f6f9355a419575b391f9655c4d9e5df5ff5"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:776e9f3c9b377fcf097c4a04b241b15691e6662d850168642ff976780609303c"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8debb45545ad95b58cc16c3c1cc19ad82cffcb106db12b437885dbee265f0ab5"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2555e4949c8d8782f18ef20e9d39730d2656e218a6f1a21a4c4c0b56546a02e"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c54dc329cd44f7f7883a9f4baaefe686e8b9662e2c6c184ea15cceee587d8d69"}, + {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e709d6ac598c5416f879bb1bae3fd751366120ac3fa235a01de763537385d036"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:17c272cfe7b07a5bb0c6ad3f234e0c336fb53f3bf17840f66bd77b5815ab3d16"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c21c82df33b264216abffff9f8370f303dab65d8eee3767efbbd2734363f677"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9331dd34145ff105177855017920dde140b447049cd62bb589de320fd6ddd582"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ac3196952c673822ebed8871cf8802e17254fff2a2ed4835d9c045d9b88c5ec7"}, + {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2c33fa6e10bb7ed262e3ff03cc69d52869514f16558db0626a7c5c61dde3c29f"}, + {file = "aiohttp-3.10.9-cp313-cp313-win32.whl", hash = "sha256:a14e4b672c257a6b94fe934ee62666bacbc8e45b7876f9dd9502d0f0fe69db16"}, + {file = "aiohttp-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:a35ed3d03910785f7d9d6f5381f0c24002b2b888b298e6f941b2fc94c5055fcd"}, + {file = "aiohttp-3.10.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f392ef50e22c31fa49b5a46af7f983fa3f118f3eccb8522063bee8bfa6755f8"}, + {file = "aiohttp-3.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d1f5c9169e26db6a61276008582d945405b8316aae2bb198220466e68114a0f5"}, + {file = "aiohttp-3.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8d9d10d10ec27c0d46ddaecc3c5598c4db9ce4e6398ca872cdde0525765caa2f"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d97273a52d7f89a75b11ec386f786d3da7723d7efae3034b4dda79f6f093edc1"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d271f770b52e32236d945911b2082f9318e90ff835d45224fa9e28374303f729"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7003f33f5f7da1eb02f0446b0f8d2ccf57d253ca6c2e7a5732d25889da82b517"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6e00c8a92e7663ed2be6fcc08a2997ff06ce73c8080cd0df10cc0321a3168d7"}, + {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a61df62966ce6507aafab24e124e0c3a1cfbe23c59732987fc0fd0d71daa0b88"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:60555211a006d26e1a389222e3fab8cd379f28e0fbf7472ee55b16c6c529e3a6"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d15a29424e96fad56dc2f3abed10a89c50c099f97d2416520c7a543e8fddf066"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:a19caae0d670771ea7854ca30df76f676eb47e0fd9b2ee4392d44708f272122d"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:99f9678bf0e2b1b695e8028fedac24ab6770937932eda695815d5a6618c37e04"}, + {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2914caa46054f3b5ff910468d686742ff8cff54b8a67319d75f5d5945fd0a13d"}, + {file = "aiohttp-3.10.9-cp38-cp38-win32.whl", hash = "sha256:0bc059ecbce835630e635879f5f480a742e130d9821fbe3d2f76610a6698ee25"}, + {file = "aiohttp-3.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:e883b61b75ca6efc2541fcd52a5c8ccfe288b24d97e20ac08fdf343b8ac672ea"}, + {file = "aiohttp-3.10.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fcd546782d03181b0b1d20b43d612429a90a68779659ba8045114b867971ab71"}, + {file = "aiohttp-3.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:85711eec2d875cd88c7eb40e734c4ca6d9ae477d6f26bd2b5bb4f7f60e41b156"}, + {file = "aiohttp-3.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:02d1d6610588bcd743fae827bd6f2e47e0d09b346f230824b4c6fb85c6065f9c"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3668d0c2a4d23fb136a753eba42caa2c0abbd3d9c5c87ee150a716a16c6deec1"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7c071235a47d407b0e93aa6262b49422dbe48d7d8566e1158fecc91043dd948"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac74e794e3aee92ae8f571bfeaa103a141e409863a100ab63a253b1c53b707eb"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bbf94d4a0447705b7775417ca8bb8086cc5482023a6e17cdc8f96d0b1b5aba6"}, + {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb0b2d5d51f96b6cc19e6ab46a7b684be23240426ae951dcdac9639ab111b45e"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e83dfefb4f7d285c2d6a07a22268344a97d61579b3e0dce482a5be0251d672ab"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f0a44bb40b6aaa4fb9a5c1ee07880570ecda2065433a96ccff409c9c20c1624a"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c2b627d3c8982691b06d89d31093cee158c30629fdfebe705a91814d49b554f8"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:03690541e4cc866eef79626cfa1ef4dd729c5c1408600c8cb9e12e1137eed6ab"}, + {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad3675c126f2a95bde637d162f8231cff6bc0bc9fbe31bd78075f9ff7921e322"}, + {file = "aiohttp-3.10.9-cp39-cp39-win32.whl", hash = "sha256:1321658f12b6caffafdc35cfba6c882cb014af86bef4e78c125e7e794dfb927b"}, + {file = "aiohttp-3.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:9fdf5c839bf95fc67be5794c780419edb0dbef776edcfc6c2e5e2ffd5ee755fa"}, + {file = "aiohttp-3.10.9.tar.gz", hash = "sha256:143b0026a9dab07a05ad2dd9e46aa859bffdd6348ddc5967b42161168c24f857"}, ] [package.dependencies] @@ -196,6 +196,24 @@ docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphi tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +[[package]] +name = "beartype" +version = "0.19.0" +description = "Unbearably fast near-real-time hybrid runtime-static type-checking in pure Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "beartype-0.19.0-py3-none-any.whl", hash = "sha256:33b2694eda0daf052eb2aff623ed9a8a586703bbf0a90bbc475a83bbf427f699"}, + {file = "beartype-0.19.0.tar.gz", hash = "sha256:de42dfc1ba5c3710fde6c3002e3bd2cad236ed4d2aabe876345ab0b4234a6573"}, +] + +[package.extras] +dev = ["autoapi (>=0.9.0)", "coverage (>=5.5)", "equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pydata-sphinx-theme (<=0.7.2)", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] +doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)"] +test = ["coverage (>=5.5)", "equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] +test-tox = ["equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "typing-extensions (>=3.10.0.0)"] +test-tox-coverage = ["coverage (>=5.5)"] + [[package]] name = "beautifulsoup4" version = "4.12.3" @@ -394,6 +412,26 @@ files = [ {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, ] +[[package]] +name = "dnspython" +version = "2.7.0" +description = "DNS toolkit" +optional = false +python-versions = ">=3.9" +files = [ + {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, + {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, +] + +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "hypercorn (>=0.16.0)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "quart-trio (>=0.11.0)", "sphinx (>=7.2.0)", "sphinx-rtd-theme (>=2.0.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=43)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=1.0.0)"] +idna = ["idna (>=3.7)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] + [[package]] name = "duckduckgo-search" version = "6.2.13" @@ -413,6 +451,21 @@ primp = ">=0.6.3" dev = ["mypy (>=1.11.1)", "pytest (>=8.3.1)", "pytest-asyncio (>=0.23.8)", "ruff (>=0.6.1)"] lxml = ["lxml (>=5.2.2)"] +[[package]] +name = "email-validator" +version = "2.2.0" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"}, + {file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + [[package]] name = "fastapi" version = "0.115.0" @@ -628,13 +681,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.5" +version = "1.0.6" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, + {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, + {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, ] [package.dependencies] @@ -645,7 +698,7 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] +trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" @@ -836,18 +889,18 @@ files = [ [[package]] name = "langchain" -version = "0.3.1" +version = "0.3.2" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "langchain-0.3.1-py3-none-any.whl", hash = "sha256:94e5ee7464d4366e4b158aa5704953c39701ea237b9ed4b200096d49e83bb3ae"}, - {file = "langchain-0.3.1.tar.gz", hash = "sha256:54d6e3abda2ec056875a231a418a4130ba7576e629e899067e499bfc847b7586"}, + {file = "langchain-0.3.2-py3-none-any.whl", hash = "sha256:cf005dcba132e46fb5e8d3dfaf7f8751bffd2d73e738c36be58f41edc7e3a4b8"}, + {file = "langchain-0.3.2.tar.gz", hash = "sha256:dc330e6eb10d81d23ba0305d18358702c73cc59e95c410eca6c6779aab4ddc9b"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" -langchain-core = ">=0.3.6,<0.4.0" +langchain-core = ">=0.3.8,<0.4.0" langchain-text-splitters = ">=0.3.0,<0.4.0" langsmith = ">=0.1.17,<0.2.0" numpy = {version = ">=1.26.0,<2.0.0", markers = "python_version >= \"3.12\""} @@ -883,13 +936,13 @@ tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<9.0.0" [[package]] name = "langchain-core" -version = "0.3.6" +version = "0.3.9" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "langchain_core-0.3.6-py3-none-any.whl", hash = "sha256:7bb3df0117bdc628b18b6c8748de72c6f537d745d47566053ce6650d5712281c"}, - {file = "langchain_core-0.3.6.tar.gz", hash = "sha256:eb190494a5483f1965f693bb2085edb523370b20fc52dc294d3bd425773cd076"}, + {file = "langchain_core-0.3.9-py3-none-any.whl", hash = "sha256:26efa048666c7de56d0ab311de2c0778b04cbb2ffe95bff76139118f13815d01"}, + {file = "langchain_core-0.3.9.tar.gz", hash = "sha256:7a6ac988d24d0ddce5874b28f538cd95f69f502b7f50581de22aca0dc58199a8"}, ] [package.dependencies] @@ -920,13 +973,13 @@ langchain-core = ">=0.3.0,<0.4.0" [[package]] name = "langsmith" -version = "0.1.129" +version = "0.1.131" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.129-py3-none-any.whl", hash = "sha256:31393fbbb17d6be5b99b9b22d530450094fab23c6c37281a6a6efb2143d05347"}, - {file = "langsmith-0.1.129.tar.gz", hash = "sha256:6c3ba66471bef41b9f87da247cc0b493268b3f54656f73648a256a205261b6a0"}, + {file = "langsmith-0.1.131-py3-none-any.whl", hash = "sha256:80c106b1c42307195cc0bb3a596472c41ef91b79d15bcee9938307800336c563"}, + {file = "langsmith-0.1.131.tar.gz", hash = "sha256:626101a3bf3ca481e5110d5155ace8aa066e4e9cc2fa7d96c8290ade0fbff797"}, ] [package.dependencies] @@ -937,6 +990,7 @@ pydantic = [ {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, ] requests = ">=2,<3" +requests-toolbelt = ">=1.0.0,<2.0.0" [[package]] name = "libcst" @@ -1338,13 +1392,13 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "openai" -version = "1.50.2" +version = "1.51.0" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.50.2-py3-none-any.whl", hash = "sha256:822dd2051baa3393d0d5406990611975dd6f533020dc9375a34d4fe67e8b75f7"}, - {file = "openai-1.50.2.tar.gz", hash = "sha256:3987ae027152fc8bea745d60b02c8f4c4a76e1b5c70e73565fa556db6f78c9e6"}, + {file = "openai-1.51.0-py3-none-any.whl", hash = "sha256:d9affafb7e51e5a27dce78589d4964ce4d6f6d560307265933a94b2e3f3c5d2c"}, + {file = "openai-1.51.0.tar.gz", hash = "sha256:8dc4f9d75ccdd5466fc8c99a952186eddceb9fd6ba694044773f3736a847149d"}, ] [package.dependencies] @@ -1527,6 +1581,7 @@ files = [ [package.dependencies] annotated-types = ">=0.6.0" +email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""} pydantic-core = "2.23.4" typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} @@ -1916,31 +1971,45 @@ requests = ">=2.0.0" [package.extras] rsa = ["oauthlib[signedtoken] (>=3.0.0)"] +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +description = "A utility belt for advanced users of python-requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, + {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, +] + +[package.dependencies] +requests = ">=2.0.1,<3.0.0" + [[package]] name = "ruff" -version = "0.6.8" +version = "0.6.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.6.8-py3-none-linux_armv6l.whl", hash = "sha256:77944bca110ff0a43b768f05a529fecd0706aac7bcce36d7f1eeb4cbfca5f0f2"}, - {file = "ruff-0.6.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:27b87e1801e786cd6ede4ada3faa5e254ce774de835e6723fd94551464c56b8c"}, - {file = "ruff-0.6.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd48f945da2a6334f1793d7f701725a76ba93bf3d73c36f6b21fb04d5338dcf5"}, - {file = "ruff-0.6.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:677e03c00f37c66cea033274295a983c7c546edea5043d0c798833adf4cf4c6f"}, - {file = "ruff-0.6.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9f1476236b3eacfacfc0f66aa9e6cd39f2a624cb73ea99189556015f27c0bdeb"}, - {file = "ruff-0.6.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f5a2f17c7d32991169195d52a04c95b256378bbf0de8cb98478351eb70d526f"}, - {file = "ruff-0.6.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5fd0d4b7b1457c49e435ee1e437900ced9b35cb8dc5178921dfb7d98d65a08d0"}, - {file = "ruff-0.6.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8034b19b993e9601f2ddf2c517451e17a6ab5cdb1c13fdff50c1442a7171d87"}, - {file = "ruff-0.6.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cfb227b932ba8ef6e56c9f875d987973cd5e35bc5d05f5abf045af78ad8e098"}, - {file = "ruff-0.6.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef0411eccfc3909269fed47c61ffebdcb84a04504bafa6b6df9b85c27e813b0"}, - {file = "ruff-0.6.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:007dee844738c3d2e6c24ab5bc7d43c99ba3e1943bd2d95d598582e9c1b27750"}, - {file = "ruff-0.6.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ce60058d3cdd8490e5e5471ef086b3f1e90ab872b548814e35930e21d848c9ce"}, - {file = "ruff-0.6.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1085c455d1b3fdb8021ad534379c60353b81ba079712bce7a900e834859182fa"}, - {file = "ruff-0.6.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:70edf6a93b19481affd287d696d9e311388d808671bc209fb8907b46a8c3af44"}, - {file = "ruff-0.6.8-py3-none-win32.whl", hash = "sha256:792213f7be25316f9b46b854df80a77e0da87ec66691e8f012f887b4a671ab5a"}, - {file = "ruff-0.6.8-py3-none-win_amd64.whl", hash = "sha256:ec0517dc0f37cad14a5319ba7bba6e7e339d03fbf967a6d69b0907d61be7a263"}, - {file = "ruff-0.6.8-py3-none-win_arm64.whl", hash = "sha256:8d3bb2e3fbb9875172119021a13eed38849e762499e3cfde9588e4b4d70968dc"}, - {file = "ruff-0.6.8.tar.gz", hash = "sha256:a5bf44b1aa0adaf6d9d20f86162b34f7c593bfedabc51239953e446aefc8ce18"}, + {file = "ruff-0.6.9-py3-none-linux_armv6l.whl", hash = "sha256:064df58d84ccc0ac0fcd63bc3090b251d90e2a372558c0f057c3f75ed73e1ccd"}, + {file = "ruff-0.6.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:140d4b5c9f5fc7a7b074908a78ab8d384dd7f6510402267bc76c37195c02a7ec"}, + {file = "ruff-0.6.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53fd8ca5e82bdee8da7f506d7b03a261f24cd43d090ea9db9a1dc59d9313914c"}, + {file = "ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645d7d8761f915e48a00d4ecc3686969761df69fb561dd914a773c1a8266e14e"}, + {file = "ruff-0.6.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eae02b700763e3847595b9d2891488989cac00214da7f845f4bcf2989007d577"}, + {file = "ruff-0.6.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d5ccc9e58112441de8ad4b29dcb7a86dc25c5f770e3c06a9d57e0e5eba48829"}, + {file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:417b81aa1c9b60b2f8edc463c58363075412866ae4e2b9ab0f690dc1e87ac1b5"}, + {file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c866b631f5fbce896a74a6e4383407ba7507b815ccc52bcedabb6810fdb3ef7"}, + {file = "ruff-0.6.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b118afbb3202f5911486ad52da86d1d52305b59e7ef2031cea3425142b97d6f"}, + {file = "ruff-0.6.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67267654edc23c97335586774790cde402fb6bbdb3c2314f1fc087dee320bfa"}, + {file = "ruff-0.6.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3ef0cc774b00fec123f635ce5c547dac263f6ee9fb9cc83437c5904183b55ceb"}, + {file = "ruff-0.6.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:12edd2af0c60fa61ff31cefb90aef4288ac4d372b4962c2864aeea3a1a2460c0"}, + {file = "ruff-0.6.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:55bb01caeaf3a60b2b2bba07308a02fca6ab56233302406ed5245180a05c5625"}, + {file = "ruff-0.6.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:925d26471fa24b0ce5a6cdfab1bb526fb4159952385f386bdcc643813d472039"}, + {file = "ruff-0.6.9-py3-none-win32.whl", hash = "sha256:eb61ec9bdb2506cffd492e05ac40e5bc6284873aceb605503d8494180d6fc84d"}, + {file = "ruff-0.6.9-py3-none-win_amd64.whl", hash = "sha256:785d31851c1ae91f45b3d8fe23b8ae4b5170089021fbb42402d811135f0b7117"}, + {file = "ruff-0.6.9-py3-none-win_arm64.whl", hash = "sha256:a9641e31476d601f83cd602608739a0840e348bda93fec9f1ee816f8b6798b93"}, + {file = "ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2"}, ] [[package]] @@ -2144,13 +2213,13 @@ test = ["pytest", "tornado (>=4.5)", "typeguard"] [[package]] name = "termcolor" -version = "2.4.0" +version = "2.5.0" description = "ANSI color formatting for output in terminal" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"}, - {file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"}, + {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"}, + {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"}, ] [package.extras] @@ -2393,4 +2462,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "09de1366659448cf284d8db6f8b7ed615e75f1aa44c1684868905e1c86780ac4" +content-hash = "4f933143b7f17beaa1c4e8bdc117978de07df01f9b8b0eb4eb11f88182230ee5" diff --git a/integrations-service/pyproject.toml b/integrations-service/pyproject.toml index 584efa480..33173f2c2 100644 --- a/integrations-service/pyproject.toml +++ b/integrations-service/pyproject.toml @@ -10,7 +10,7 @@ langchain-community = "^0.3.0" fastapi = "^0.115.0" uvicorn = "^0.30.6" langchain = "^0.3.0" -pydantic = "^2.9.2" +pydantic = {extras = ["email"], version = "^2.9.2"} duckduckgo-search = "^6.2.13" openai = "^1.47.1" tweepy = "^4.14.0" @@ -20,6 +20,7 @@ pyowm = "^3.3.0" spider-client = "^0.0.70" browserbase = "^0.3.0" setuptools = "^75.1.0" +beartype = "^0.19.0" [tool.poe.tasks] format = "ruff format" @@ -38,4 +39,4 @@ ruff = "^0.6.8" [build-system] requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" \ No newline at end of file +build-backend = "poetry.core.masonry.api" diff --git a/typespec/common/scalars.tsp b/typespec/common/scalars.tsp index dc206fa02..95c92d0b8 100644 --- a/typespec/common/scalars.tsp +++ b/typespec/common/scalars.tsp @@ -55,22 +55,3 @@ scalar PyExpression extends string; /** A valid jinja template. */ scalar JinjaTemplate extends string; - -/** Integration provider name */ -alias integrationProvider = ( - | "dummy" - | "hacker_news" - | "weather" - | "wikipedia" - | "spider" - | "brave" - | "browserbase" - // | "dalle_image_generator" - // | "duckduckgo_search" - // | "twitter" - // | "webpage" - // | "requests" -); - -/** A valid HTTP method */ -alias httpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "CONNECT" | "TRACE"; diff --git a/typespec/tasks/steps.tsp b/typespec/tasks/steps.tsp index 7a5f6d5b9..1d8c19209 100644 --- a/typespec/tasks/steps.tsp +++ b/typespec/tasks/steps.tsp @@ -48,8 +48,6 @@ alias MappableWorkflowStep = | GetStep | SetStep | LogStep - | EmbedStep - | SearchStep | YieldStep; alias NonConditionalWorkflowStep = @@ -159,34 +157,6 @@ model LogStepDef { log: JinjaTemplate; } -//////////////////////// -/// Doc search steps /// -//////////////////////// - -model EmbedStep extends BaseWorkflowStep<"embed"> { - @visibility("read") - kind_: "embed" = "embed"; - - ...EmbedStepDef; -} - -model EmbedStepDef { - /** The text to embed */ - embed: EmbedQueryRequest; -} - -model SearchStep extends BaseWorkflowStep<"search"> { - @visibility("read") - kind_: "search" = "search"; - - ...SearchStepDef; -} - -model SearchStepDef { - /** The search query */ - search: DocSearchRequest; -} - /////////////////////// /// Key-value steps /// /////////////////////// diff --git a/typespec/tools/models.tsp b/typespec/tools/models.tsp index 61918a4f7..de509dec4 100644 --- a/typespec/tools/models.tsp +++ b/typespec/tools/models.tsp @@ -8,6 +8,23 @@ namespace Tools; // TOOL MODELS // +// TODO: Split these into different files + +/** A valid HTTP method */ +alias httpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "CONNECT" | "TRACE"; + +/** Integration provider name */ +alias integrationProvider = ( + | "dummy" + | "hacker_news" + | "weather" + | "wikipedia" + | "spider" + | "brave" + | "browserbase" + | "email" +); + enum ToolType { /** A tool that emulates a function call */ function, @@ -42,6 +59,8 @@ model FunctionDef { } +// TODO: Add granular definitions for each integration + /** Integration definition */ model IntegrationDef { /** The provider of the integration */ @@ -93,6 +112,8 @@ alias operationType = ( | "list" ); +// TODO: Add granular definitions for each system call + /** System definition */ model SystemDef { /** Resource is the name of the resource to use */ diff --git a/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml b/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml index 7a7afc3e9..d00a5b9d2 100644 --- a/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml +++ b/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml @@ -3871,8 +3871,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -3901,8 +3899,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -3935,8 +3931,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -3971,8 +3965,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -4035,8 +4027,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4071,8 +4061,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -4105,36 +4093,6 @@ components: discriminator: propertyName: kind_ description: Payload for creating a task - Tasks.EmbedStep: - type: object - required: - - kind_ - - embed - properties: - kind_: - type: string - enum: - - embed - default: embed - readOnly: true - embed: - allOf: - - $ref: '#/components/schemas/Docs.EmbedQueryRequest' - description: The text to embed - allOf: - - type: object - required: - - kind_ - properties: - kind_: - type: string - enum: - - embed - description: The kind of step - readOnly: true - discriminator: - propertyName: kind_ - mapping: {} Tasks.ErrorWorkflowStep: type: object required: @@ -4215,8 +4173,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration Tasks.ForeachDoUpdateItem: @@ -4239,8 +4195,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration Tasks.ForeachStep: @@ -4346,8 +4300,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4363,8 +4315,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4407,8 +4357,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4424,8 +4372,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4496,8 +4442,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' maxItems: 100 description: The steps to run in parallel. Max concurrency will depend on the platform. @@ -4530,8 +4474,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' maxItems: 100 description: The steps to run in parallel. Max concurrency will depend on the platform. @@ -4560,8 +4502,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4589,8 +4529,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -4648,8 +4586,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4677,8 +4613,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5001,38 +4935,6 @@ components: discriminator: propertyName: kind_ mapping: {} - Tasks.SearchStep: - type: object - required: - - kind_ - - search - properties: - kind_: - type: string - enum: - - search - default: search - readOnly: true - search: - anyOf: - - $ref: '#/components/schemas/Docs.VectorDocSearchRequest' - - $ref: '#/components/schemas/Docs.TextOnlyDocSearchRequest' - - $ref: '#/components/schemas/Docs.HybridDocSearchRequest' - description: The search query - allOf: - - type: object - required: - - kind_ - properties: - kind_: - type: string - enum: - - search - description: The kind of step - readOnly: true - discriminator: - propertyName: kind_ - mapping: {} Tasks.SetStep: type: object required: @@ -5210,8 +5112,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5246,8 +5146,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5324,8 +5222,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5360,8 +5256,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5496,8 +5390,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5532,8 +5424,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5596,8 +5486,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5632,8 +5520,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5967,6 +5853,7 @@ components: - spider - brave - browserbase + - email - type: string description: The provider of the integration method: @@ -5995,6 +5882,7 @@ components: - spider - brave - browserbase + - email - type: string description: The provider of the integration method: diff --git a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml index d82540194..b3f3919a9 100644 --- a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml +++ b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml @@ -3871,8 +3871,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -3901,8 +3899,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -3935,8 +3931,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -3971,8 +3965,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -4035,8 +4027,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4071,8 +4061,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -4105,36 +4093,6 @@ components: discriminator: propertyName: kind_ description: Payload for creating a task - Tasks.EmbedStep: - type: object - required: - - kind_ - - embed - properties: - kind_: - type: string - enum: - - embed - default: embed - readOnly: true - embed: - allOf: - - $ref: '#/components/schemas/Docs.EmbedQueryRequest' - description: The text to embed - allOf: - - type: object - required: - - kind_ - properties: - kind_: - type: string - enum: - - embed - description: The kind of step - readOnly: true - discriminator: - propertyName: kind_ - mapping: {} Tasks.ErrorWorkflowStep: type: object required: @@ -4215,8 +4173,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration Tasks.ForeachDoUpdateItem: @@ -4239,8 +4195,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration Tasks.ForeachStep: @@ -4346,8 +4300,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4363,8 +4315,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4407,8 +4357,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4424,8 +4372,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4496,8 +4442,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' maxItems: 100 description: The steps to run in parallel. Max concurrency will depend on the platform. @@ -4530,8 +4474,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' maxItems: 100 description: The steps to run in parallel. Max concurrency will depend on the platform. @@ -4560,8 +4502,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4589,8 +4529,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -4648,8 +4586,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -4677,8 +4613,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5001,38 +4935,6 @@ components: discriminator: propertyName: kind_ mapping: {} - Tasks.SearchStep: - type: object - required: - - kind_ - - search - properties: - kind_: - type: string - enum: - - search - default: search - readOnly: true - search: - anyOf: - - $ref: '#/components/schemas/Docs.VectorDocSearchRequest' - - $ref: '#/components/schemas/Docs.TextOnlyDocSearchRequest' - - $ref: '#/components/schemas/Docs.HybridDocSearchRequest' - description: The search query - allOf: - - type: object - required: - - kind_ - properties: - kind_: - type: string - enum: - - search - description: The kind of step - readOnly: true - discriminator: - propertyName: kind_ - mapping: {} Tasks.SetStep: type: object required: @@ -5210,8 +5112,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5246,8 +5146,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5324,8 +5222,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5360,8 +5256,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5496,8 +5390,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5532,8 +5424,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5596,8 +5486,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' - $ref: '#/components/schemas/Tasks.ReturnStep' - $ref: '#/components/schemas/Tasks.SleepStep' @@ -5632,8 +5520,6 @@ components: - $ref: '#/components/schemas/Tasks.GetStep' - $ref: '#/components/schemas/Tasks.SetStep' - $ref: '#/components/schemas/Tasks.LogStep' - - $ref: '#/components/schemas/Tasks.EmbedStep' - - $ref: '#/components/schemas/Tasks.SearchStep' - $ref: '#/components/schemas/Tasks.YieldStep' description: The steps to run for each iteration reduce: @@ -5967,6 +5853,7 @@ components: - spider - brave - browserbase + - email - type: string description: The provider of the integration method: @@ -5995,6 +5882,7 @@ components: - spider - brave - browserbase + - email - type: string description: The provider of the integration method: From 00af85d9c845c38b9d03ec27584fc0299955bb8e Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 01:16:26 -0400 Subject: [PATCH 19/23] fix: Add developer_id constraints in all queries when possible (#603) Signed-off-by: Diwank Singh Tomer ---- > [!IMPORTANT] > Add developer_id constraints to database queries and introduce environment flags for developer verification. > > - **Behavior**: > - Add `developer_id` constraints to queries in `create_or_update_agent.py`, `get_agent.py`, `prepare_session_data.py`, `create_or_update_user.py`, and `patch_user.py` to ensure operations are scoped to the correct developer. > - Introduce `do_verify_developer` and `do_verify_developer_owns_resource` flags in `env.py` to toggle developer verification. > - **Queries**: > - Modify queries in `create_or_update_agent.py` and `get_agent.py` to include `developer_id` in input and match conditions. > - Update `prepare_session_data.py` to pass `developer_id` in session-related queries. > - Add `developer_id` checks in `create_or_update_user.py` and `patch_user.py` for user operations. > - **Utils**: > - Update `verify_developer_id_query` and `verify_developer_owns_resource_query` in `utils.py` to respect new environment flags. > > This description was created by [Ellipsis](https://www.ellipsis.dev?ref=julep-ai%2Fjulep&utm_source=github&utm_medium=referral) for 09d8dadf50f44e4db93df5de89d2832be8dd4aad. It will automatically update as commits are pushed. Signed-off-by: Diwank Singh Tomer --- agents-api/agents_api/env.py | 4 ++++ .../models/agent/create_or_update_agent.py | 2 ++ agents-api/agents_api/models/agent/get_agent.py | 1 + .../models/session/prepare_session_data.py | 14 +++++++++++--- .../models/user/create_or_update_user.py | 2 ++ agents-api/agents_api/models/user/patch_user.py | 2 ++ agents-api/agents_api/models/utils.py | 7 +++++++ 7 files changed, 29 insertions(+), 3 deletions(-) diff --git a/agents-api/agents_api/env.py b/agents-api/agents_api/env.py index 42b2ce8d2..2b016fd40 100644 --- a/agents-api/agents_api/env.py +++ b/agents-api/agents_api/env.py @@ -40,6 +40,10 @@ summarization_model_name: str = env.str( "SUMMARIZATION_MODEL_NAME", default="gpt-4-turbo" ) +do_verify_developer: bool = env.bool("DO_VERIFY_DEVELOPER", default=True) +do_verify_developer_owns_resource: bool = env.bool( + "DO_VERIFY_DEVELOPER_OWNS_RESOURCE", default=True +) # Auth diff --git a/agents-api/agents_api/models/agent/create_or_update_agent.py b/agents-api/agents_api/models/agent/create_or_update_agent.py index 3902c1bb5..8a3975183 100644 --- a/agents-api/agents_api/models/agent/create_or_update_agent.py +++ b/agents-api/agents_api/models/agent/create_or_update_agent.py @@ -136,6 +136,7 @@ def create_or_update_agent( input[_agent_id, developer_id, model, name, about, metadata, instructions, updated_at], *agents{ agent_id, + developer_id, created_at, }, agent_id = to_uuid(_agent_id), @@ -144,6 +145,7 @@ def create_or_update_agent( input[_agent_id, developer_id, model, name, about, metadata, instructions, updated_at], not *agents{ agent_id, + developer_id, }, created_at = now(), agent_id = to_uuid(_agent_id), diff --git a/agents-api/agents_api/models/agent/get_agent.py b/agents-api/agents_api/models/agent/get_agent.py index bdae85fcb..008e39454 100644 --- a/agents-api/agents_api/models/agent/get_agent.py +++ b/agents-api/agents_api/models/agent/get_agent.py @@ -71,6 +71,7 @@ def get_agent(*, developer_id: UUID, agent_id: UUID) -> tuple[list[str], dict]: instructions, ] := input[id], *agents { + developer_id: to_uuid($developer_id), agent_id: id, model, name, diff --git a/agents-api/agents_api/models/session/prepare_session_data.py b/agents-api/agents_api/models/session/prepare_session_data.py index bbbd9c4cd..83ee0c219 100644 --- a/agents-api/agents_api/models/session/prepare_session_data.py +++ b/agents-api/agents_api/models/session/prepare_session_data.py @@ -56,12 +56,13 @@ def prepare_session_data( # This query retrieves session information by using `input` to pass parameters, get_query = """ - input[session_id] <- [[ + input[session_id, developer_id] <- [[ to_uuid($session_id), + to_uuid($developer_id), ]] participants[collect(participant_id), participant_type] := - input[session_id], + input[session_id, developer_id], *session_lookup{ session_id, participant_id, @@ -102,9 +103,11 @@ def prepare_session_data( } agent_data[collect(record)] := + input[session_id, developer_id], agents[agent_ids], agent_id in agent_ids, *agents{ + developer_id, agent_id, model, name, @@ -129,9 +132,11 @@ def prepare_session_data( # Version where we don't have default settings agent_data[collect(record)] := + input[session_id, developer_id], agents[agent_ids], agent_id in agent_ids, *agents{ + developer_id, agent_id, model, name, @@ -155,9 +160,11 @@ def prepare_session_data( } user_data[collect(record)] := + input[session_id, developer_id], users[user_ids], user_id in user_ids, *users{ + developer_id, user_id, name, about, @@ -175,8 +182,9 @@ def prepare_session_data( } session_data[record] := - input[session_id], + input[session_id, developer_id], *sessions{ + developer_id, session_id, situation, summary, diff --git a/agents-api/agents_api/models/user/create_or_update_user.py b/agents-api/agents_api/models/user/create_or_update_user.py index 97db913c5..d295d1d8a 100644 --- a/agents-api/agents_api/models/user/create_or_update_user.py +++ b/agents-api/agents_api/models/user/create_or_update_user.py @@ -70,6 +70,7 @@ def create_or_update_user( ?[user_id, developer_id, name, about, metadata, created_at, updated_at] := input[_user_id, developer_id, name, about, metadata, updated_at], *users{ + developer_id, user_id, created_at, }, @@ -78,6 +79,7 @@ def create_or_update_user( ?[user_id, developer_id, name, about, metadata, created_at, updated_at] := input[_user_id, developer_id, name, about, metadata, updated_at], not *users{ + developer_id, user_id, }, created_at = now(), user_id = to_uuid(_user_id), diff --git a/agents-api/agents_api/models/user/patch_user.py b/agents-api/agents_api/models/user/patch_user.py index 4498c6ded..265241d47 100644 --- a/agents-api/agents_api/models/user/patch_user.py +++ b/agents-api/agents_api/models/user/patch_user.py @@ -78,6 +78,7 @@ def patch_user( ?[{user_update_cols}, metadata] := input[{user_update_cols}], *users {{ + developer_id: to_uuid($developer_id), user_id: to_uuid($user_id), metadata: md, }}, @@ -101,5 +102,6 @@ def patch_user( "user_update_vals": user_update_vals, "metadata": metadata, "user_id": str(user_id), + "developer_id": str(developer_id), }, ) diff --git a/agents-api/agents_api/models/utils.py b/agents-api/agents_api/models/utils.py index c163642c0..f63646e1c 100644 --- a/agents-api/agents_api/models/utils.py +++ b/agents-api/agents_api/models/utils.py @@ -8,6 +8,7 @@ from pydantic import BaseModel from ..common.utils.cozo import uuid_int_list_to_uuid4 +from ..env import do_verify_developer, do_verify_developer_owns_resource P = ParamSpec("P") T = TypeVar("T") @@ -117,6 +118,9 @@ def mark_session_updated_query(developer_id: UUID | str, session_id: UUID | str) def verify_developer_id_query(developer_id: UUID | str) -> str: + if not do_verify_developer: + return "?[exists] := exists = true" + return f""" matched[count(developer_id)] := *developers{{ @@ -138,6 +142,9 @@ def verify_developer_owns_resource_query( parents: list[tuple[str, str]] | None = None, **resource_id, ) -> str: + if not do_verify_developer_owns_resource: + return "?[exists] := exists = true" + parents = parents or [] resource_id_key, resource_id_value = next(iter(resource_id.items())) From e36f33b785f0301999695636be2b37793f6d981b Mon Sep 17 00:00:00 2001 From: Hamada Salhab Date: Mon, 7 Oct 2024 14:32:37 +0300 Subject: [PATCH 20/23] feat(agents-api): Add doc search system tool (#604) > [!IMPORTANT] > Adds document creation and search functionalities for agents and users, updates `list_docs` with a new parameter, and refactors `base_evaluate` for complex dictionaries. > > - **Behavior**: > - Adds support for document creation and search operations in `execute_system.py` for both agents and users. > - Introduces `create_agent_doc`, `create_user_doc`, `search_agent_docs`, and `search_user_docs` functions. > - Handles `text`, `vector`, and `hybrid` search requests using `HybridDocSearchRequest`, `TextOnlyDocSearchRequest`, and `VectorDocSearchRequest`. > - Replaces `developer_id` with `x_developer_id` for certain operations. > - **Models**: > - Updates `list_docs` in `list_docs.py` to include `include_without_embeddings` parameter. > - **Misc**: > - Refactors `base_evaluate` in `base_evaluate.py` to handle nested dictionaries with string values. > > This description was created by [Ellipsis](https://www.ellipsis.dev?ref=julep-ai%2Fjulep&utm_source=github&utm_medium=referral) for 8432e9584eb68dfd4f474386933271b6e1f601ca. It will automatically update as commits are pushed. --------- Signed-off-by: Diwank Singh Tomer Co-authored-by: Diwank Singh Tomer Co-authored-by: HamadaSalhab --- .../agents_api/activities/execute_system.py | 91 ++++++++++++++++++- .../activities/task_steps/base_evaluate.py | 22 ++--- .../agents_api/models/docs/list_docs.py | 2 + 3 files changed, 100 insertions(+), 15 deletions(-) diff --git a/agents-api/agents_api/activities/execute_system.py b/agents-api/agents_api/activities/execute_system.py index 8e4d71274..8ffb85814 100644 --- a/agents-api/agents_api/activities/execute_system.py +++ b/agents-api/agents_api/activities/execute_system.py @@ -2,8 +2,15 @@ from uuid import UUID from beartype import beartype +from fastapi.background import BackgroundTasks from temporalio import activity +from ..autogen.Docs import ( + CreateDocRequest, + HybridDocSearchRequest, + TextOnlyDocSearchRequest, + VectorDocSearchRequest, +) from ..autogen.Tools import SystemDef from ..common.protocol.tasks import StepContext from ..env import testing @@ -31,6 +38,8 @@ from ..models.user.get_user import get_user as get_user_query from ..models.user.list_users import list_users as list_users_query from ..models.user.update_user import update_user as update_user_query +from ..routers.docs.create_doc import create_agent_doc, create_user_doc +from ..routers.docs.search_docs import search_agent_docs, search_user_docs @beartype @@ -63,17 +72,54 @@ async def execute_system( agent_doc_args = { **{ "owner_type": "agent", - "owner_id": arguments.pop("agent_id"), + "owner_id": arguments["agent_id"], }, **arguments, } + agent_doc_args.pop("agent_id") + if system.operation == "list": return list_docs_query(**agent_doc_args) + elif system.operation == "create": - return create_doc_query(**agent_doc_args) + # The `create_agent_doc` function requires `x_developer_id` instead of `developer_id`. + arguments["x_developer_id"] = arguments.pop("developer_id") + return await create_agent_doc( + data=CreateDocRequest(**arguments.pop("data")), + background_tasks=BackgroundTasks(), + **arguments, + ) + elif system.operation == "delete": return delete_doc_query(**agent_doc_args) + elif system.operation == "search": + # The `search_agent_docs` function requires `x_developer_id` instead of `developer_id`. + arguments["x_developer_id"] = arguments.pop("developer_id") + + if "text" in arguments and "vector" in arguments: + search_params = HybridDocSearchRequest( + text=arguments.pop("text"), + vector=arguments.pop("vector"), + limit=arguments.get("limit", 10), + ) + + elif "text" in arguments: + search_params = TextOnlyDocSearchRequest( + text=arguments.pop("text"), + limit=arguments.get("limit", 10), + ) + elif "vector" in arguments: + search_params = VectorDocSearchRequest( + vector=arguments.pop("vector"), + limit=arguments.get("limit", 10), + ) + + return await search_agent_docs( + search_params=search_params, + **arguments, + ) + # NO SUBRESOURCE elif system.subresource == None: if system.operation == "list": @@ -95,17 +141,54 @@ async def execute_system( user_doc_args = { **{ "owner_type": "user", - "owner_id": arguments.pop("user_id"), + "owner_id": arguments["user_id"], }, **arguments, } + user_doc_args.pop("user_id") + if system.operation == "list": return list_docs_query(**user_doc_args) + elif system.operation == "create": - return create_doc_query(**user_doc_args) + # The `create_user_doc` function requires `x_developer_id` instead of `developer_id`. + arguments["x_developer_id"] = arguments.pop("developer_id") + return await create_user_doc( + data=CreateDocRequest(**arguments.pop("data")), + background_tasks=BackgroundTasks(), + **arguments, + ) + elif system.operation == "delete": return delete_doc_query(**user_doc_args) + elif system.operation == "search": + # The `search_user_docs` function requires `x_developer_id` instead of `developer_id`. + arguments["x_developer_id"] = arguments.pop("developer_id") + + if "text" in arguments and "vector" in arguments: + search_params = HybridDocSearchRequest( + text=arguments.pop("text"), + vector=arguments.pop("vector"), + limit=arguments.get("limit", 10), + ) + + elif "text" in arguments: + search_params = TextOnlyDocSearchRequest( + text=arguments.pop("text"), + limit=arguments.get("limit", 10), + ) + elif "vector" in arguments: + search_params = VectorDocSearchRequest( + vector=arguments.pop("vector"), + limit=arguments.get("limit", 10), + ) + + return await search_user_docs( + search_params=search_params, + **arguments, + ) + # NO SUBRESOURCE elif system.subresource == None: if system.operation == "list": 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 3fcbf2f73..c6b83ba89 100644 --- a/agents-api/agents_api/activities/task_steps/base_evaluate.py +++ b/agents-api/agents_api/activities/task_steps/base_evaluate.py @@ -46,29 +46,29 @@ async def base_evaluate( evaluator = get_evaluator(names=values, extra_functions=extra_lambdas) try: + result = None match exprs: case str(): - return evaluator.eval(exprs) - + result = evaluator.eval(exprs) case list(): - return [evaluator.eval(expr) for expr in exprs] - - case dict() as d if all(isinstance(v, dict) for v in d.values()): - return { + result = [evaluator.eval(expr) for expr in exprs] + case dict() as d if all( + isinstance(v, dict) or isinstance(v, str) for v in d.values() + ): + result = { k: {ik: evaluator.eval(iv) for ik, iv in v.items()} + if isinstance(v, dict) + else evaluator.eval(v) for k, v in d.items() } - - case dict(): - return {k: evaluator.eval(v) for k, v in exprs.items()} - case _: raise ValueError(f"Invalid expression: {exprs}") + return result + except BaseException as e: if activity.in_activity(): activity.logger.error(f"Error in base_evaluate: {e}") - raise diff --git a/agents-api/agents_api/models/docs/list_docs.py b/agents-api/agents_api/models/docs/list_docs.py index 4dad7ec06..8f8d8c7a0 100644 --- a/agents-api/agents_api/models/docs/list_docs.py +++ b/agents-api/agents_api/models/docs/list_docs.py @@ -50,6 +50,7 @@ def list_docs( sort_by: Literal["created_at"] = "created_at", direction: Literal["asc", "desc"] = "desc", metadata_filter: dict[str, Any] = {}, + include_without_embeddings: bool = False, ) -> tuple[list[str], dict]: # Transforms the metadata_filter dictionary into a string representation for the datalog query. metadata_filter_str = ", ".join( @@ -70,6 +71,7 @@ def list_docs( content, embedding, }}, + {"" if include_without_embeddings else "not is_null(embedding),"} snippet_data = [index, content, embedding] ?[ From 5b041ca9d43466dafb3ca672c54ffb06f5561c2f Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 09:06:31 -0400 Subject: [PATCH 21/23] doc: Add devfest email assistant README Signed-off-by: Diwank Singh Tomer --- IDEAS.md | 1377 ++++++++++++++++++++ cookbooks/00-Devfest-Email-Assistant.ipynb | 296 +++++ 2 files changed, 1673 insertions(+) create mode 100644 IDEAS.md create mode 100644 cookbooks/00-Devfest-Email-Assistant.ipynb diff --git a/IDEAS.md b/IDEAS.md new file mode 100644 index 000000000..83d6d58d4 --- /dev/null +++ b/IDEAS.md @@ -0,0 +1,1377 @@ +# Expanded Implementation Scenarios for Julep + +Below are detailed implementation plans for each of the 50 scenarios using Julep's **docs**, **sessions**, **tasks**, and **executions** features. Each scenario includes a complexity rating from **1 (easiest)** to **5 (most complex)**. + +--- + +### 1. Automated Customer Support Agent + +**Implementation Using Julep:** + +- **Docs:** + - Store customer data, FAQs, and troubleshooting guides. + - Integrate CRM documentation for accessing and updating customer information. + +- **Sessions:** + - Create a persistent session for each customer to maintain conversation context. + - Track interaction history to personalize support. + +- **Tasks:** + - Define tasks for handling common inquiries (e.g., order status, billing issues). + - Implement escalation tasks for complex issues that require human intervention. + - Automate ticket creation and update processes. + +- **Executions:** + - Execute tasks based on customer inputs. + - Monitor task executions to ensure timely responses and issue resolutions. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integrating with external CRM systems, handling diverse query types, and maintaining contextual sessions, which increases complexity. + +--- + +### 2. Smart Research Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store access to academic databases and research papers. + - Include summarization templates and research methodologies. + +- **Sessions:** + - Manage user-specific research sessions to track ongoing projects and queries. + - Maintain context for multi-step research tasks. + +- **Tasks:** + - Create tasks for searching databases, summarizing articles, and compiling reports. + - Implement conditional steps based on research findings. + +- **Executions:** + - Execute research tasks sequentially or in parallel. + - Stream execution results to provide real-time updates to the user. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with academic databases, advanced summarization capabilities, and managing complex multi-step workflows. + +--- + +### 3. Personal Finance Manager + +**Implementation Using Julep:** + +- **Docs:** + - Store user financial data, budgeting templates, and investment information. + - Integrate banking API documentation for transaction fetching. + +- **Sessions:** + - Create persistent sessions to track user financial activities over time. + - Maintain context for budgeting goals and financial plans. + +- **Tasks:** + - Define tasks for expense tracking, budget creation, and investment monitoring. + - Automate alerts for budget limits and investment opportunities. + +- **Executions:** + - Execute financial tasks based on user interactions and predefined schedules. + - Monitor executions to provide real-time financial advice and updates. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Needs secure integration with banking APIs, real-time data processing, and robust budgeting logic. + +--- + +### 4. Content Creation Workflow + +**Implementation Using Julep:** + +- **Docs:** + - Store SEO guidelines, content templates, and style guides. + - Include access to keyword research tools. + +- **Sessions:** + - Manage content creation sessions to track progress and drafts. + - Maintain context for ongoing content projects. + +- **Tasks:** + - Create multi-step tasks for topic ideation, content drafting, SEO optimization, and scheduling. + - Integrate tools for grammar checking and SEO analysis. + +- **Executions:** + - Automate the execution of content creation tasks. + - Schedule publishing according to editorial calendars. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves coordinating multiple tools and steps but remains manageable with clear task definitions. + +--- + +### 5. E-commerce Order Processing System + +**Implementation Using Julep:** + +- **Docs:** + - Store product catalogs, inventory data, and order processing guidelines. + - Integrate with shipping provider APIs. + +- **Sessions:** + - Create sessions for each order to track its lifecycle. + - Maintain context for customer preferences and order history. + +- **Tasks:** + - Define tasks for order validation, inventory updates, payment processing, and shipment tracking. + - Automate customer notifications at each stage. + +- **Executions:** + - Execute order processing tasks in sequence. + - Monitor executions to handle exceptions like payment failures or inventory shortages. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires robust integrations with payment gateways, inventory systems, and shipping providers, along with handling various order states. + +--- + +### 6. AI-Powered Personal Trainer + +**Implementation Using Julep:** + +- **Docs:** + - Store workout routines, nutritional plans, and progress tracking templates. + - Include integration details for fitness tracking APIs. + +- **Sessions:** + - Create individual sessions for each user to track their fitness journey. + - Maintain context for user goals and progress. + +- **Tasks:** + - Define tasks for generating personalized workout plans, tracking progress, and adjusting routines. + - Automate reminders and motivational messages. + +- **Executions:** + - Execute fitness tasks based on user inputs and scheduled routines. + - Monitor executions to provide real-time feedback and adjustments. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves personalization and integration with fitness data sources, but achievable with well-defined task workflows. + +--- + +### 7. Automated Email Marketing Campaigns + +**Implementation Using Julep:** + +- **Docs:** + - Store email templates, segmentation criteria, and campaign schedules. + - Integrate with email marketing platforms (e.g., SendGrid, Mailchimp). + +- **Sessions:** + - Manage campaign-specific sessions to track interactions and responses. + - Maintain context for ongoing and past campaigns. + +- **Tasks:** + - Create tasks for email creation, scheduling, sending, and performance analysis. + - Automate A/B testing and content personalization. + +- **Executions:** + - Execute email campaigns based on predefined schedules and triggers. + - Monitor execution performance and adjust strategies accordingly. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with email platforms and managing dynamic content delivery, but is straightforward with clear task definitions. + +--- + +### 8. Intelligent Recruitment Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store job descriptions, candidate profiles, and evaluation criteria. + - Integrate with HR systems and job boards. + +- **Sessions:** + - Create sessions for each recruitment process to track candidate interactions. + - Maintain context for candidate status and feedback. + +- **Tasks:** + - Define tasks for resume screening, interview scheduling, and candidate communications. + - Automate feedback collection and report generation. + +- **Executions:** + - Execute recruitment tasks based on candidate actions and application stages. + - Monitor executions to ensure timely processing and compliance. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves complex integrations with HR systems, handling diverse candidate data, and ensuring compliance with recruitment processes. + +--- + +### 9. Smart Home Automation Controller + +**Implementation Using Julep:** + +- **Docs:** + - Store device configurations, automation rules, and user preferences. + - Integrate with smart home device APIs (e.g., Philips Hue, Nest). + +- **Sessions:** + - Manage user-specific sessions to track home automation settings. + - Maintain context for user routines and preferences. + +- **Tasks:** + - Create tasks for device control, routine scheduling, and energy monitoring. + - Automate actions based on triggers like time, occupancy, or environmental changes. + +- **Executions:** + - Execute home automation tasks in real-time or based on schedules. + - Monitor executions to ensure devices respond correctly and adjust settings as needed. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with multiple smart devices and managing dynamic automation rules, increasing system complexity. + +--- + +### 10. Automated Legal Document Analyzer + +**Implementation Using Julep:** + +- **Docs:** + - Store legal templates, compliance guidelines, and case studies. + - Integrate with legal databases and document repositories. + +- **Sessions:** + - Create sessions for each document analysis to track progress and findings. + - Maintain context for specific legal requirements and clauses. + +- **Tasks:** + - Define tasks for document ingestion, key information extraction, compliance checking, and summarization. + - Automate flagging of non-compliant sections and suggest necessary amendments. + +- **Executions:** + - Execute document analysis tasks sequentially or in parallel. + - Monitor executions to ensure accuracy and compliance with legal standards. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves advanced natural language processing, integration with legal databases, and ensuring compliance with intricate legal standards. + +--- + +### 11. Personalized Learning Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store educational content, learning paths, and assessment criteria. + - Integrate with educational platforms and resources. + +- **Sessions:** + - Create individual learning sessions to track user progress and preferences. + - Maintain context for personalized learning paths and goals. + +- **Tasks:** + - Define tasks for content recommendation, quiz generation, progress tracking, and feedback provision. + - Automate adjustments to learning paths based on performance. + +- **Executions:** + - Execute learning tasks based on user interactions and progress. + - Monitor executions to provide real-time feedback and adjust learning strategies. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires personalization algorithms, integration with educational content sources, and dynamic adaptation to user progress. + +--- + +### 12. AI-Driven Social Media Manager + +**Implementation Using Julep:** + +- **Docs:** + - Store social media strategies, content calendars, and engagement guidelines. + - Integrate with social media APIs (e.g., Twitter, Facebook, LinkedIn). + +- **Sessions:** + - Manage campaign-specific sessions to track posts, engagements, and analytics. + - Maintain context for ongoing and scheduled campaigns. + +- **Tasks:** + - Create tasks for content creation, scheduling, posting, and performance analysis. + - Automate engagement responses and A/B testing of content. + +- **Executions:** + - Execute social media tasks based on schedules and real-time engagement triggers. + - Monitor executions to optimize performance and adjust strategies. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with multiple social media platforms, dynamic content management, and real-time engagement handling. + +--- + +### 13. Automated Travel Itinerary Planner + +**Implementation Using Julep:** + +- **Docs:** + - Store travel guides, destination information, and booking APIs. + - Integrate with flight, hotel, and transportation service APIs. + +- **Sessions:** + - Create travel-specific sessions to track itinerary progress and user preferences. + - Maintain context for personalized travel plans and updates. + +- **Tasks:** + - Define tasks for destination research, booking accommodations and transportation, and itinerary scheduling. + - Automate real-time updates and notifications during trips. + +- **Executions:** + - Execute travel planning tasks based on user inputs and predefined schedules. + - Monitor executions to handle changes and provide timely updates. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with travel service APIs and managing dynamic itinerary changes, which adds moderate complexity. + +--- + +### 14. AI-Powered Inventory Management System + +**Implementation Using Julep:** + +- **Docs:** + - Store inventory data, supplier information, and reordering guidelines. + - Integrate with inventory tracking systems and supplier APIs. + +- **Sessions:** + - Manage inventory sessions to monitor stock levels and reorder statuses. + - Maintain context for inventory forecasts and demand trends. + +- **Tasks:** + - Create tasks for stock monitoring, demand forecasting, automatic reordering, and supplier communication. + - Automate alerts for low stock levels and order confirmations. + +- **Executions:** + - Execute inventory management tasks in real-time or based on schedules. + - Monitor executions to ensure accurate stock levels and timely reorders. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires real-time inventory tracking, predictive analytics for demand forecasting, and reliable integration with supplier systems. + +--- + +### 15. Intelligent Health Monitoring System + +**Implementation Using Julep:** + +- **Docs:** + - Store health metrics templates, medical guidelines, and user health data. + - Integrate with health tracking devices and APIs (e.g., Fitbit, Apple Health). + +- **Sessions:** + - Create sessions for each user to track their health metrics and progress. + - Maintain context for personalized health goals and alerts. + +- **Tasks:** + - Define tasks for data collection, health metric analysis, trend monitoring, and alert notifications. + - Automate health insights and recommendations based on data. + +- **Executions:** + - Execute health monitoring tasks continuously or at scheduled intervals. + - Monitor executions to provide real-time health alerts and advice. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with diverse health tracking devices, real-time data processing, and ensuring data privacy and accuracy. + +--- + +### 16. Automated Content Moderation Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store community guidelines, content policies, and moderation rules. + - Integrate with content platforms (e.g., forums, social media). + +- **Sessions:** + - Manage moderation sessions to track content reviews and decisions. + - Maintain context for specific moderation cases and user histories. + +- **Tasks:** + - Create tasks for content ingestion, automated screening, manual review, and action enforcement. + - Automate flagging of inappropriate content and notifying users of violations. + +- **Executions:** + - Execute content moderation tasks in real-time or batch processing. + - Monitor executions to ensure compliance and handle escalations. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves sophisticated content analysis, balancing automation with manual oversight, and ensuring adherence to diverse content policies. + +--- + +### 17. AI-Powered Resume Builder + +**Implementation Using Julep:** + +- **Docs:** + - Store resume templates, industry-specific keywords, and formatting guidelines. + - Integrate with LinkedIn and other professional platforms for data fetching. + +- **Sessions:** + - Create user-specific sessions to track resume building progress. + - Maintain context for personalized content and formatting preferences. + +- **Tasks:** + - Define tasks for data collection, content suggestion, resume formatting, and final export. + - Automate style checks and consistency validations. + +- **Executions:** + - Execute resume building tasks based on user inputs and selections. + - Monitor executions to provide real-time feedback and suggestions. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with professional data sources and implementing dynamic content generation and formatting. + +--- + +### 18. Smart Event Management System + +**Implementation Using Julep:** + +- **Docs:** + - Store event templates, scheduling guidelines, and registration forms. + - Integrate with calendar and email platforms. + +- **Sessions:** + - Manage event-specific sessions to track registrations, schedules, and attendee interactions. + - Maintain context for event updates and follow-ups. + +- **Tasks:** + - Create tasks for event creation, attendee registration, schedule management, and post-event follow-ups. + - Automate reminders, notifications, and feedback collection. + +- **Executions:** + - Execute event management tasks based on schedules and attendee actions. + - Monitor executions to handle registrations and event logistics seamlessly. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves coordinating multiple aspects of event planning, handling real-time registrations, and ensuring smooth execution logistics. + +--- + +### 19. Automated Survey Analyzer + +**Implementation Using Julep:** + +- **Docs:** + - Store survey templates, question types, and analysis methodologies. + - Integrate with survey distribution platforms (e.g., SurveyMonkey, Google Forms). + +- **Sessions:** + - Create sessions for each survey to track responses and analysis progress. + - Maintain context for specific survey objectives and parameters. + +- **Tasks:** + - Define tasks for survey distribution, data collection, sentiment analysis, and report generation. + - Automate data visualization and trend identification. + +- **Executions:** + - Execute survey analysis tasks upon survey completion. + - Monitor executions to provide timely and accurate insights. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with survey platforms and implementing effective data analysis and visualization techniques. + +--- + +### 20. AI-Driven Project Management Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store project templates, task guidelines, and progress tracking tools. + - Integrate with project management platforms (e.g., Jira, Trello). + +- **Sessions:** + - Manage project-specific sessions to track tasks, milestones, and team interactions. + - Maintain context for project goals and progress updates. + +- **Tasks:** + - Create tasks for task breakdown, assignment, progress tracking, and status reporting. + - Automate notifications for deadlines and task completions. + +- **Executions:** + - Execute project management tasks based on project timelines and team inputs. + - Monitor executions to ensure projects stay on track and within scope. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with diverse project management tools, handling dynamic task assignments, and ensuring effective progress tracking. + +--- + +### 21. Intelligent Document Summarizer + +**Implementation Using Julep:** + +- **Docs:** + - Store access to large documents, research papers, and reports. + - Include summarization algorithms and templates. + +- **Sessions:** + - Create sessions for each document summarization task. + - Maintain context for document sections and summarization preferences. + +- **Tasks:** + - Define tasks for document ingestion, key point extraction, and summary generation. + - Automate quality checks and user-specific summary adjustments. + +- **Executions:** + - Execute document summarization tasks efficiently. + - Monitor executions to ensure accurate and concise summaries. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires advanced natural language processing capabilities and efficient handling of large document data. + +--- + +### 22. Automated Feedback Collection and Analysis + +**Implementation Using Julep:** + +- **Docs:** + - Store feedback forms, analysis templates, and reporting guidelines. + - Integrate with feedback collection platforms (e.g., Typeform, Google Forms). + +- **Sessions:** + - Manage feedback-specific sessions to track responses and analysis progress. + - Maintain context for feedback sources and analysis objectives. + +- **Tasks:** + - Create tasks for feedback distribution, data collection, sentiment analysis, and insight generation. + - Automate categorization and prioritization of feedback. + +- **Executions:** + - Execute feedback analysis tasks promptly upon data collection. + - Monitor executions to provide actionable insights and improvement strategies. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integrating with feedback platforms and implementing effective sentiment analysis and categorization. + +--- + +### 23. AI-Powered Language Translator + +**Implementation Using Julep:** + +- **Docs:** + - Store language dictionaries, translation models, and formatting guidelines. + - Integrate with translation APIs (e.g., Google Translate, DeepL). + +- **Sessions:** + - Create translation-specific sessions to track user preferences and translation history. + - Maintain context for ongoing translation projects. + +- **Tasks:** + - Define tasks for text ingestion, language detection, translation processing, and quality assurance. + - Automate post-translation formatting and localization adjustments. + +- **Executions:** + - Execute translation tasks in real-time or batch mode. + - Monitor executions to ensure accuracy and contextual relevance. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with robust translation APIs and handling nuances of different languages and contexts. + +--- + +### 24. Smart Appointment Scheduler + +**Implementation Using Julep:** + +- **Docs:** + - Store scheduling templates, availability guidelines, and notification templates. + - Integrate with calendar platforms (e.g., Google Calendar, Outlook). + +- **Sessions:** + - Manage appointment-specific sessions to track scheduling progress and attendee interactions. + - Maintain context for user availability and preferences. + +- **Tasks:** + - Create tasks for availability checking, meeting scheduling, sending reminders, and handling cancellations. + - Automate conflict detection and resolution. + +- **Executions:** + - Execute scheduling tasks based on user inputs and calendar data. + - Monitor executions to ensure appointments are set correctly and notifications are sent. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integration with calendar systems and implementing conflict resolution logic, which adds moderate complexity. + +--- + +### 25. Automated Inventory Auditor + +**Implementation Using Julep:** + +- **Docs:** + - Store inventory audit templates, reconciliation guidelines, and reporting formats. + - Integrate with inventory management systems and databases. + +- **Sessions:** + - Create auditing sessions to track audit schedules and findings. + - Maintain context for different inventory categories and audit criteria. + +- **Tasks:** + - Define tasks for data extraction, discrepancy detection, reconciliation processes, and report generation. + - Automate audit scheduling and notification of audit results. + +- **Executions:** + - Execute inventory audit tasks periodically or on-demand. + - Monitor executions to ensure accurate and timely audits. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires reliable data integration and robust discrepancy detection mechanisms to handle complex inventory data. + +--- + +### 26. AI-Driven Competitive Analysis Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store competitor profiles, market analysis frameworks, and data sources. + - Integrate with market research APIs and competitor websites. + +- **Sessions:** + - Manage competitive analysis sessions to track data collection and analysis progress. + - Maintain context for specific market segments and competitive factors. + +- **Tasks:** + - Create tasks for data scraping, trend analysis, SWOT analysis, and report generation. + - Automate the aggregation and visualization of competitive data. + +- **Executions:** + - Execute competitive analysis tasks on a scheduled basis. + - Monitor executions to provide up-to-date insights and strategic recommendations. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves complex data scraping, accurate trend analysis, and maintaining up-to-date competitive insights, increasing overall complexity. + +--- + +### 27. Smart Recipe Generator + +**Implementation Using Julep:** + +- **Docs:** + - Store ingredient databases, recipe templates, and dietary guidelines. + - Integrate with nutrition APIs and grocery databases. + +- **Sessions:** + - Create user-specific sessions to track dietary preferences and past recipes. + - Maintain context for ingredient availability and nutritional goals. + +- **Tasks:** + - Define tasks for ingredient analysis, recipe generation, nutritional calculation, and grocery list creation. + - Automate recipe suggestions based on user inputs and constraints. + +- **Executions:** + - Execute recipe generation tasks in real-time based on user requests. + - Monitor executions to ensure recipe accuracy and adherence to dietary needs. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with nutrition and grocery APIs and implementing intelligent recipe generation logic. + +--- + +### 28. Automated Video Content Creator + +**Implementation Using Julep:** + +- **Docs:** + - Store video script templates, editing guidelines, and publishing schedules. + - Integrate with video editing and hosting platforms (e.g., Adobe Premiere, YouTube). + +- **Sessions:** + - Manage video creation sessions to track script development, editing stages, and publishing. + - Maintain context for ongoing video projects and collaboration. + +- **Tasks:** + - Create tasks for script generation, video editing, thumbnail creation, and publishing. + - Automate content review and approval workflows. + +- **Executions:** + - Execute video creation tasks based on project timelines. + - Monitor executions to ensure timely releases and quality standards. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with multiple video tools, managing creative workflows, and ensuring high-quality content production. + +--- + +### 29. AI-Powered News Aggregator + +**Implementation Using Julep:** + +- **Docs:** + - Store news source lists, categorization templates, and summarization guidelines. + - Integrate with news APIs (e.g., NewsAPI, RSS feeds). + +- **Sessions:** + - Create user-specific sessions to track news preferences and reading history. + - Maintain context for personalized news feeds and topics of interest. + +- **Tasks:** + - Define tasks for news scraping, categorization, summarization, and personalization. + - Automate feed generation and delivery based on user preferences. + +- **Executions:** + - Execute news aggregation tasks periodically. + - Monitor executions to ensure timely and relevant news delivery. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires efficient news scraping, accurate categorization, and personalized summarization, but is manageable with clear task workflows. + +--- + +### 30. Intelligent Appointment Follow-Up System + +**Implementation Using Julep:** + +- **Docs:** + - Store follow-up templates, feedback forms, and communication guidelines. + - Integrate with CRM and email platforms. + +- **Sessions:** + - Manage follow-up sessions to track appointments and subsequent communications. + - Maintain context for previous interactions and follow-up actions. + +- **Tasks:** + - Create tasks for sending follow-up emails, collecting feedback, and scheduling future appointments. + - Automate reminder notifications and feedback analysis. + +- **Executions:** + - Execute follow-up tasks based on appointment completions. + - Monitor executions to ensure timely and effective communications. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integration with CRM systems and implementing automated communication workflows, adding moderate complexity. + +--- + +### 31. Automated Compliance Monitoring Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store regulatory guidelines, compliance checklists, and reporting templates. + - Integrate with internal systems and regulatory databases. + +- **Sessions:** + - Create compliance-specific sessions to track monitoring activities and audit trails. + - Maintain context for various compliance standards and organizational policies. + +- **Tasks:** + - Define tasks for continuous monitoring, policy enforcement, and compliance reporting. + - Automate detection of non-compliant activities and trigger corrective actions. + +- **Executions:** + - Execute compliance monitoring tasks in real-time. + - Monitor executions to ensure ongoing adherence to regulations and standards. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Requires comprehensive integration with organizational systems, robust monitoring mechanisms, and ensuring adherence to multifaceted regulatory requirements. + +--- + +### 32. AI-Powered Personal Shopper + +**Implementation Using Julep:** + +- **Docs:** + - Store product catalogs, user preference data, and recommendation algorithms. + - Integrate with e-commerce APIs (e.g., Amazon, Shopify). + +- **Sessions:** + - Manage shopping sessions to track user preferences and purchase history. + - Maintain context for personalized product recommendations. + +- **Tasks:** + - Create tasks for product suggestion, wishlist management, and deal notifications. + - Automate price comparisons and availability checks. + +- **Executions:** + - Execute personal shopping tasks based on user inputs and behavior. + - Monitor executions to provide timely recommendations and alerts. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with multiple e-commerce platforms, implementing personalized recommendation logic, and handling real-time deal tracking. + +--- + +### 33. Smart Content Personalization Engine + +**Implementation Using Julep:** + +- **Docs:** + - Store content variants, personalization rules, and user segmentation data. + - Integrate with website CMS and analytics platforms. + +- **Sessions:** + - Create user-specific sessions to track interactions and preferences. + - Maintain context for personalized content delivery. + +- **Tasks:** + - Define tasks for content analysis, user behavior tracking, and personalized content delivery. + - Automate A/B testing and content optimization based on performance metrics. + +- **Executions:** + - Execute content personalization tasks in real-time. + - Monitor executions to adjust personalization strategies dynamically. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires real-time user behavior tracking, dynamic content delivery, and continuous optimization based on analytics, increasing system complexity. + +--- + +### 34. Automated Debt Collection Agent + +**Implementation Using Julep:** + +- **Docs:** + - Store debt agreements, payment schedules, and communication templates. + - Integrate with financial systems and payment gateways. + +- **Sessions:** + - Manage debt collection sessions to track debtor interactions and payment statuses. + - Maintain context for individual debtors and their payment histories. + +- **Tasks:** + - Create tasks for sending payment reminders, negotiating payment plans, and issuing notifications. + - Automate follow-ups and escalation procedures for delinquent accounts. + +- **Executions:** + - Execute debt collection tasks based on payment statuses and schedules. + - Monitor executions to ensure effective communication and resolution. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves sensitive financial data handling, integration with payment systems, and implementing automated negotiation workflows. + +--- + +### 35. AI-Driven Talent Matching System + +**Implementation Using Julep:** + +- **Docs:** + - Store job descriptions, candidate profiles, and matching criteria. + - Integrate with job boards and professional networking platforms. + +- **Sessions:** + - Create sessions for each matching process to track candidate-job pairings. + - Maintain context for specific job requirements and candidate qualifications. + +- **Tasks:** + - Define tasks for candidate screening, skills matching, and recommendation generation. + - Automate notifications to both candidates and employers regarding match statuses. + +- **Executions:** + - Execute talent matching tasks based on incoming job postings and candidate applications. + - Monitor executions to ensure accurate and timely matches. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Requires sophisticated matching algorithms, integration with diverse data sources, and handling dynamic job and candidate data. + +--- + +### 36. Intelligent Expense Reporting Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store expense categories, reimbursement policies, and reporting templates. + - Integrate with financial systems and expense tracking APIs. + +- **Sessions:** + - Manage expense reporting sessions to track submissions and approvals. + - Maintain context for individual employee expenses and budget limits. + +- **Tasks:** + - Create tasks for expense submission, approval workflows, and reimbursement processing. + - Automate validation checks and compliance with policies. + +- **Executions:** + - Execute expense reporting tasks based on submission triggers and approval workflows. + - Monitor executions to ensure timely reimbursements and policy adherence. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with financial systems, implementing approval workflows, and ensuring compliance with expense policies. + +--- + +### 37. Automated Meeting Minutes Recorder + +**Implementation Using Julep:** + +- **Docs:** + - Store meeting agendas, transcription templates, and summary guidelines. + - Integrate with audio transcription services (e.g., Otter.ai, Google Speech-to-Text). + +- **Sessions:** + - Create meeting-specific sessions to track transcription and summarization progress. + - Maintain context for meeting topics and participant interactions. + +- **Tasks:** + - Define tasks for audio ingestion, transcription, summary generation, and distribution. + - Automate the extraction of action items and key decisions. + +- **Executions:** + - Execute transcription and summarization tasks in real-time or post-meeting. + - Monitor executions to ensure accurate recordings and timely distribution. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires reliable audio transcription integration and effective summarization techniques, but manageable with clear task definitions. + +--- + +### 38. AI-Driven Content Recommendation System + +**Implementation Using Julep:** + +- **Docs:** + - Store user profiles, content metadata, and recommendation algorithms. + - Integrate with content management systems and user behavior analytics. + +- **Sessions:** + - Manage user-specific sessions to track interactions and preference changes. + - Maintain context for personalized content delivery. + +- **Tasks:** + - Define tasks for content analysis, user behavior tracking, and recommendation generation. + - Automate personalization based on real-time user interactions. + +- **Executions:** + - Execute content recommendation tasks in real-time. + - Monitor executions to refine recommendation accuracy and relevance. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves real-time data processing, advanced recommendation algorithms, and integration with multiple content sources. + +--- + +### 39. Smart Time Tracking Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store time tracking templates, productivity guidelines, and reporting formats. + - Integrate with productivity tools (e.g., Toggl, Clockify). + +- **Sessions:** + - Create user-specific sessions to track time spent on tasks and projects. + - Maintain context for task prioritization and productivity goals. + +- **Tasks:** + - Define tasks for time logging, productivity analysis, and report generation. + - Automate reminders for time tracking and productivity tips based on usage patterns. + +- **Executions:** + - Execute time tracking tasks continuously or based on user actions. + - Monitor executions to provide real-time productivity insights and suggestions. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with time tracking tools and implementing effective productivity analysis logic. + +--- + +### 40. Automated Webinar Hosting Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store webinar schedules, registration forms, and hosting guidelines. + - Integrate with webinar platforms (e.g., Zoom, WebinarJam). + +- **Sessions:** + - Manage webinar-specific sessions to track registrations, attendee interactions, and follow-ups. + - Maintain context for webinar topics and participant engagement. + +- **Tasks:** + - Create tasks for webinar scheduling, participant management, live interactions, and post-webinar follow-ups. + - Automate reminders, thank-you emails, and feedback collection. + +- **Executions:** + - Execute webinar hosting tasks based on schedules and participant actions. + - Monitor executions to ensure smooth webinar operations and effective follow-ups. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves integration with webinar platforms, managing live interactions, and handling post-event processes seamlessly. + +--- + +### 41. AI-Powered Inventory Forecasting Tool + +**Implementation Using Julep:** + +- **Docs:** + - Store sales data, forecasting models, and inventory guidelines. + - Integrate with sales and inventory tracking systems. + +- **Sessions:** + - Create forecasting sessions to track sales trends and inventory predictions. + - Maintain context for seasonal factors and market conditions affecting inventory. + +- **Tasks:** + - Define tasks for data collection, trend analysis, prediction model execution, and report generation. + - Automate alerts for predicted stock shortages or surpluses. + +- **Executions:** + - Execute forecasting tasks periodically based on sales data updates. + - Monitor executions to refine prediction accuracy and adjust inventory strategies. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires advanced predictive analytics, integration with sales systems, and handling dynamic market conditions influencing inventory. + +--- + +### 42. Smart Contract Management System + +**Implementation Using Julep:** + +- **Docs:** + - Store smart contract templates, execution guidelines, and compliance rules. + - Integrate with blockchain platforms (e.g., Ethereum, Hyperledger). + +- **Sessions:** + - Manage contract-specific sessions to track creation, execution, and monitoring. + - Maintain context for contract terms and participant interactions. + +- **Tasks:** + - Create tasks for contract creation, deployment, execution monitoring, and compliance checks. + - Automate notifications for contract milestones and compliance alerts. + +- **Executions:** + - Execute smart contract tasks based on blockchain events and predefined triggers. + - Monitor executions to ensure contract integrity and compliance. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves blockchain integration, ensuring smart contract security, and managing complex execution and compliance workflows. + +--- + +### 43. Automated Knowledge Base Updater + +**Implementation Using Julep:** + +- **Docs:** + - Store knowledge base articles, update guidelines, and categorization rules. + - Integrate with content management systems and information sources. + +- **Sessions:** + - Create knowledge base sessions to track updates, revisions, and user queries. + - Maintain context for content accuracy and relevance. + +- **Tasks:** + - Define tasks for content ingestion, information extraction, categorization, and publishing. + - Automate periodic reviews and updates based on new information sources. + +- **Executions:** + - Execute knowledge base update tasks as new content becomes available. + - Monitor executions to ensure timely and accurate information updates. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires efficient content ingestion, accurate information extraction, and seamless integration with knowledge management systems. + +--- + +### 44. AI-Driven Fraud Detection System + +**Implementation Using Julep:** + +- **Docs:** + - Store fraud detection algorithms, monitoring guidelines, and incident response protocols. + - Integrate with financial transaction systems and security APIs. + +- **Sessions:** + - Manage fraud detection sessions to track suspicious activities and investigations. + - Maintain context for user behavior patterns and anomaly detection. + +- **Tasks:** + - Create tasks for real-time transaction monitoring, anomaly detection, incident logging, and alerting. + - Automate response actions like freezing accounts or notifying security teams. + +- **Executions:** + - Execute fraud detection tasks continuously based on transaction flows. + - Monitor executions to ensure timely detection and response to fraudulent activities. + +**Complexity Rating:** ★★★★★ + +**Explanation:** Involves real-time data processing, sophisticated anomaly detection algorithms, and ensuring robust security measures. + +--- + +### 45. Intelligent Personal Diary Assistant + +**Implementation Using Julep:** + +- **Docs:** + - Store diary templates, emotional analysis guidelines, and reflection prompts. + - Integrate with sentiment analysis APIs. + +- **Sessions:** + - Create user-specific sessions to track daily entries and emotional states. + - Maintain context for personal growth and mood trends. + +- **Tasks:** + - Define tasks for daily entry prompts, sentiment analysis, and insight generation. + - Automate privacy controls and data encryption for secure diary storage. + +- **Executions:** + - Execute diary assistant tasks daily based on user inputs. + - Monitor executions to provide personalized insights and growth tracking. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Requires integration with sentiment analysis tools and ensuring secure data handling, but manageable with well-defined workflows. + +--- + +### 46. Automated Language Learning Tutor + +**Implementation Using Julep:** + +- **Docs:** + - Store language lessons, exercise templates, and feedback guidelines. + - Integrate with language processing APIs and educational resources. + +- **Sessions:** + - Manage learning sessions to track user progress and performance. + - Maintain context for personalized lesson plans and feedback. + +- **Tasks:** + - Create tasks for lesson delivery, exercise generation, progress tracking, and feedback provision. + - Automate adaptive learning paths based on user performance. + +- **Executions:** + - Execute language learning tasks based on user interactions and learning schedules. + - Monitor executions to adjust learning strategies and provide real-time feedback. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves adaptive learning algorithms, integration with language processing tools, and personalized content delivery. + +--- + +### 47. AI-Powered Budgeting Tool for Businesses + +**Implementation Using Julep:** + +- **Docs:** + - Store budgeting templates, financial guidelines, and reporting formats. + - Integrate with accounting systems and financial data sources. + +- **Sessions:** + - Create budgeting sessions to track financial planning and expenditure. + - Maintain context for organizational financial goals and constraints. + +- **Tasks:** + - Define tasks for budget creation, expenditure tracking, financial forecasting, and report generation. + - Automate alerts for budget overruns and financial goal assessments. + +- **Executions:** + - Execute budgeting tasks based on financial data updates and planning cycles. + - Monitor executions to ensure accurate financial tracking and reporting. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires integration with accounting systems, accurate financial forecasting, and robust budgeting logic to handle business complexities. + +--- + +### 48. Smart Compliance Documentation Generator + +**Implementation Using Julep:** + +- **Docs:** + - Store compliance templates, regulatory guidelines, and documentation standards. + - Integrate with regulatory databases and internal policy systems. + +- **Sessions:** + - Manage compliance documentation sessions to track document creation and updates. + - Maintain context for specific regulatory requirements and organizational policies. + +- **Tasks:** + - Create tasks for document generation, compliance checking, format validation, and publishing. + - Automate updates based on regulatory changes and policy revisions. + +- **Executions:** + - Execute compliance documentation tasks as needed or on a schedule. + - Monitor executions to ensure documents meet all compliance standards. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Involves dynamic document generation, adherence to detailed regulatory standards, and ensuring continuous updates based on regulatory changes. + +--- + +### 49. Automated Product Recommendation Engine + +**Implementation Using Julep:** + +- **Docs:** + - Store product catalogs, user behavior data, and recommendation algorithms. + - Integrate with e-commerce platforms and user analytics tools. + +- **Sessions:** + - Create user-specific sessions to track interactions and preferences. + - Maintain context for personalized recommendation accuracy. + +- **Tasks:** + - Define tasks for data collection, behavior analysis, recommendation generation, and user feedback integration. + - Automate real-time recommendations based on user actions and trends. + +- **Executions:** + - Execute recommendation tasks in real-time to provide instant suggestions. + - Monitor executions to refine algorithms and improve recommendation relevance. + +**Complexity Rating:** ★★★★☆ + +**Explanation:** Requires sophisticated recommendation algorithms, real-time data processing, and continuous refinement based on user feedback. + +--- + +### 50. Intelligent Event Feedback Analyzer + +**Implementation Using Julep:** + +- **Docs:** + - Store feedback forms, analysis templates, and reporting standards. + - Integrate with event platforms and feedback collection tools. + +- **Sessions:** + - Manage feedback-specific sessions to track responses and analysis progress. + - Maintain context for event-specific feedback and improvement areas. + +- **Tasks:** + - Create tasks for feedback collection, sentiment analysis, trend identification, and report generation. + - Automate the extraction of actionable insights and improvement suggestions. + +- **Executions:** + - Execute feedback analysis tasks post-event. + - Monitor executions to ensure accurate and timely feedback processing and reporting. + +**Complexity Rating:** ★★★☆☆ + +**Explanation:** Involves integrating with feedback collection tools and implementing effective sentiment analysis and trend identification mechanisms. + +--- + +# Complexity and Difficulty Ratings + +The scenarios have been rated based on the number of integrated features, required integrations, and overall system complexity. Here's a quick overview: + +- **★☆☆☆☆ (1/5): Easiest** +- **★★☆☆☆ (2/5): Low Complexity** +- **★★★☆☆ (3/5): Moderate Complexity** +- **★★★★☆ (4/5): High Complexity** +- **★★★★★ (5/5): Most Complex** + +| **Scenario** | **Complexity Rating** | +|---------------------------------------------------|-----------------------| +| 1. Automated Customer Support Agent | ★★★★☆ | +| 2. Smart Research Assistant | ★★★★☆ | +| 3. Personal Finance Manager | ★★★☆☆ | +| 4. Content Creation Workflow | ★★★☆☆ | +| 5. E-commerce Order Processing System | ★★★★☆ | +| 6. AI-Powered Personal Trainer | ★★★☆☆ | +| 7. Automated Email Marketing Campaigns | ★★★☆☆ | +| 8. Intelligent Recruitment Assistant | ★★★★★ | +| 9. Smart Home Automation Controller | ★★★★☆ | +| 10. Automated Legal Document Analyzer | ★★★★★ | +| 11. Personalized Learning Assistant | ★★★★☆ | +| 12. AI-Driven Social Media Manager | ★★★★☆ | +| 13. Automated Travel Itinerary Planner | ★★★☆☆ | +| 14. AI-Powered Inventory Management System | ★★★★☆ | +| 15. Intelligent Health Monitoring System | ★★★★☆ | +| 16. Automated Content Moderation Tool | ★★★★★ | +| 17. AI-Powered Resume Builder | ★★★☆☆ | +| 18. Smart Event Management System | ★★★★☆ | +| 19. Automated Survey Analyzer | ★★★☆☆ | +| 20. AI-Driven Project Management Assistant | ★★★★☆ | +| 21. Intelligent Document Summarizer | ★★★★☆ | +| 22. Automated Feedback Collection and Analysis | ★★★☆☆ | +| 23. AI-Powered Language Translator | ★★★☆☆ | +| 24. Smart Appointment Scheduler | ★★★☆☆ | +| 25. Automated Inventory Auditor | ★★★★☆ | +| 26. AI-Driven Competitive Analysis Tool | ★★★★☆ | +| 27. Smart Recipe Generator | ★★★☆☆ | +| 28. Automated Video Content Creator | ★★★★☆ | +| 29. AI-Powered News Aggregator | ★★★☆☆ | +| 30. Intelligent Appointment Follow-Up System | ★★★☆☆ | +| 31. Automated Compliance Monitoring Tool | ★★★★★ | +| 32. AI-Powered Personal Shopper | ★★★★☆ | +| 33. Smart Content Personalization Engine | ★★★★☆ | +| 34. Automated Debt Collection Agent | ★★★★☆ | +| 35. AI-Driven Talent Matching System | ★★★★★ | +| 36. Intelligent Expense Reporting Tool | ★★★★☆ | +| 37. Automated Meeting Minutes Recorder | ★★★☆☆ | +| 38. AI-Driven Content Recommendation System | ★★★★☆ | +| 39. Smart Time Tracking Assistant | ★★★☆☆ | +| 40. Automated Webinar Hosting Assistant | ★★★★☆ | +| 41. AI-Powered Inventory Forecasting Tool | ★★★★☆ | +| 42. Smart Contract Management System | ★★★★★ | +| 43. Automated Knowledge Base Updater | ★★★★☆ | +| 44. AI-Driven Fraud Detection System | ★★★★★ | +| 45. Intelligent Personal Diary Assistant | ★★★☆☆ | +| 46. Automated Language Learning Tutor | ★★★★☆ | +| 47. AI-Powered Budgeting Tool for Businesses | ★★★★☆ | +| 48. Smart Compliance Documentation Generator | ★★★★☆ | +| 49. Automated Product Recommendation Engine | ★★★★☆ | +| 50. Intelligent Event Feedback Analyzer | ★★★☆☆ | + +--- + +# Conclusion + +These 50 scenarios showcase the versatility and power of Julep's **docs**, **sessions**, **tasks**, and **executions** features in automating and enhancing various business and personal workflows. Depending on your specific needs and available integrations, these scenarios can be tailored to create efficient, intelligent, and scalable solutions. + +Feel free to explore these scenarios, adapt them to your use cases, and contribute to expanding Julep's capabilities further! \ No newline at end of file diff --git a/cookbooks/00-Devfest-Email-Assistant.ipynb b/cookbooks/00-Devfest-Email-Assistant.ipynb new file mode 100644 index 000000000..d4d891cf6 --- /dev/null +++ b/cookbooks/00-Devfest-Email-Assistant.ipynb @@ -0,0 +1,296 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "!pip install julep" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import yaml\n", + "from julep import Julep\n", + "\n", + "api_key = os.getenv(\"JULEP_API_KEY\")\n", + "julep = Julep(api_key=api_key, environment=\"dev\")" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [], + "source": [ + "agent = julep.agents.create(\n", + " name=\"Julep Email Assistant\",\n", + " about=(\n", + " \"You are an agent that handles emails for julep users.\"\n", + " + \" Julep is a platform for creating kick-ass AI agents.\"\n", + " ),\n", + " model=\"gpt-4o\",\n", + " default_settings={\"temperature\": 0.2},\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2790657c-8378-4c5b-a60b-08b27e8ed7cf'" + ] + }, + "execution_count": 96, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "agent.id" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [], + "source": [ + "mailgun_password = os.getenv(\"MAILGUN_PASSWORD\")\n", + "\n", + "task_def = yaml.safe_load(f\"\"\"\n", + "name: Julep Email Assistant\n", + "\n", + "input_schema:\n", + " type: object\n", + " properties:\n", + " from:\n", + " type: string\n", + " to:\n", + " type: string\n", + " subject:\n", + " type: string\n", + " body:\n", + " type: string\n", + "\n", + "tools:\n", + "- name: send_email\n", + " integration:\n", + " provider: email\n", + " setup:\n", + " host: smtp.mailgun.org\n", + " password: {mailgun_password}\n", + " port: 587\n", + " user: postmaster@email.julep.ai\n", + "\n", + "- name: search_docs\n", + " system:\n", + " resource: agent\n", + " subresource: doc\n", + " operation: search\n", + " \n", + "main:\n", + "- prompt: |-\n", + " You are {{{{ agent.name }}}}. {{{{ agent.about }}}}\n", + "\n", + " A user with email address {{{{ _.from }}}} has sent the following inquiry:\n", + " ------\n", + " Subject: {{{{ _.subject }}}}\n", + "\n", + " {{{{ _.body }}}}\n", + " ------\n", + "\n", + " Can you generate a query to search the documentation based on this email?\n", + " Just respond with the query as is and nothing else.\n", + "\n", + " unwrap: true\n", + "\n", + "- tool: search_docs\n", + " arguments:\n", + " agent_id: \"'{agent.id}'\"\n", + " text: _\n", + " \n", + "- prompt: |-\n", + " You are {{{{ agent.name }}}}. {{{{ agent.about }}}}\n", + "\n", + " A user with email address {{{{ inputs[0].from }}}} has sent the following inquiry:\n", + " ------\n", + " Subject: {{{{ inputs[0].subject }}}}\n", + "\n", + " {{{{ inputs[0].body }}}}\n", + " ------\n", + "\n", + " Here are some possibly relevant snippets from the julep documentation:\n", + " {{% for doc in _.docs %}}\n", + " {{% for snippet in doc.snippets %}}\n", + " {{{{ snippet.content }}}}\n", + " {{% endfor %}}\n", + " {{% endfor %}}\n", + " ========\n", + "\n", + " Based on the above info, craft an email body to respond with as a json object.\n", + " The json object must have `subject` and `body` fields.\n", + " response_format:\n", + " type: json_object\n", + " \n", + " unwrap: true\n", + " \n", + "- evaluate:\n", + " subject: \"load_json(_.split('```json')[1].split('```')[0])['subject']\"\n", + " body: \"load_json(_.split('```json')[1].split('```')[0])['body']\"\n", + " \n", + "- tool: send_email\n", + " arguments:\n", + " body: _.body\n", + " from: \"'postmaster@email.julep.ai'\"\n", + " subject: _.subject\n", + " to: inputs[0].from\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [], + "source": [ + "task = julep.tasks.create(\n", + " agent_id=agent.id,\n", + " **task_def,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'614a7f59-6b43-4887-a6dd-1a75e5516025'" + ] + }, + "execution_count": 105, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "task.id" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": {}, + "outputs": [], + "source": [ + "execution = julep.executions.create(\n", + " task_id=task.id,\n", + " input={\"from\": \"diwank@julep.ai\", \"to\": \"help@agents.new\", \"subject\": \"what's up\", \"body\": \"sup\"},\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Execution(id='4205dda5-2afb-4f2f-8538-cbbf3e0c19f3', created_at=datetime.datetime(2024, 10, 7, 13, 1, 6, 431430, tzinfo=datetime.timezone.utc), input={'body': 'sup', 'from': 'diwank@julep.ai', 'subject': \"what's up\", 'to': 'help@agents.new'}, status='succeeded', task_id='614a7f59-6b43-4887-a6dd-1a75e5516025', updated_at=datetime.datetime(2024, 10, 7, 13, 1, 8, 518972, tzinfo=datetime.timezone.utc), error=None, metadata={}, output={'body': 'Hi there! How can I assist you today? If you have any questions or need help with Julep, feel free to let me know!', 'subject': 'Hello!'})" + ] + }, + "execution_count": 108, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "julep.executions.get(execution.id)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[20], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mjulep\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexecutions\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtransitions\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m(\u001b[49m\u001b[43mexecution_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mexecution\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mid\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/resources/executions/transitions.py:127\u001b[0m, in \u001b[0;36mTransitionsResource.stream\u001b[0;34m(self, execution_id, next_page_token, extra_headers, extra_query, extra_body, timeout)\u001b[0m\n\u001b[1;32m 125\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m execution_id:\n\u001b[1;32m 126\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpected a non-empty value for `execution_id` but received \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mexecution_id\u001b[38;5;132;01m!r}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 127\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 128\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43mf\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/executions/\u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43mexecution_id\u001b[49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[38;5;124;43m/transitions.stream\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 129\u001b[0m \u001b[43m \u001b[49m\u001b[43moptions\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmake_request_options\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 130\u001b[0m \u001b[43m \u001b[49m\u001b[43mextra_headers\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_headers\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 131\u001b[0m \u001b[43m \u001b[49m\u001b[43mextra_query\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_query\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 132\u001b[0m \u001b[43m \u001b[49m\u001b[43mextra_body\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_body\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 133\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 134\u001b[0m \u001b[43m \u001b[49m\u001b[43mquery\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmaybe_transform\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 135\u001b[0m \u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mnext_page_token\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mnext_page_token\u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtransition_stream_params\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mTransitionStreamParams\u001b[49m\n\u001b[1;32m 136\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 137\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 138\u001b[0m \u001b[43m \u001b[49m\u001b[43mcast_to\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mobject\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 139\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/_base_client.py:1200\u001b[0m, in \u001b[0;36mSyncAPIClient.get\u001b[0;34m(self, path, cast_to, options, stream, stream_cls)\u001b[0m\n\u001b[1;32m 1197\u001b[0m opts \u001b[38;5;241m=\u001b[39m FinalRequestOptions\u001b[38;5;241m.\u001b[39mconstruct(method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mget\u001b[39m\u001b[38;5;124m\"\u001b[39m, url\u001b[38;5;241m=\u001b[39mpath, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39moptions)\n\u001b[1;32m 1198\u001b[0m \u001b[38;5;66;03m# cast is required because mypy complains about returning Any even though\u001b[39;00m\n\u001b[1;32m 1199\u001b[0m \u001b[38;5;66;03m# it understands the type variables\u001b[39;00m\n\u001b[0;32m-> 1200\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cast(ResponseT, \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcast_to\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mopts\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream_cls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream_cls\u001b[49m\u001b[43m)\u001b[49m)\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/_base_client.py:946\u001b[0m, in \u001b[0;36mSyncAPIClient.request\u001b[0;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[1;32m 943\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 944\u001b[0m retries_taken \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m--> 946\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 947\u001b[0m \u001b[43m \u001b[49m\u001b[43mcast_to\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcast_to\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 948\u001b[0m \u001b[43m \u001b[49m\u001b[43moptions\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43moptions\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 949\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 950\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream_cls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream_cls\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 951\u001b[0m \u001b[43m \u001b[49m\u001b[43mretries_taken\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mretries_taken\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 952\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/_base_client.py:982\u001b[0m, in \u001b[0;36mSyncAPIClient._request\u001b[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001b[0m\n\u001b[1;32m 979\u001b[0m log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSending HTTP Request: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m, request\u001b[38;5;241m.\u001b[39mmethod, request\u001b[38;5;241m.\u001b[39murl)\n\u001b[1;32m 981\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 982\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_client\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 983\u001b[0m \u001b[43m \u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 984\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_should_stream_response_body\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 985\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 986\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 987\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m httpx\u001b[38;5;241m.\u001b[39mTimeoutException \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 988\u001b[0m log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEncountered httpx.TimeoutException\u001b[39m\u001b[38;5;124m\"\u001b[39m, exc_info\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_client.py:940\u001b[0m, in \u001b[0;36mClient.send\u001b[0;34m(self, request, stream, auth, follow_redirects)\u001b[0m\n\u001b[1;32m 938\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 939\u001b[0m response\u001b[38;5;241m.\u001b[39mclose()\n\u001b[0;32m--> 940\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_client.py:934\u001b[0m, in \u001b[0;36mClient.send\u001b[0;34m(self, request, stream, auth, follow_redirects)\u001b[0m\n\u001b[1;32m 932\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 933\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m stream:\n\u001b[0;32m--> 934\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 936\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m response\n\u001b[1;32m 938\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_models.py:815\u001b[0m, in \u001b[0;36mResponse.read\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 811\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 812\u001b[0m \u001b[38;5;124;03mRead and return the response content.\u001b[39;00m\n\u001b[1;32m 813\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 814\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_content\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[0;32m--> 815\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_content \u001b[38;5;241m=\u001b[39m \u001b[38;5;124;43mb\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mjoin\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miter_bytes\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 816\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_content\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_models.py:831\u001b[0m, in \u001b[0;36mResponse.iter_bytes\u001b[0;34m(self, chunk_size)\u001b[0m\n\u001b[1;32m 829\u001b[0m chunker \u001b[38;5;241m=\u001b[39m ByteChunker(chunk_size\u001b[38;5;241m=\u001b[39mchunk_size)\n\u001b[1;32m 830\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m request_context(request\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request):\n\u001b[0;32m--> 831\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mraw_bytes\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miter_raw\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 832\u001b[0m \u001b[43m \u001b[49m\u001b[43mdecoded\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mdecoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43mraw_bytes\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 833\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunker\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdecoded\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_models.py:885\u001b[0m, in \u001b[0;36mResponse.iter_raw\u001b[0;34m(self, chunk_size)\u001b[0m\n\u001b[1;32m 882\u001b[0m chunker \u001b[38;5;241m=\u001b[39m ByteChunker(chunk_size\u001b[38;5;241m=\u001b[39mchunk_size)\n\u001b[1;32m 884\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m request_context(request\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request):\n\u001b[0;32m--> 885\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mraw_stream_bytes\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 886\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_num_bytes_downloaded\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mraw_stream_bytes\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 887\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunker\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43mraw_stream_bytes\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_client.py:127\u001b[0m, in \u001b[0;36mBoundSyncStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 126\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__iter__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m typing\u001b[38;5;241m.\u001b[39mIterator[\u001b[38;5;28mbytes\u001b[39m]:\n\u001b[0;32m--> 127\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_stream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 128\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_transports/default.py:116\u001b[0m, in \u001b[0;36mResponseStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 114\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__iter__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m typing\u001b[38;5;241m.\u001b[39mIterator[\u001b[38;5;28mbytes\u001b[39m]:\n\u001b[1;32m 115\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m map_httpcore_exceptions():\n\u001b[0;32m--> 116\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_httpcore_stream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 117\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:367\u001b[0m, in \u001b[0;36mPoolByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 365\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 366\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n\u001b[0;32m--> 367\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:363\u001b[0m, in \u001b[0;36mPoolByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 361\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__iter__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Iterator[\u001b[38;5;28mbytes\u001b[39m]:\n\u001b[1;32m 362\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 363\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_stream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 364\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\n\u001b[1;32m 365\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:349\u001b[0m, in \u001b[0;36mHTTP11ConnectionByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m ShieldCancellation():\n\u001b[1;32m 348\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n\u001b[0;32m--> 349\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:341\u001b[0m, in \u001b[0;36mHTTP11ConnectionByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 339\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 340\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m Trace(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreceive_response_body\u001b[39m\u001b[38;5;124m\"\u001b[39m, logger, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request, kwargs):\n\u001b[0;32m--> 341\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_connection\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_receive_response_body\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 342\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 344\u001b[0m \u001b[38;5;66;03m# If we get an exception while streaming the response,\u001b[39;00m\n\u001b[1;32m 345\u001b[0m \u001b[38;5;66;03m# we want to close the response (and possibly the connection)\u001b[39;00m\n\u001b[1;32m 346\u001b[0m \u001b[38;5;66;03m# before raising that exception.\u001b[39;00m\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:210\u001b[0m, in \u001b[0;36mHTTP11Connection._receive_response_body\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m 207\u001b[0m timeout \u001b[38;5;241m=\u001b[39m timeouts\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mread\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 209\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 210\u001b[0m event \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_receive_event\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 211\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(event, h11\u001b[38;5;241m.\u001b[39mData):\n\u001b[1;32m 212\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m \u001b[38;5;28mbytes\u001b[39m(event\u001b[38;5;241m.\u001b[39mdata)\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:224\u001b[0m, in \u001b[0;36mHTTP11Connection._receive_event\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 221\u001b[0m event \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_h11_state\u001b[38;5;241m.\u001b[39mnext_event()\n\u001b[1;32m 223\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m event \u001b[38;5;129;01mis\u001b[39;00m h11\u001b[38;5;241m.\u001b[39mNEED_DATA:\n\u001b[0;32m--> 224\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_network_stream\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 225\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mREAD_NUM_BYTES\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\n\u001b[1;32m 226\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 228\u001b[0m \u001b[38;5;66;03m# If we feed this case through h11 we'll raise an exception like:\u001b[39;00m\n\u001b[1;32m 229\u001b[0m \u001b[38;5;66;03m#\u001b[39;00m\n\u001b[1;32m 230\u001b[0m \u001b[38;5;66;03m# httpcore.RemoteProtocolError: can't handle event type\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[38;5;66;03m# perspective. Instead we handle this case distinctly and treat\u001b[39;00m\n\u001b[1;32m 235\u001b[0m \u001b[38;5;66;03m# it as a ConnectError.\u001b[39;00m\n\u001b[1;32m 236\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m data \u001b[38;5;241m==\u001b[39m \u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_h11_state\u001b[38;5;241m.\u001b[39mtheir_state \u001b[38;5;241m==\u001b[39m h11\u001b[38;5;241m.\u001b[39mSEND_RESPONSE:\n", + "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_backends/sync.py:126\u001b[0m, in \u001b[0;36mSyncStream.read\u001b[0;34m(self, max_bytes, timeout)\u001b[0m\n\u001b[1;32m 124\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m map_exceptions(exc_map):\n\u001b[1;32m 125\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sock\u001b[38;5;241m.\u001b[39msettimeout(timeout)\n\u001b[0;32m--> 126\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sock\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrecv\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmax_bytes\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/.asdf/installs/python/3.12.5/lib/python3.12/ssl.py:1233\u001b[0m, in \u001b[0;36mSSLSocket.recv\u001b[0;34m(self, buflen, flags)\u001b[0m\n\u001b[1;32m 1229\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m flags \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 1230\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 1231\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnon-zero flags not allowed in calls to recv() on \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 1232\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m)\n\u001b[0;32m-> 1233\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbuflen\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1234\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1235\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mrecv(buflen, flags)\n", + "File \u001b[0;32m~/.asdf/installs/python/3.12.5/lib/python3.12/ssl.py:1106\u001b[0m, in \u001b[0;36mSSLSocket.read\u001b[0;34m(self, len, buffer)\u001b[0m\n\u001b[1;32m 1104\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sslobj\u001b[38;5;241m.\u001b[39mread(\u001b[38;5;28mlen\u001b[39m, buffer)\n\u001b[1;32m 1105\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1106\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sslobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1107\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m SSLError \u001b[38;5;28;01mas\u001b[39;00m x:\n\u001b[1;32m 1108\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m x\u001b[38;5;241m.\u001b[39margs[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m==\u001b[39m SSL_ERROR_EOF \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msuppress_ragged_eofs:\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "# julep.executions.transitions.stream(execution_id=execution.id)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From ca9ecb937da9f848cb68f5c41e15631b76355c22 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Mon, 7 Oct 2024 18:39:26 +0530 Subject: [PATCH 22/23] Update README.md --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e3a212efb..150209ea0 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,11 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓 > [!TIP] > Ready to join the fun? **[Tweet that you are participating](https://twitter.com/intent/tweet?text=Pumped%20to%20be%20participating%20in%20%40devfestai%20with%20%40julep_ai%20building%20%23ai%20%23agents%20%23workflows%20Let's%20gooo!%20https%3A%2F%2Fgit.new%2Fjulep)** and let's get coding! 🖥️ +> [!NOTE] +> Get your API key [here](https://dashboard-dev.julep.ai). +> +> While we are in beta, you can also reach out on [Discord](https://discord.com/invite/JTSBGRZrzj) to get rate limits lifted on your API key. + ![Julep DevFest.AI](https://media.giphy.com/media/YjyUeyotft6epaMHtU/giphy.gif)
@@ -294,9 +299,9 @@ pip install julep ``` > [!NOTE] -> ~~Get your API key [here](https://app.julep.ai/api-keys).~~ +> Get your API key [here](https://dashboard-dev.julep.ai). > -> While we are in beta, you can reach out on [Discord](https://discord.com/invite/JTSBGRZrzj) to get your API key. +> While we are in beta, you can also reach out on [Discord](https://discord.com/invite/JTSBGRZrzj) to get rate limits lifted on your API key. > [!TIP] > 💻 Are you a _show me the code!™_ kind of person? We have created a ton of cookbooks for you to get started with. **Check out the [cookbooks](/cookbooks)** to browse through examples. From 637d50b953f9099d6f5ec5eed0ffcc3ff5f237d7 Mon Sep 17 00:00:00 2001 From: HamadaSalhab Date: Mon, 7 Oct 2024 17:16:04 +0300 Subject: [PATCH 23/23] feat(cookbooks): Update DevFest Email Assistant notebook cookbook --- cookbooks/00-Devfest-Email-Assistant.ipynb | 126 ++++++++++++--------- 1 file changed, 72 insertions(+), 54 deletions(-) diff --git a/cookbooks/00-Devfest-Email-Assistant.ipynb b/cookbooks/00-Devfest-Email-Assistant.ipynb index d4d891cf6..6182d7152 100644 --- a/cookbooks/00-Devfest-Email-Assistant.ipynb +++ b/cookbooks/00-Devfest-Email-Assistant.ipynb @@ -4,14 +4,34 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: julep in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (1.6.0)\n", + "Requirement already satisfied: anyio<5,>=3.5.0 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from julep) (4.6.0)\n", + "Requirement already satisfied: distro<2,>=1.7.0 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from julep) (1.9.0)\n", + "Requirement already satisfied: httpx<1,>=0.23.0 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from julep) (0.27.2)\n", + "Requirement already satisfied: pydantic<3,>=1.9.0 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from julep) (2.9.2)\n", + "Requirement already satisfied: sniffio in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from julep) (1.3.1)\n", + "Requirement already satisfied: typing-extensions<5,>=4.7 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from julep) (4.12.2)\n", + "Requirement already satisfied: idna>=2.8 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from anyio<5,>=3.5.0->julep) (3.10)\n", + "Requirement already satisfied: certifi in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from httpx<1,>=0.23.0->julep) (2024.8.30)\n", + "Requirement already satisfied: httpcore==1.* in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from httpx<1,>=0.23.0->julep) (1.0.5)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->julep) (0.14.0)\n", + "Requirement already satisfied: annotated-types>=0.6.0 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->julep) (0.7.0)\n", + "Requirement already satisfied: pydantic-core==2.23.4 in /Users/hamadasalhab/Documents/repos/julep-ai/julep/agents-api/.venv/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->julep) (2.23.4)\n" + ] + } + ], "source": [ "!pip install julep" ] }, { "cell_type": "code", - "execution_count": 95, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -21,12 +41,13 @@ "from julep import Julep\n", "\n", "api_key = os.getenv(\"JULEP_API_KEY\")\n", + "\n", "julep = Julep(api_key=api_key, environment=\"dev\")" ] }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -43,16 +64,16 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'2790657c-8378-4c5b-a60b-08b27e8ed7cf'" + "'231366f8-cdc8-423a-a1c6-72d4a300675f'" ] }, - "execution_count": 96, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -63,7 +84,7 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -155,13 +176,13 @@ " body: _.body\n", " from: \"'postmaster@email.julep.ai'\"\n", " subject: _.subject\n", - " to: inputs[0].from\n", + " to: inputs[0]['from']\n", "\"\"\")" ] }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -173,16 +194,16 @@ }, { "cell_type": "code", - "execution_count": 105, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'614a7f59-6b43-4887-a6dd-1a75e5516025'" + "'a942a86d-dfcc-4abd-a8e7-0f502a2e4c67'" ] }, - "execution_count": 105, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -193,7 +214,7 @@ }, { "cell_type": "code", - "execution_count": 106, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -205,16 +226,16 @@ }, { "cell_type": "code", - "execution_count": 108, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Execution(id='4205dda5-2afb-4f2f-8538-cbbf3e0c19f3', created_at=datetime.datetime(2024, 10, 7, 13, 1, 6, 431430, tzinfo=datetime.timezone.utc), input={'body': 'sup', 'from': 'diwank@julep.ai', 'subject': \"what's up\", 'to': 'help@agents.new'}, status='succeeded', task_id='614a7f59-6b43-4887-a6dd-1a75e5516025', updated_at=datetime.datetime(2024, 10, 7, 13, 1, 8, 518972, tzinfo=datetime.timezone.utc), error=None, metadata={}, output={'body': 'Hi there! How can I assist you today? If you have any questions or need help with Julep, feel free to let me know!', 'subject': 'Hello!'})" + "Execution(id='54c1b4d2-c036-4b22-af8c-8c8a81fe41ad', created_at=datetime.datetime(2024, 10, 7, 14, 15, 15, 575516, tzinfo=datetime.timezone.utc), input={'body': 'sup', 'from': 'diwank@julep.ai', 'subject': \"what's up\", 'to': 'help@agents.new'}, status='running', task_id='a942a86d-dfcc-4abd-a8e7-0f502a2e4c67', updated_at=datetime.datetime(2024, 10, 7, 14, 15, 16, 717572, tzinfo=datetime.timezone.utc), error=None, metadata={}, output=None)" ] }, - "execution_count": 108, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -225,51 +246,48 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 16, "metadata": {}, "outputs": [ { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[20], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mjulep\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexecutions\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtransitions\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m(\u001b[49m\u001b[43mexecution_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mexecution\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mid\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/resources/executions/transitions.py:127\u001b[0m, in \u001b[0;36mTransitionsResource.stream\u001b[0;34m(self, execution_id, next_page_token, extra_headers, extra_query, extra_body, timeout)\u001b[0m\n\u001b[1;32m 125\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m execution_id:\n\u001b[1;32m 126\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpected a non-empty value for `execution_id` but received \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mexecution_id\u001b[38;5;132;01m!r}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 127\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 128\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43mf\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/executions/\u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43mexecution_id\u001b[49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[38;5;124;43m/transitions.stream\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 129\u001b[0m \u001b[43m \u001b[49m\u001b[43moptions\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmake_request_options\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 130\u001b[0m \u001b[43m \u001b[49m\u001b[43mextra_headers\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_headers\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 131\u001b[0m \u001b[43m \u001b[49m\u001b[43mextra_query\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_query\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 132\u001b[0m \u001b[43m \u001b[49m\u001b[43mextra_body\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_body\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 133\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 134\u001b[0m \u001b[43m \u001b[49m\u001b[43mquery\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmaybe_transform\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 135\u001b[0m \u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mnext_page_token\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mnext_page_token\u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtransition_stream_params\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mTransitionStreamParams\u001b[49m\n\u001b[1;32m 136\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 137\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 138\u001b[0m \u001b[43m \u001b[49m\u001b[43mcast_to\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mobject\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 139\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/_base_client.py:1200\u001b[0m, in \u001b[0;36mSyncAPIClient.get\u001b[0;34m(self, path, cast_to, options, stream, stream_cls)\u001b[0m\n\u001b[1;32m 1197\u001b[0m opts \u001b[38;5;241m=\u001b[39m FinalRequestOptions\u001b[38;5;241m.\u001b[39mconstruct(method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mget\u001b[39m\u001b[38;5;124m\"\u001b[39m, url\u001b[38;5;241m=\u001b[39mpath, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39moptions)\n\u001b[1;32m 1198\u001b[0m \u001b[38;5;66;03m# cast is required because mypy complains about returning Any even though\u001b[39;00m\n\u001b[1;32m 1199\u001b[0m \u001b[38;5;66;03m# it understands the type variables\u001b[39;00m\n\u001b[0;32m-> 1200\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cast(ResponseT, \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcast_to\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mopts\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream_cls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream_cls\u001b[49m\u001b[43m)\u001b[49m)\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/_base_client.py:946\u001b[0m, in \u001b[0;36mSyncAPIClient.request\u001b[0;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[1;32m 943\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 944\u001b[0m retries_taken \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m--> 946\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 947\u001b[0m \u001b[43m \u001b[49m\u001b[43mcast_to\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcast_to\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 948\u001b[0m \u001b[43m \u001b[49m\u001b[43moptions\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43moptions\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 949\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 950\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream_cls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream_cls\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 951\u001b[0m \u001b[43m \u001b[49m\u001b[43mretries_taken\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mretries_taken\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 952\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/julep/_base_client.py:982\u001b[0m, in \u001b[0;36mSyncAPIClient._request\u001b[0;34m(self, cast_to, options, retries_taken, stream, stream_cls)\u001b[0m\n\u001b[1;32m 979\u001b[0m log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSending HTTP Request: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m, request\u001b[38;5;241m.\u001b[39mmethod, request\u001b[38;5;241m.\u001b[39murl)\n\u001b[1;32m 981\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 982\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_client\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 983\u001b[0m \u001b[43m \u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 984\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_should_stream_response_body\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 985\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 986\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 987\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m httpx\u001b[38;5;241m.\u001b[39mTimeoutException \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 988\u001b[0m log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEncountered httpx.TimeoutException\u001b[39m\u001b[38;5;124m\"\u001b[39m, exc_info\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_client.py:940\u001b[0m, in \u001b[0;36mClient.send\u001b[0;34m(self, request, stream, auth, follow_redirects)\u001b[0m\n\u001b[1;32m 938\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 939\u001b[0m response\u001b[38;5;241m.\u001b[39mclose()\n\u001b[0;32m--> 940\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_client.py:934\u001b[0m, in \u001b[0;36mClient.send\u001b[0;34m(self, request, stream, auth, follow_redirects)\u001b[0m\n\u001b[1;32m 932\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 933\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m stream:\n\u001b[0;32m--> 934\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 936\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m response\n\u001b[1;32m 938\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_models.py:815\u001b[0m, in \u001b[0;36mResponse.read\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 811\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 812\u001b[0m \u001b[38;5;124;03mRead and return the response content.\u001b[39;00m\n\u001b[1;32m 813\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 814\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_content\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[0;32m--> 815\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_content \u001b[38;5;241m=\u001b[39m \u001b[38;5;124;43mb\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mjoin\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miter_bytes\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 816\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_content\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_models.py:831\u001b[0m, in \u001b[0;36mResponse.iter_bytes\u001b[0;34m(self, chunk_size)\u001b[0m\n\u001b[1;32m 829\u001b[0m chunker \u001b[38;5;241m=\u001b[39m ByteChunker(chunk_size\u001b[38;5;241m=\u001b[39mchunk_size)\n\u001b[1;32m 830\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m request_context(request\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request):\n\u001b[0;32m--> 831\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mraw_bytes\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miter_raw\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 832\u001b[0m \u001b[43m \u001b[49m\u001b[43mdecoded\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mdecoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43mraw_bytes\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 833\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunker\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdecoded\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_models.py:885\u001b[0m, in \u001b[0;36mResponse.iter_raw\u001b[0;34m(self, chunk_size)\u001b[0m\n\u001b[1;32m 882\u001b[0m chunker \u001b[38;5;241m=\u001b[39m ByteChunker(chunk_size\u001b[38;5;241m=\u001b[39mchunk_size)\n\u001b[1;32m 884\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m request_context(request\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request):\n\u001b[0;32m--> 885\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mraw_stream_bytes\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 886\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_num_bytes_downloaded\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mraw_stream_bytes\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 887\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunker\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43mraw_stream_bytes\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_client.py:127\u001b[0m, in \u001b[0;36mBoundSyncStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 126\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__iter__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m typing\u001b[38;5;241m.\u001b[39mIterator[\u001b[38;5;28mbytes\u001b[39m]:\n\u001b[0;32m--> 127\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_stream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 128\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpx/_transports/default.py:116\u001b[0m, in \u001b[0;36mResponseStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 114\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__iter__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m typing\u001b[38;5;241m.\u001b[39mIterator[\u001b[38;5;28mbytes\u001b[39m]:\n\u001b[1;32m 115\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m map_httpcore_exceptions():\n\u001b[0;32m--> 116\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_httpcore_stream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 117\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:367\u001b[0m, in \u001b[0;36mPoolByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 365\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 366\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n\u001b[0;32m--> 367\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py:363\u001b[0m, in \u001b[0;36mPoolByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 361\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__iter__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Iterator[\u001b[38;5;28mbytes\u001b[39m]:\n\u001b[1;32m 362\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 363\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_stream\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 364\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mpart\u001b[49m\n\u001b[1;32m 365\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:349\u001b[0m, in \u001b[0;36mHTTP11ConnectionByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m ShieldCancellation():\n\u001b[1;32m 348\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n\u001b[0;32m--> 349\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:341\u001b[0m, in \u001b[0;36mHTTP11ConnectionByteStream.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 339\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 340\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m Trace(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreceive_response_body\u001b[39m\u001b[38;5;124m\"\u001b[39m, logger, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request, kwargs):\n\u001b[0;32m--> 341\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_connection\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_receive_response_body\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 342\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01myield\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mchunk\u001b[49m\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 344\u001b[0m \u001b[38;5;66;03m# If we get an exception while streaming the response,\u001b[39;00m\n\u001b[1;32m 345\u001b[0m \u001b[38;5;66;03m# we want to close the response (and possibly the connection)\u001b[39;00m\n\u001b[1;32m 346\u001b[0m \u001b[38;5;66;03m# before raising that exception.\u001b[39;00m\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:210\u001b[0m, in \u001b[0;36mHTTP11Connection._receive_response_body\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m 207\u001b[0m timeout \u001b[38;5;241m=\u001b[39m timeouts\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mread\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 209\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 210\u001b[0m event \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_receive_event\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 211\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(event, h11\u001b[38;5;241m.\u001b[39mData):\n\u001b[1;32m 212\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m \u001b[38;5;28mbytes\u001b[39m(event\u001b[38;5;241m.\u001b[39mdata)\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_sync/http11.py:224\u001b[0m, in \u001b[0;36mHTTP11Connection._receive_event\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 221\u001b[0m event \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_h11_state\u001b[38;5;241m.\u001b[39mnext_event()\n\u001b[1;32m 223\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m event \u001b[38;5;129;01mis\u001b[39;00m h11\u001b[38;5;241m.\u001b[39mNEED_DATA:\n\u001b[0;32m--> 224\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_network_stream\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 225\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mREAD_NUM_BYTES\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\n\u001b[1;32m 226\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 228\u001b[0m \u001b[38;5;66;03m# If we feed this case through h11 we'll raise an exception like:\u001b[39;00m\n\u001b[1;32m 229\u001b[0m \u001b[38;5;66;03m#\u001b[39;00m\n\u001b[1;32m 230\u001b[0m \u001b[38;5;66;03m# httpcore.RemoteProtocolError: can't handle event type\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[38;5;66;03m# perspective. Instead we handle this case distinctly and treat\u001b[39;00m\n\u001b[1;32m 235\u001b[0m \u001b[38;5;66;03m# it as a ConnectError.\u001b[39;00m\n\u001b[1;32m 236\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m data \u001b[38;5;241m==\u001b[39m \u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_h11_state\u001b[38;5;241m.\u001b[39mtheir_state \u001b[38;5;241m==\u001b[39m h11\u001b[38;5;241m.\u001b[39mSEND_RESPONSE:\n", - "File \u001b[0;32m~/github.com/julep-ai/julep/playground/.venv/lib/python3.12/site-packages/httpcore/_backends/sync.py:126\u001b[0m, in \u001b[0;36mSyncStream.read\u001b[0;34m(self, max_bytes, timeout)\u001b[0m\n\u001b[1;32m 124\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m map_exceptions(exc_map):\n\u001b[1;32m 125\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sock\u001b[38;5;241m.\u001b[39msettimeout(timeout)\n\u001b[0;32m--> 126\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sock\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrecv\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmax_bytes\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/.asdf/installs/python/3.12.5/lib/python3.12/ssl.py:1233\u001b[0m, in \u001b[0;36mSSLSocket.recv\u001b[0;34m(self, buflen, flags)\u001b[0m\n\u001b[1;32m 1229\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m flags \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 1230\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 1231\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnon-zero flags not allowed in calls to recv() on \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 1232\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m)\n\u001b[0;32m-> 1233\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbuflen\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1234\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1235\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mrecv(buflen, flags)\n", - "File \u001b[0;32m~/.asdf/installs/python/3.12.5/lib/python3.12/ssl.py:1106\u001b[0m, in \u001b[0;36mSSLSocket.read\u001b[0;34m(self, len, buffer)\u001b[0m\n\u001b[1;32m 1104\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sslobj\u001b[38;5;241m.\u001b[39mread(\u001b[38;5;28mlen\u001b[39m, buffer)\n\u001b[1;32m 1105\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1106\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sslobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1107\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m SSLError \u001b[38;5;28;01mas\u001b[39;00m x:\n\u001b[1;32m 1108\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m x\u001b[38;5;241m.\u001b[39margs[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m==\u001b[39m SSL_ERROR_EOF \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msuppress_ragged_eofs:\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + "name": "stdout", + "output_type": "stream", + "text": [ + "Type: init\n", + "output: {'body': 'sup', 'from': 'diwank@julep.ai', 'subject': \"what's up\", 'to': 'help@agents.new'}\n", + "----------------------------------------------------------------------------------------------------\n", + "Type: step\n", + "output: \"what's up\" site:julep.ai/docs\n", + "----------------------------------------------------------------------------------------------------\n", + "Type: step\n", + "output: {'docs': [], 'time': 0.007443666458129883}\n", + "----------------------------------------------------------------------------------------------------\n", + "Type: step\n", + "output: ```json\n", + "{\n", + " \"subject\": \"Hello!\",\n", + " \"body\": \"Hi there! How can I assist you today? If you have any questions or need help with Julep, feel free to let me know!\"\n", + "}\n", + "```\n", + "----------------------------------------------------------------------------------------------------\n", + "Type: step\n", + "output: {'body': 'Hi there! How can I assist you today? If you have any questions or need help with Julep, feel free to let me know!', 'subject': 'Hello!'}\n", + "----------------------------------------------------------------------------------------------------\n", + "Type: finish\n", + "output: {'success': True}\n", + "----------------------------------------------------------------------------------------------------\n" ] } ], "source": [ - "# julep.executions.transitions.stream(execution_id=execution.id)" + "execution_transitions = julep.executions.transitions.list(\n", + " execution_id=execution.id).items\n", + "\n", + "for transition in reversed(execution_transitions):\n", + " print(\"Type: \", transition.type)\n", + " print(\"output: \", transition.output)\n", + " print(\"-\" * 100)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -288,7 +306,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.5" + "version": "3.12.3" } }, "nbformat": 4,