diff --git a/README.md b/README.md
index d57877707..3d82661b5 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@
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:
-1. Check out our [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on how to contribute.
+1. Check out our [CONTRIBUTING.md](https://github.com/julep-ai/julep/blob/dev/CONTRIBUTING.md) file for guidelines on how to contribute.
2. Browse our [good first issues](https://github.com/julep-ai/julep/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to find a task that interests you.
3. If you have any questions or need help, don't hesitate to reach out on our [Discord](https://discord.com/invite/JTSBGRZrzj) channel.
diff --git a/agents-api/agents_api/activities/excecute_api_call.py b/agents-api/agents_api/activities/excecute_api_call.py
index 88fabce89..e7752aa06 100644
--- a/agents-api/agents_api/activities/excecute_api_call.py
+++ b/agents-api/agents_api/activities/excecute_api_call.py
@@ -1,3 +1,4 @@
+import base64
from typing import Annotated, Any, Optional, TypedDict, Union
import httpx
@@ -20,6 +21,8 @@ class RequestArgs(TypedDict):
json_: Optional[dict[str, Any]]
cookies: Optional[dict[str, str]]
params: Optional[Union[str, dict[str, Any]]]
+ url: Optional[str]
+ headers: Optional[dict[str, str]]
@beartype
@@ -29,18 +32,23 @@ async def execute_api_call(
) -> Any:
try:
async with httpx.AsyncClient() as client:
+ arg_url = request_args.pop("url", None)
+ arg_headers = request_args.pop("headers", None)
+
response = await client.request(
method=api_call.method,
- url=str(api_call.url),
- headers=api_call.headers,
+ url=arg_url or str(api_call.url),
+ headers=arg_headers or api_call.headers,
follow_redirects=api_call.follow_redirects,
**request_args,
)
+ content_base64 = base64.b64encode(response.content).decode("ascii")
+
response_dict = {
"status_code": response.status_code,
"headers": dict(response.headers),
- "content": response.content,
+ "content": content_base64,
"json": response.json(),
}
diff --git a/agents-api/agents_api/activities/utils.py b/agents-api/agents_api/activities/utils.py
index f9f7ded12..fca62578a 100644
--- a/agents-api/agents_api/activities/utils.py
+++ b/agents-api/agents_api/activities/utils.py
@@ -1,20 +1,33 @@
+import base64
+import datetime as dt
+import functools
+import itertools
import json
-from functools import reduce
-from itertools import accumulate
-from random import random
-from time import time
-from typing import Any, Callable
+import math
+import random
+import statistics
+import string
+import time
+import urllib.parse
+from typing import Any, Callable, ParamSpec, Type, TypeVar, cast
import re2
import yaml
+import zoneinfo
from beartype import beartype
from simpleeval import EvalWithCompoundTypes, SimpleEval
-from yaml import CSafeLoader
+from yaml import CSafeDumper, CSafeLoader
+
+T = TypeVar("T")
+
+
+P = ParamSpec("P")
+R = TypeVar("R")
+
# TODO: We need to make sure that we dont expose any security issues
ALLOWED_FUNCTIONS = {
"abs": abs,
- "accumulate": accumulate,
"all": all,
"any": any,
"bool": bool,
@@ -25,23 +38,169 @@
"int": int,
"len": len,
"list": list,
- "load_json": json.loads,
- "load_yaml": lambda string: yaml.load(string, Loader=CSafeLoader),
"map": map,
- "match_regex": lambda pattern, string: bool(re2.fullmatch(pattern, string)),
"max": max,
"min": min,
- "random": random,
"range": range,
- "reduce": reduce,
"round": round,
- "search_regex": lambda pattern, string: re2.search(pattern, string),
"set": set,
"str": str,
"sum": sum,
- "time": time,
"tuple": tuple,
+ "reduce": functools.reduce,
"zip": zip,
+ "search_regex": lambda pattern, string: re2.search(pattern, string),
+ "load_json": json.loads,
+ "load_yaml": lambda string: yaml.load(string, Loader=CSafeLoader),
+ "match_regex": lambda pattern, string: bool(re2.fullmatch(pattern, string)),
+}
+
+
+class stdlib_re:
+ fullmatch = re2.fullmatch
+ search = re2.search
+ escape = re2.escape
+ findall = re2.findall
+ finditer = re2.finditer
+ match = re2.match
+ split = re2.split
+ sub = re2.sub
+ subn = re2.subn
+
+
+class stdlib_json:
+ loads = json.loads
+ dumps = json.dumps
+
+
+class stdlib_yaml:
+ load = lambda string: yaml.load(string, Loader=CSafeLoader) # noqa: E731
+ dump = lambda value: yaml.dump(value, Dumper=CSafeDumper) # noqa: E731
+
+
+class stdlib_time:
+ strftime = time.strftime
+ strptime = time.strptime
+ time = time
+
+
+class stdlib_random:
+ choice = random.choice
+ choices = random.choices
+ sample = random.sample
+ shuffle = random.shuffle
+ randrange = random.randrange
+ randint = random.randint
+ random = random.random
+
+
+class stdlib_itertools:
+ accumulate = itertools.accumulate
+
+
+class stdlib_functools:
+ partial = functools.partial
+ reduce = functools.reduce
+
+
+class stdlib_base64:
+ b64encode = base64.b64encode
+ b64decode = base64.b64decode
+
+
+class stdlib_urllib:
+ class parse:
+ urlparse = urllib.parse.urlparse
+ urlencode = urllib.parse.urlencode
+ unquote = urllib.parse.unquote
+ quote = urllib.parse.quote
+ parse_qs = urllib.parse.parse_qs
+ parse_qsl = urllib.parse.parse_qsl
+ urlsplit = urllib.parse.urlsplit
+ urljoin = urllib.parse.urljoin
+ unwrap = urllib.parse.unwrap
+
+
+class stdlib_string:
+ ascii_letters = string.ascii_letters
+ ascii_lowercase = string.ascii_lowercase
+ ascii_uppercase = string.ascii_uppercase
+ digits = string.digits
+ hexdigits = string.hexdigits
+ octdigits = string.octdigits
+ punctuation = string.punctuation
+ whitespace = string.whitespace
+ printable = string.printable
+
+
+class stdlib_zoneinfo:
+ ZoneInfo = zoneinfo.ZoneInfo
+
+
+class stdlib_datetime:
+ class timezone:
+ class utc:
+ utc = dt.timezone.utc
+
+ class datetime:
+ now = dt.datetime.now
+ datetime = dt.datetime
+ timedelta = dt.timedelta
+ date = dt.date
+ time = dt.time
+
+ timedelta = dt.timedelta
+
+
+class stdlib_math:
+ sqrt = math.sqrt
+ exp = math.exp
+ ceil = math.ceil
+ floor = math.floor
+ isinf = math.isinf
+ isnan = math.isnan
+ log = math.log
+ log10 = math.log10
+ log2 = math.log2
+ pow = math.pow
+ sin = math.sin
+ cos = math.cos
+ tan = math.tan
+ asin = math.asin
+ acos = math.acos
+ atan = math.atan
+ atan2 = math.atan2
+
+ pi = math.pi
+ e = math.e
+
+
+class stdlib_statistics:
+ mean = statistics.mean
+ stdev = statistics.stdev
+ geometric_mean = statistics.geometric_mean
+ median = statistics.median
+ median_low = statistics.median_low
+ median_high = statistics.median_high
+ mode = statistics.mode
+ quantiles = statistics.quantiles
+
+
+stdlib = {
+ "re": stdlib_re,
+ "json": stdlib_json,
+ "yaml": stdlib_yaml,
+ "time": stdlib_time,
+ "random": stdlib_random,
+ "itertools": stdlib_itertools,
+ "functools": stdlib_functools,
+ "base64": stdlib_base64,
+ "urllib": stdlib_urllib,
+ "string": stdlib_string,
+ "zoneinfo": stdlib_zoneinfo,
+ "datetime": stdlib_datetime,
+ "math": stdlib_math,
+ "statistics": stdlib_statistics,
}
@@ -50,7 +209,7 @@ def get_evaluator(
names: dict[str, Any], extra_functions: dict[str, Callable] | None = None
) -> SimpleEval:
evaluator = EvalWithCompoundTypes(
- names=names, functions=ALLOWED_FUNCTIONS | (extra_functions or {})
+ names=names | stdlib, functions=ALLOWED_FUNCTIONS | (extra_functions or {})
)
return evaluator
diff --git a/agents-api/agents_api/common/exceptions/tasks.py b/agents-api/agents_api/common/exceptions/tasks.py
index 8ead1e7e2..81331234c 100644
--- a/agents-api/agents_api/common/exceptions/tasks.py
+++ b/agents-api/agents_api/common/exceptions/tasks.py
@@ -20,7 +20,7 @@
import temporalio.exceptions
# List of error types that should not be retried
-NON_RETRYABLE_ERROR_TYPES = [
+NON_RETRYABLE_ERROR_TYPES = (
# Temporal-specific errors
temporalio.exceptions.WorkflowAlreadyStartedError,
temporalio.exceptions.TerminatedError,
@@ -99,10 +99,10 @@
litellm.exceptions.ServiceUnavailableError,
litellm.exceptions.OpenAIError,
litellm.exceptions.APIError,
-]
+)
-def is_non_retryable_error(error: Exception) -> bool:
+def is_non_retryable_error(error: BaseException) -> bool:
"""
Determines if the given error is non-retryable.
@@ -115,4 +115,4 @@ def is_non_retryable_error(error: Exception) -> bool:
Returns:
bool: True if the error is non-retryable, False otherwise.
"""
- return isinstance(error, tuple(NON_RETRYABLE_ERROR_TYPES))
+ return isinstance(error, NON_RETRYABLE_ERROR_TYPES)
diff --git a/agents-api/agents_api/common/interceptors.py b/agents-api/agents_api/common/interceptors.py
index 2fb077c45..c6e8e2eaf 100644
--- a/agents-api/agents_api/common/interceptors.py
+++ b/agents-api/agents_api/common/interceptors.py
@@ -31,7 +31,7 @@ class CustomActivityInterceptor(ActivityInboundInterceptor):
async def execute_activity(self, input: ExecuteActivityInput):
try:
return await super().execute_activity(input)
- except Exception as e:
+ except BaseException as e:
if is_non_retryable_error(e):
raise ApplicationError(
str(e),
@@ -53,7 +53,7 @@ class CustomWorkflowInterceptor(WorkflowInboundInterceptor):
async def execute_workflow(self, input: ExecuteWorkflowInput):
try:
return await super().execute_workflow(input)
- except Exception as e:
+ except BaseException as e:
if is_non_retryable_error(e):
raise ApplicationError(
str(e),
diff --git a/agents-api/agents_api/common/protocol/tasks.py b/agents-api/agents_api/common/protocol/tasks.py
index bbb5c28d3..bd4aaa5a2 100644
--- a/agents-api/agents_api/common/protocol/tasks.py
+++ b/agents-api/agents_api/common/protocol/tasks.py
@@ -118,7 +118,8 @@
} # type: ignore
-PartialTransition: Type[BaseModel] = create_partial_model(CreateTransitionRequest)
+class PartialTransition(create_partial_model(CreateTransitionRequest)):
+ user_state: dict[str, Any] = Field(default_factory=dict)
class ExecutionInput(BaseModel):
diff --git a/agents-api/agents_api/models/execution/create_execution_transition.py b/agents-api/agents_api/models/execution/create_execution_transition.py
index f40395126..2b1c09ae8 100644
--- a/agents-api/agents_api/models/execution/create_execution_transition.py
+++ b/agents-api/agents_api/models/execution/create_execution_transition.py
@@ -176,7 +176,7 @@ def create_execution_transition(
data=UpdateExecutionRequest(
status=transition_to_execution_status[data.type]
),
- output=data.output if data.type == "finish" else None,
+ output=data.output if data.type != "error" else None,
error=str(data.output)
if data.type == "error" and data.output
else None,
diff --git a/agents-api/agents_api/workflows/task_execution/__init__.py b/agents-api/agents_api/workflows/task_execution/__init__.py
index edf54fb12..155b49397 100644
--- a/agents-api/agents_api/workflows/task_execution/__init__.py
+++ b/agents-api/agents_api/workflows/task_execution/__init__.py
@@ -118,30 +118,6 @@
# Main workflow definition
@workflow.defn
class TaskExecutionWorkflow:
- user_state: dict[str, Any] = {}
-
- def __init__(self) -> None:
- self.user_state = {}
-
- # TODO: Add endpoints for getting and setting user state for an execution
- # Query methods for user state
- @workflow.query
- def get_user_state(self) -> dict[str, Any]:
- return self.user_state
-
- @workflow.query
- def get_user_state_by_key(self, key: str) -> Any:
- return self.user_state.get(key)
-
- # Signal methods for updating user state
- @workflow.signal
- def set_user_state(self, key: str, value: Any) -> None:
- self.user_state[key] = value
-
- @workflow.signal
- def update_user_state(self, values: dict[str, Any]) -> None:
- self.user_state.update(values)
-
# Main workflow run method
@workflow.run
async def run(
@@ -149,11 +125,7 @@ async def run(
execution_input: ExecutionInput,
start: TransitionTarget = TransitionTarget(workflow="main", step=0),
previous_inputs: list[Any] = [],
- user_state: dict[str, Any] = {},
) -> Any:
- # Set the initial user state
- self.user_state = user_state
-
workflow.logger.info(
f"TaskExecutionWorkflow for task {execution_input.task.id}"
f" [LOC {start.workflow}.{start.step}]"
@@ -258,7 +230,6 @@ async def run(
switch=switch,
index=index,
previous_inputs=previous_inputs,
- user_state=self.user_state,
)
state = PartialTransition(output=result)
@@ -276,7 +247,6 @@ async def run(
else_branch=else_branch,
condition=condition,
previous_inputs=previous_inputs,
- user_state=self.user_state,
)
state = PartialTransition(output=result)
@@ -288,7 +258,6 @@ async def run(
do_step=do_step,
items=items,
previous_inputs=previous_inputs,
- user_state=self.user_state,
)
state = PartialTransition(output=result)
@@ -303,7 +272,6 @@ async def run(
reduce=reduce,
initial=initial,
previous_inputs=previous_inputs,
- user_state=self.user_state,
)
state = PartialTransition(output=result)
@@ -316,7 +284,6 @@ async def run(
map_defn=map_defn,
items=items,
previous_inputs=previous_inputs,
- user_state=self.user_state,
initial=initial,
reduce=reduce,
parallelism=parallelism,
@@ -376,7 +343,6 @@ async def run(
context,
start=yield_next_target,
previous_inputs=[output],
- user_state=self.user_state,
)
state = PartialTransition(output=result)
@@ -439,14 +405,15 @@ async def run(
case SetStep(), StepOutcome(output=evaluated_output):
workflow.logger.info("Set step: Updating user state")
- self.update_user_state(evaluated_output)
# Pass along the previous output unchanged
- state = PartialTransition(output=context.current_input)
+ state = PartialTransition(
+ output=context.current_input, user_state=evaluated_output
+ )
case GetStep(get=key), _:
workflow.logger.info(f"Get step: Fetching '{key}' from user state")
- value = self.get_user_state_by_key(key)
+ value = workflow.memo_value(key, default=None)
workflow.logger.debug(f"Retrieved value: {value}")
state = PartialTransition(output=value)
@@ -596,5 +563,5 @@ def model_dump(obj):
context.execution_input,
start=final_state.next,
previous_inputs=previous_inputs + [final_state.output],
- user_state=self.user_state,
+ user_state=state.user_state,
)
diff --git a/agents-api/agents_api/workflows/task_execution/helpers.py b/agents-api/agents_api/workflows/task_execution/helpers.py
index 04449db58..271f33dbf 100644
--- a/agents-api/agents_api/workflows/task_execution/helpers.py
+++ b/agents-api/agents_api/workflows/task_execution/helpers.py
@@ -27,15 +27,23 @@ async def continue_as_child(
previous_inputs: list[Any],
user_state: dict[str, Any] = {},
) -> Any:
- return await workflow.execute_child_workflow(
- "TaskExecutionWorkflow",
+ info = workflow.info()
+
+ if info.is_continue_as_new_suggested():
+ run = workflow.continue_as_new
+ else:
+ run = lambda *args, **kwargs: workflow.execute_child_workflow( # noqa: E731
+ info.workflow_type, *args, **kwargs
+ )
+
+ return await run(
args=[
execution_input,
start,
previous_inputs,
- user_state,
],
retry_policy=DEFAULT_RETRY_POLICY,
+ memo=workflow.memo() | user_state,
)
@@ -46,7 +54,7 @@ async def execute_switch_branch(
switch: list,
index: int,
previous_inputs: list[Any],
- user_state: dict[str, Any],
+ user_state: dict[str, Any] = {},
) -> Any:
workflow.logger.info(f"Switch step: Chose branch {index}")
chosen_branch = switch[index]
@@ -77,7 +85,7 @@ async def execute_if_else_branch(
else_branch: WorkflowStep,
condition: bool,
previous_inputs: list[Any],
- user_state: dict[str, Any],
+ user_state: dict[str, Any] = {},
) -> Any:
workflow.logger.info(f"If-Else step: Condition evaluated to {condition}")
chosen_branch = then_branch if condition else else_branch
@@ -108,7 +116,7 @@ async def execute_foreach_step(
do_step: WorkflowStep,
items: list[Any],
previous_inputs: list[Any],
- user_state: dict[str, Any],
+ user_state: dict[str, Any] = {},
) -> Any:
workflow.logger.info(f"Foreach step: Iterating over {len(items)} items")
results = []
@@ -142,7 +150,7 @@ async def execute_map_reduce_step(
map_defn: WorkflowStep,
items: list[Any],
previous_inputs: list[Any],
- user_state: dict[str, Any],
+ user_state: dict[str, Any] = {},
reduce: str | None = None,
initial: Any = [],
) -> Any:
@@ -185,7 +193,7 @@ async def execute_map_reduce_step_parallel(
map_defn: WorkflowStep,
items: list[Any],
previous_inputs: list[Any],
- user_state: dict[str, Any],
+ user_state: dict[str, Any] = {},
initial: Any = [],
reduce: str | None = None,
parallelism: int = task_max_parallelism,
diff --git a/agents-api/tests/test_execution_workflow.py b/agents-api/tests/test_execution_workflow.py
index e5ef7110a..f8a89cb62 100644
--- a/agents-api/tests/test_execution_workflow.py
+++ b/agents-api/tests/test_execution_workflow.py
@@ -819,9 +819,9 @@ async def _(
"input_schema": {"type": "object", "additionalProperties": True},
"main": [
{
- "if": "True",
+ "if": "False",
"then": {"evaluate": {"hello": '"world"'}},
- "else": {"evaluate": {"hello": '"nope"'}},
+ "else": {"evaluate": {"hello": "random.randint(0, 10)"}},
},
],
}
@@ -849,7 +849,7 @@ async def _(
mock_run_task_execution_workflow.assert_called_once()
result = await handle.result()
- assert result["hello"] == "world"
+ assert result["hello"] in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@test("workflow: switch step")
diff --git a/cookbooks/01-Website_Crawler_using_Spider.ipynb b/cookbooks/01-Website_Crawler_using_Spider.ipynb
index 36a77d525..c65a3cb40 100644
--- a/cookbooks/01-Website_Crawler_using_Spider.ipynb
+++ b/cookbooks/01-Website_Crawler_using_Spider.ipynb
@@ -173,7 +173,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Here is a Task which uses a agent to generate a sarcastic response to a given text using a DuckDuckGo search tool.\n",
+ "Here is a Task to crawl a website using the Spider Integration tool.\n",
"\n",
"More on how to define a task can be found [here](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)."
]
@@ -207,7 +207,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creating/Updating a task to generate a sarcastic response to a given text using a Intergation."
+ "Creating/Updating a task"
]
},
{
@@ -237,7 +237,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creates a execution worflow for the Task defined in the yaml file."
+ "Creates a execution worklow for the Task defined in the yaml file."
]
},
{
diff --git a/cookbooks/01-Website_Crawler_using_Spider.py b/cookbooks/01-Website_Crawler_using_Spider.py
index 978fd3286..69d5785be 100644
--- a/cookbooks/01-Website_Crawler_using_Spider.py
+++ b/cookbooks/01-Website_Crawler_using_Spider.py
@@ -57,15 +57,20 @@
input={}
)
+# Waiting for the execution to complete
+import time
+time.sleep(5)
+
# 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)
+print("Execution Steps:")
+for transition in transitions:
+ print(transition)
-# Streaming the execution steps
+# Stream the steps of the defined task
print("Streaming execution transitions:")
-for transition in client.executions.transitions.stream(execution_id=execution.id):
- print(transition)
\ No newline at end of file
+print(client.executions.transitions.stream(execution_id=execution.id))
\ No newline at end of file
diff --git a/cookbooks/02-Sarcastic_News_Headline_Generator.ipynb b/cookbooks/02-Sarcastic_News_Headline_Generator.ipynb
index fded810a1..fb7957a5f 100644
--- a/cookbooks/02-Sarcastic_News_Headline_Generator.ipynb
+++ b/cookbooks/02-Sarcastic_News_Headline_Generator.ipynb
@@ -200,8 +200,6 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Here is a Task which uses a agent to generate a sarcastic response to a given text using a DuckDuckGo search tool.\n",
- "\n",
"More on how to define a task can be found [here](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)."
]
},
@@ -242,7 +240,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creating/Updating a task to generate a sarcastic response to a given text using a Intergation."
+ "Creating/Updating a task."
]
},
{
@@ -272,7 +270,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creates a execution worflow for the Task defined in the yaml file."
+ "Creates a execution worklow for the Task defined in the yaml file."
]
},
{
diff --git a/cookbooks/02-Sarcastic_News_Headline_Generator.py b/cookbooks/02-Sarcastic_News_Headline_Generator.py
index c658a6569..cf305c15e 100644
--- a/cookbooks/02-Sarcastic_News_Headline_Generator.py
+++ b/cookbooks/02-Sarcastic_News_Headline_Generator.py
@@ -75,15 +75,21 @@
}
)
+# Waiting for the execution to complete
+import time
+time.sleep(5)
+
# 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)
+print("Execution Steps:")
+for transition in transitions:
+ print(transition)
# Stream the steps of the defined task
print("Streaming execution transitions:")
-for transition in client.executions.transitions.stream(execution_id=execution.id):
- print(transition)
+print(client.executions.transitions.stream(execution_id=execution.id))
+
diff --git a/cookbooks/03-SmartResearcher_With_WebSearch.ipynb b/cookbooks/03-SmartResearcher_With_WebSearch.ipynb
index c01b54652..9bb6436c4 100644
--- a/cookbooks/03-SmartResearcher_With_WebSearch.ipynb
+++ b/cookbooks/03-SmartResearcher_With_WebSearch.ipynb
@@ -213,8 +213,6 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Here is a Task which uses a agent to generate a sarcastic response to a given text using a DuckDuckGo and Wikipedia tool.\n",
- "\n",
"More on how to define a task can be found [here](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)."
]
},
@@ -272,7 +270,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creating/Updating a task to generate a sarcastic response to a given text using a Intergation."
+ "Creating/Updating a task."
]
},
{
@@ -302,7 +300,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creates a execution worflow for the Task defined in the yaml file."
+ "Creates a execution worklow for the Task defined in the yaml file."
]
},
{
diff --git a/cookbooks/03-SmartResearcher_With_WebSearch.py b/cookbooks/03-SmartResearcher_With_WebSearch.py
index 9996a5dd5..6b0b210fb 100644
--- a/cookbooks/03-SmartResearcher_With_WebSearch.py
+++ b/cookbooks/03-SmartResearcher_With_WebSearch.py
@@ -1,6 +1,6 @@
import uuid
from julep import Client
-import yaml
+import yaml, time
# Global UUID is generated for agent and task
AGENT_UUID = uuid.uuid4()
@@ -92,13 +92,19 @@
print(execution.id)
+# Wait for the execution to complete
+time.sleep(10)
+
# 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)
+print("Execution Steps:")
+for transition in transitions:
+ print(transition)
-# Streaming the execution steps
-client.executions.transitions.stream(execution_id=execution.id)
\ No newline at end of file
+# Stream the steps of the defined task
+print("Streaming execution transitions:")
+print(client.executions.transitions.stream(execution_id=execution.id))
\ No newline at end of file
diff --git a/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb b/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb
index d7fc39840..dad492f20 100644
--- a/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb
+++ b/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.ipynb
@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "div align=\"center\">\n",
+ "
\n",
"
\n",
"
\n",
"\n",
@@ -219,8 +219,6 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Here is a Task which uses a agent to generate a sarcastic response to a given text using a DuckDuckGo and Wikipedia tool.\n",
- "\n",
"More on how to define a task can be found [here](https://github.com/julep-ai/julep/blob/dev/docs/julep-concepts.md)."
]
},
@@ -295,7 +293,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creating/Updating a task to generate a sarcastic response to a given text using a Intergation."
+ "Creating/Updating a task."
]
},
{
@@ -325,7 +323,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Creates a execution worflow for the Task defined in the yaml file."
+ "Creates a execution worklow for the Task defined in the yaml file."
]
},
{
diff --git a/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py b/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py
index cde5d71a6..bd446a849 100644
--- a/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py
+++ b/cookbooks/04-TripPlanner_With_Weather_And_WikiInfo.py
@@ -107,6 +107,10 @@
print(f"Execution ID: {execution.id}")
+# Wait for the execution to complete
+import time
+time.sleep(10)
+
# Getting the execution details
execution = client.executions.get(execution.id)
print("Execution Output:")
@@ -114,10 +118,11 @@
# List all steps of the executed task
print("Execution Steps:")
-for item in client.executions.transitions.list(execution_id=execution.id).items:
- print(item)
+transitions = client.executions.transitions.list(execution_id=execution.id).items
+print("Execution Steps:")
+for transition in transitions:
+ print(transition)
-# 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
+# Stream the steps of the defined task
+print("Streaming execution transitions:")
+print(client.executions.transitions.stream(execution_id=execution.id))
\ 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
index c701471f7..05b16f7bd 100644
--- a/cookbooks/05-Basic_Agent_Creation_and_Interaction.py
+++ b/cookbooks/05-Basic_Agent_Creation_and_Interaction.py
@@ -1,3 +1,5 @@
+# UNDER CONSTRUCTION - NOT WORKING YET
+
import uuid
from julep import Client
@@ -26,7 +28,7 @@
agent_id=AGENT_UUID,
name=name,
about=about,
- model="gpt-4-turbo",
+ model="gpt-4o",
)
print(f"Agent created with ID: {agent.id}")
diff --git a/cookbooks/06-Designing_Multi-Step_Tasks.py b/cookbooks/06-Designing_Multi-Step_Tasks.py
index 395f409cf..b623ae378 100644
--- a/cookbooks/06-Designing_Multi-Step_Tasks.py
+++ b/cookbooks/06-Designing_Multi-Step_Tasks.py
@@ -1,5 +1,5 @@
import uuid
-import yaml
+import yaml, time
from julep import Client
# Global UUID is generated for agent and task
@@ -28,14 +28,13 @@
agent_id=AGENT_UUID,
name=name,
about=about,
- model="gpt-4-turbo",
+ model="gpt-4o",
)
# 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",
@@ -71,7 +70,7 @@
# Step 2: Tool Call - Web search for each question
- foreach:
- in: "_.split('\n')"
+ in: _.split('\\n')
do:
tool: web_search
arguments:
@@ -121,10 +120,13 @@
print(f"Execution ID: {execution.id}")
+# Wait for the execution to complete
+time.sleep(10)
+
# Getting the execution details
execution = client.executions.get(execution.id)
print("Execution Output:")
-print(execution.output)
+print(client.executions.transitions.list(execution_id=execution.id).items[0].output)
# Listing all the steps of a defined task
transitions = client.executions.transitions.list(execution_id=execution.id).items
@@ -132,7 +134,6 @@
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
+# Stream the steps of the defined task
+print("Streaming execution transitions:")
+print(client.executions.transitions.stream(execution_id=execution.id))
\ 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
index fa93f687a..71d8780d3 100644
--- a/cookbooks/07-Integrating_External_Tools_and_APIs.py
+++ b/cookbooks/07-Integrating_External_Tools_and_APIs.py
@@ -19,10 +19,10 @@
agent_id=AGENT_UUID,
name=name,
about=about,
- model="gpt-4-turbo",
+ model="gpt-4o",
)
-# Defining a Task
+# Defining a Task with various step types
task_def = yaml.safe_load("""
name: Comprehensive Analysis Report
@@ -42,14 +42,14 @@
integration:
provider: brave
setup:
- api_key: "YOUR_BRAVE_API_KEY"
+ api_key: "YOUR_API_KEY"
- name: weather
type: integration
integration:
provider: weather
setup:
- openweathermap_api_key: "YOUR_OPENWEATHERMAP_API_KEY"
+ openweathermap_api_key: "YOUR_API_KEY"
- name: wikipedia
type: integration
@@ -59,20 +59,20 @@
main:
- tool: brave_search
arguments:
- query: "{{inputs[0].topic}} latest developments"
+ query: "inputs[0].topic + ' latest developments'"
- tool: weather
arguments:
- location: "{{inputs[0].location}}"
+ location: inputs[0].location
- tool: wikipedia
arguments:
- query: "{{inputs[0].topic}}"
+ 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}}"
+ 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)
@@ -88,8 +88,6 @@
Provide a well-structured, informative report that synthesizes information from all these sources.
unwrap: true
-
-- return: _
""")
# Creating/Updating a task
@@ -104,23 +102,27 @@
task_id=task.id,
input={
"topic": "Renewable Energy",
- "location": "Berlin, Germany"
+ "location": "Berlin"
}
)
print(f"Execution ID: {execution.id}")
+# Waiting for the execution to complete
+import time
+time.sleep(5)
+
# Getting the execution details
execution = client.executions.get(execution.id)
print("Execution Output:")
print(execution.output)
# List all steps of the executed task
+transitions = client.executions.transitions.list(execution_id=execution.id).items
print("Execution Steps:")
-for item in client.executions.transitions.list(execution_id=execution.id).items:
- print(item)
+for transition in transitions:
+ print(transition)
-# 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
+# Stream the steps of the defined task
+print("Streaming execution transitions:")
+print(client.executions.transitions.stream(execution_id=execution.id))
\ No newline at end of file
diff --git a/cookbooks/08-Managing_Persistent_Sessions.py b/cookbooks/08-Managing_Persistent_Sessions.py
index 40077b7df..ab2472ac8 100644
--- a/cookbooks/08-Managing_Persistent_Sessions.py
+++ b/cookbooks/08-Managing_Persistent_Sessions.py
@@ -27,7 +27,7 @@
agent_id=AGENT_UUID,
name="Session Manager",
about="An AI agent specialized in managing persistent sessions and context.",
- model="gpt-4-turbo",
+ model="gpt-4o",
)
# Defining a task for managing user context
@@ -44,7 +44,7 @@
main:
- prompt:
- role: system
+ - 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}}
@@ -53,16 +53,17 @@
Respond to the user and update the context with any new relevant information.
unwrap: true
-
+
- evaluate:
- updated_context: >-
- {**inputs[0].session_context,
+ session_context: >-
+ {
+ **inputs[0].session_context,
'last_interaction': inputs[0].user_input,
- 'agent_response': _}
+ 'agent_response': _}
- return:
response: _
- context: outputs[1].updated_context
+ context: outputs[1].session_context
""")
# Creating the task
@@ -78,7 +79,7 @@ def user_interaction(prompt):
# Create a session
session = client.sessions.create(
- agent_id=AGENT_UUID,
+ agent=agent.id,
context_overflow="adaptive" # Use adaptive context management
)
@@ -100,10 +101,16 @@ def user_interaction(prompt):
# Get the execution result
result = client.executions.get(execution.id)
+
+ # Wait for the execution to complete
+ time.sleep(2)
# Update the context and print the response
- context = result.output['context']
- print(f"Agent: {result.output['response']}")
+ final_response = client.executions.transitions.list(execution_id=result.id).items[0].output
+ print(final_response)
+ # print(client.executions.transitions.list(execution_id=result.id).items[0])
+ context = final_response['session_context']
+ print(f"Agent: {final_response['session_context']['agent_response']}")
print(f"Updated Context: {context}")
print()
@@ -127,11 +134,13 @@ def user_interaction(prompt):
)
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']}")
+# Wait for the execution to complete
+time.sleep(2)
+overflow_response = client.executions.transitions.list(execution_id=overflow_result.id).items[0].output
+print(f"Agent response to large input: {overflow_response['session_context']['agent_response']}")
+print(f"Updated context after overflow: {overflow_response['session_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
+history = client.sessions.history(session_id=session.id)
+print(history)
diff --git a/cookbooks/09-User_Management_and_Personalization.py b/cookbooks/09-User_Management_and_Personalization.py
index 18f9df238..50ada9570 100644
--- a/cookbooks/09-User_Management_and_Personalization.py
+++ b/cookbooks/09-User_Management_and_Personalization.py
@@ -12,7 +12,7 @@
# 9. Display updated personalized recommendations after preference changes
import uuid
-import yaml
+import yaml, time
from julep import Client
# Global UUIDs for agent and tasks
@@ -29,7 +29,7 @@
agent_id=AGENT_UUID,
name="Personalization Assistant",
about="An AI agent specialized in user management and personalized content recommendations.",
- model="gpt-4-turbo",
+ model="gpt-4o",
)
# Defining a task for user registration and profile creation
@@ -48,7 +48,7 @@
main:
- prompt:
- role: system
+ - role: system
content: >-
You are a user registration assistant. Create a user profile based on the following information:
Username: {{inputs[0].username}}
@@ -58,15 +58,13 @@
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
+ username: inputs[0].username
+ interests: inputs[0].interests
+ bio: _.split('\\n')[0]
+ content_preferences: _.split('\\n')[1]
+
+- return:
+ profile: _
""")
# Creating the registration task
@@ -85,44 +83,38 @@
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"}
- ]
+ description: User's profile containing their interests and preferences.
+ content_list:
+ type: array
+ description: List of available content to recommend from.
+ items:
+ type: object
+ properties:
+ id:
+ type: integer
+ title:
+ type: string
+ category:
+ type: string
main:
-- tool: content_database
- arguments: {}
-
- prompt:
- role: system
+ - 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]}}
-
+ {{inputs[0].content_list}}
+
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
@@ -141,19 +133,35 @@ def register_user(username, interests):
"interests": interests
}
)
+ # Wait for the execution to complete
+ time.sleep(2)
result = client.executions.get(execution.id)
- return result.output
+ user_result = client.executions.transitions.list(execution_id=result.id).items[0].output
+ return user_result
-# Function to get personalized content recommendations
+# Function to get personalized recommendations for a user
def get_recommendations(user_profile):
+ content_list = [
+ {"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"}
+ ]
+
execution = client.executions.create(
task_id=RECOMMENDATION_TASK_UUID,
input={
- "user_profile": user_profile
+ "user_profile": user_profile,
+ "content_list": content_list
}
)
+ # Wait for the execution to complete
+ time.sleep(2)
result = client.executions.get(execution.id)
- return result.output
+ recommendation_respose = client.executions.transitions.list(execution_id=result.id).items[0].output
+ return recommendation_respose
+
# Function to update user preferences
def update_user_preferences(user_profile, new_interests):
diff --git a/cookbooks/10-Document_Management_and_Search.py b/cookbooks/10-Document_Management_and_Search.py
index 87cc492aa..70db82d3f 100644
--- a/cookbooks/10-Document_Management_and_Search.py
+++ b/cookbooks/10-Document_Management_and_Search.py
@@ -10,8 +10,10 @@
# 7. Execute the document search task
# 8. Display the search results
+# UNDER CONSTRUCTION - YAML is working but the flow is not correct yet
+
import uuid
-import yaml
+import yaml,time
from julep import Client
# Global UUID is generated for agent and tasks
@@ -43,21 +45,32 @@
items:
type: object
properties:
+ tile:
+ type: string
content:
type: string
metadata:
type: object
+
+tools:
+- name: document_create
+ system:
+ resource: agent
+ subresource: doc
+ operation: create
main:
- over: inputs[0].documents
map:
tool: document_upload
arguments:
+ agent_id: "'{agent.id}'"
+ title: _.title
content: _.content
metadata: _.metadata
- prompt:
- role: system
+ - role: system
content: >-
You have successfully uploaded and indexed {{len(outputs[0])}} documents.
Provide a summary of the uploaded documents.
@@ -82,14 +95,22 @@
filters:
type: object
+tools:
+- name: document_search
+ system:
+ resource: agent
+ subresource: doc
+ operation: search
+
main:
- tool: document_search
arguments:
- query: inputs[0].query
- filters: inputs[0].filters
+ agent_id: "'{agent.id}'"
+ text: inputs[0].query
+ metadata_filters: inputs[0].filters
- prompt:
- role: system
+ - role: system
content: >-
Based on the search results, provide a summary of the most relevant documents found.
Search query: {{inputs[0].query}}
@@ -97,6 +118,7 @@
Results:
{{outputs[0]}}
+ unwrap: true
""")
# Creating the search task
@@ -109,14 +131,17 @@
# Sample documents
sample_documents = [
{
+ "Title": "The Impact of Technology on Society",
"content": "Artificial Intelligence (AI) is revolutionizing various industries, including healthcare, finance, and transportation.",
"metadata": {"category": "technology", "author": "John Doe"}
},
{
+ "Title": "Climate Change and Global Warming",
"content": "Climate change is a pressing global issue that requires immediate action from governments, businesses, and individuals.",
"metadata": {"category": "environment", "author": "Jane Smith"}
},
{
+ "Title": "Remote Work and Digital Transformation",
"content": "The COVID-19 pandemic has accelerated the adoption of remote work and digital technologies across many organizations.",
"metadata": {"category": "business", "author": "Alice Johnson"}
}
@@ -129,8 +154,12 @@
)
print("Uploading and indexing documents...")
+# Wait for the execution to complete
+time.sleep(5)
upload_result = client.executions.get(upload_execution.id)
-print(upload_result.output)
+upload_response = client.executions.transitions.list(upload_execution.id).items[0].output
+print("Upload Result:")
+print(upload_response)
# Execute the document search task
search_execution = client.executions.create(
@@ -142,9 +171,9 @@
)
print("\nSearching documents...")
+# Wait for the execution to complete
+time.sleep(5)
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:
@@ -153,4 +182,5 @@
print(f"- {doc['content']} (Score: {doc['score']})")
print("\nSearch Summary:")
-print(search_result.output)
\ No newline at end of file
+search_response = client.executions.transitions.list(search_result.id).items[0].output
+print(search_response)
\ No newline at end of file
diff --git a/cookbooks/11-Advanced_Chat_Interactions.py b/cookbooks/11-Advanced_Chat_Interactions.py
index 692112be1..1a6b13026 100644
--- a/cookbooks/11-Advanced_Chat_Interactions.py
+++ b/cookbooks/11-Advanced_Chat_Interactions.py
@@ -12,6 +12,8 @@
# d. Integrating external information during the conversation
# 6. Display the chat history and any relevant metrics
+# UNDER CONSTRUCTION - YAML is working but the flow is not correct yet
+
import uuid
import yaml
import os
@@ -34,14 +36,13 @@
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",
+ model="gpt-4o",
)
# 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",
@@ -74,48 +75,49 @@
integration:
provider: weather
setup:
- api_key: "YOUR_WEATHER_API_KEY"
+ api_key: "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: _
+- if: "_.context_length > '10'"
+ then:
+ evaluate:
+ summarized_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}}
+ unwrap: true
+ 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}}
+ unwrap: true
+
+- if: "'weather' in inputs[0].user_input.lower()"
+ then:
+ tool: weather_api
+ arguments:
+ location: inputs[0].user_input.lower.split('weather')[1].strip()
+ prompt:
+ - role: system
+ content: >-
+ The user mentioned weather. Here's the current weather information for {{inputs[0].user_input.lower.split('weather')[1].strip()}}
+
+ Incorporate this information into your response.
+ unwrap: true
+
+- return:
+ summary: _
""")
# Creating the chat task
@@ -139,7 +141,7 @@ 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)
+ session = client.sessions.create(agent=AGENT_UUID)
while True:
user_input = get_user_input()
@@ -155,8 +157,11 @@ def run_chat_session():
"chat_history": chat_history
}
)
-
+ # Wait for the execution to complete
+ time.sleep(3)
result = client.executions.get(execution.id)
+ print(client.executions.transitions.list(execution.id).items)
+ print(f"Execution result: {result.output}")
assistant_response = result.output
chat_history.append({"role": "assistant", "content": assistant_response})
@@ -169,9 +174,4 @@ def run_chat_session():
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
+run_chat_session()
\ No newline at end of file
diff --git a/cookbooks/12-Monitoring_Task_Executions.py b/cookbooks/12-Monitoring_Task_Executions.py
index 7e5f576a0..675ff27a1 100644
--- a/cookbooks/12-Monitoring_Task_Executions.py
+++ b/cookbooks/12-Monitoring_Task_Executions.py
@@ -12,6 +12,8 @@
# 5. Execute the task and demonstrate real-time monitoring
# 6. Display execution summary and metrics
+# UNDER CONSTRUCTION - NOT WORKING YET
+
import uuid
import yaml
from julep import Client
@@ -30,7 +32,7 @@
agent_id=AGENT_UUID,
name="Task Execution Monitor",
about="An AI agent designed to monitor and manage complex task executions.",
- model="gpt-4-turbo",
+ model="gpt-4o",
)
# Defining a multi-step task that simulates a complex workflow
diff --git a/cookbooks/13-Error_Handling_and_Recovery.py b/cookbooks/13-Error_Handling_and_Recovery.py
index b45732ed5..f0cdf68be 100644
--- a/cookbooks/13-Error_Handling_and_Recovery.py
+++ b/cookbooks/13-Error_Handling_and_Recovery.py
@@ -9,6 +9,8 @@
# 6. Show how to log and report errors
# 7. Demonstrate graceful degradation when a step fails
+# UNDER CONSTRUCTION - NOT WORKING YET
+
import uuid
import yaml
import time
@@ -27,7 +29,7 @@
agent_id=AGENT_UUID,
name="Error Handler",
about="An AI agent specialized in demonstrating error handling and recovery mechanisms.",
- model="gpt-4-turbo",
+ model="gpt-4o",
)
# Defining a task with potential errors and recovery mechanisms
@@ -73,45 +75,45 @@
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"
+ case: "inputs[0].operation == '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"
+ case: "inputs[0].operation == '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"
+ case: "inputs[0].operation == '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
+ - role: system
content: >-
Summarize the result of the operation:
Operation: {{inputs[0].operation}}
- Result: {{_}}
+ Result: {{_}}]
+ unwrap: true
""")
# Creating the task
diff --git a/docs/README.md b/docs/README.md
index d57877707..5359f6c38 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -38,7 +38,7 @@
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:
-1. Check out our [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on how to contribute.
+1. Check out our [CONTRIBUTING.md](https://github.com/julep-ai/julep/blob/dev/CONTRIBUTING.md) file for guidelines on how to contribute.
2. Browse our [good first issues](https://github.com/julep-ai/julep/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to find a task that interests you.
3. If you have any questions or need help, don't hesitate to reach out on our [Discord](https://discord.com/invite/JTSBGRZrzj) channel.
@@ -69,6 +69,8 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓
📖 Table of Contents
+- [🌟 Call for Contributors!](#-call-for-contributors)
+ - [🎉 DevFest.AI October 2024](#-devfestai-october-2024)
- [Introduction](#introduction)
- [Quick Example](#quick-example)
- [Key Features](#key-features)
@@ -92,6 +94,11 @@ Exciting news! We're participating in DevFest.AI throughout October 2024! 🗓
- [Concepts](#concepts)
- [Understanding Tasks](#understanding-tasks)
- [Types of Workflow Steps](#types-of-workflow-steps)
+ - [Common Steps](#common-steps)
+ - [Key-Value Steps](#key-value-steps)
+ - [Iteration Steps](#iteration-steps)
+ - [Conditional Steps](#conditional-steps)
+ - [Other Control Flow](#other-control-flow)
- [Advanced Features](#advanced-features)
- [Adding Tools to Agents](#adding-tools-to-agents)
- [Managing Sessions and Users](#managing-sessions-and-users)