From f8bfd978a4ca7f0c8e57f88779d15401db61363f Mon Sep 17 00:00:00 2001 From: Junkyu Lee Date: Tue, 17 Feb 2026 07:59:26 -0500 Subject: [PATCH 1/7] llm connection stores available llms in cache, move open ai to the end so other models registered before Signed-off-by: Junkyu Lee --- src/agentics/core/agentics.py | 6 +- src/agentics/core/llm_connections.py | 84 ++++++++++++++++------------ 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/agentics/core/agentics.py b/src/agentics/core/agentics.py index b8d07f310..87b6bc9bc 100644 --- a/src/agentics/core/agentics.py +++ b/src/agentics/core/agentics.py @@ -57,7 +57,7 @@ StateOperator, StateReducer, ) -from agentics.core.llm_connections import available_llms, get_llm_provider +from agentics.core.llm_connections import get_cached_available_llms from agentics.core.utils import ( chunk_list, get_function_io_types, @@ -107,7 +107,8 @@ class AG(BaseModel, Generic[T]): "amap", description="Type of transduction to be used, amap, areduce", ) - llm: Any = Field(default_factory=get_llm_provider, exclude=True) + # llm: Any = Field(default_factory=get_llm_provider, exclude=True) + llm: Any = Field(default_factory=lambda: AG.get_llm_provider("first"), exclude=True) provide_explanations: bool = False explanations: Optional[list[Explanation]] = None @@ -218,6 +219,7 @@ class GeneratedAtype(BaseModel): def get_llm_provider( cls, provider_name: str = "first" ) -> Union[LLM, dict[str, LLM]]: + available_llms = get_cached_available_llms() if provider_name == "first": return ( next(iter(available_llms.values()), None) diff --git a/src/agentics/core/llm_connections.py b/src/agentics/core/llm_connections.py index dc973715b..0b413d178 100644 --- a/src/agentics/core/llm_connections.py +++ b/src/agentics/core/llm_connections.py @@ -10,6 +10,9 @@ # Track which environment variables are used for each LLM _llms_env_vars: dict[str, list[str]] = {} +# Cache for available LLMs (computed once at first use) +_available_llms_cache: dict[str, LLM | AsyncOpenAI] | None = None + def get_llm_provider(provider_name: str | None = None) -> LLM | AsyncOpenAI | None: """ @@ -50,6 +53,30 @@ def _check_env(*var_names: str) -> bool: return all(os.getenv(var) for var in var_names) +def get_cached_available_llms() -> dict[str, LLM | AsyncOpenAI]: + """ + Get cached LLMs or compute and cache them on first call. + + This avoids repeatedly scanning environment variables on every access. + Call refresh_llm_cache() if you need to reload the configuration. + """ + global _available_llms_cache + if _available_llms_cache is None: + _available_llms_cache = get_available_llms() + return _available_llms_cache + + +def refresh_llm_cache() -> dict[str, LLM | AsyncOpenAI]: + """ + Force refresh the LLM cache. + + Call this if environment variables change at runtime. + """ + global _available_llms_cache + _available_llms_cache = None + return get_cached_available_llms() + + def _get_llm_params(model: str) -> dict: """ Get provider-specific LLM parameters based on the model name. @@ -108,23 +135,6 @@ def get_available_llms() -> dict[str, LLM | AsyncOpenAI]: ) _llms_env_vars["ollama_llm"] = ["OLLAMA_MODEL_ID"] - # OpenAI LLM - if _check_env("OPENAI_API_KEY"): - openai_llm = LLM( - model=os.getenv("OPENAI_MODEL_ID", "openai/gpt-4"), - server_url=os.getenv("OPENAI_BASE_URL"), - temperature=0.8, - top_p=0.9, - stop=["END"], - api_key=os.getenv("OPENAI_API_KEY"), - seed=42, - ) - llms["openai_llm"] = openai_llm - llms["openai"] = openai_llm - env_vars = ["OPENAI_API_KEY", "OPENAI_MODEL_ID"] - _llms_env_vars["openai_llm"] = env_vars - _llms_env_vars["openai"] = env_vars - # OpenAI Compatible LLM if _check_env( "OPENAI_COMPATIBLE_API_KEY", @@ -149,22 +159,7 @@ def get_available_llms() -> dict[str, LLM | AsyncOpenAI]: _llms_env_vars["openai_compatible_llm"] = env_vars _llms_env_vars["openai_compatible"] = env_vars - # WatsonX LLM - if _check_env("WATSONX_APIKEY", "WATSONX_URL", "WATSONX_PROJECTID", "MODEL_ID"): - watsonx_llm = LLM( - model=os.getenv("MODEL_ID"), - base_url=os.getenv("WATSONX_URL"), - project_id=os.getenv("WATSONX_PROJECTID"), - api_key=os.getenv("WATSONX_APIKEY"), - temperature=0, - max_tokens=4000, - max_input_tokens=100000, - ) - llms["watsonx_llm"] = watsonx_llm - llms["watsonx"] = watsonx_llm - env_vars = ["WATSONX_APIKEY", "WATSONX_URL", "WATSONX_PROJECTID", "MODEL_ID"] - _llms_env_vars["watsonx_llm"] = env_vars - _llms_env_vars["watsonx"] = env_vars + # VLLM (AsyncOpenAI) if _check_env("VLLM_URL"): @@ -255,6 +250,23 @@ def get_available_llms() -> dict[str, LLM | AsyncOpenAI]: _llms_env_vars["litellm_proxy_llm"] = env_vars _llms_env_vars["litellm_proxy"] = env_vars + # OpenAI LLM + if _check_env("OPENAI_API_KEY"): + openai_llm = LLM( + model=os.getenv("OPENAI_MODEL_ID", "openai/gpt-4"), + base_url=os.getenv("OPENAI_BASE_URL"), + temperature=0.8, + top_p=0.9, + stop=["END"], + api_key=os.getenv("OPENAI_API_KEY"), + seed=42, + ) + llms["openai_llm"] = openai_llm + llms["openai"] = openai_llm + env_vars = ["OPENAI_API_KEY", "OPENAI_MODEL_ID"] + _llms_env_vars["openai_llm"] = env_vars + _llms_env_vars["openai"] = env_vars + return llms @@ -265,9 +277,11 @@ def __getattr__(name: str) -> dict[str, LLM | AsyncOpenAI] | LLM | AsyncOpenAI | Allows accessing 'available_llms' and individual LLM variables dynamically. """ if name == "available_llms": - return get_available_llms() + # return get_available_llms() + return get_cached_available_llms() - llms = get_available_llms() + # llms = get_available_llms() + llms = get_cached_available_llms() if name in llms: return llms[name] From 028742ecc0f4cde595c7cbfdda90966c55c6570a Mon Sep 17 00:00:00 2001 From: Junkyu Lee Date: Tue, 17 Feb 2026 08:04:09 -0500 Subject: [PATCH 2/7] unpack output type for estimateLogicalProximity Signed-off-by: Junkyu Lee --- src/agentics/core/transducible_functions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/agentics/core/transducible_functions.py b/src/agentics/core/transducible_functions.py index 42b02e879..885805b7b 100644 --- a/src/agentics/core/transducible_functions.py +++ b/src/agentics/core/transducible_functions.py @@ -587,6 +587,7 @@ async def __call__(self, state: Any) -> Any: ... async def estimateLogicalProximity(func, llm=AG.get_llm_provider()): sources = await generate_prototypical_instances(func.input_model, llm=llm) targets = await func(sources) + targets, explanations = _unpack_if_needed(targets) total_lp = 0 if len(targets) > 0: for target, source in zip(targets, sources): From 12c51290a9c7ae1a1de826e8aa5c64cc91dbe404 Mon Sep 17 00:00:00 2001 From: Junkyu Lee Date: Tue, 17 Feb 2026 08:15:01 -0500 Subject: [PATCH 3/7] unpack explanation before model dump Signed-off-by: Junkyu Lee --- tutorials/logical_transduction_algebra.ipynb | 25 ++++++++++---------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tutorials/logical_transduction_algebra.ipynb b/tutorials/logical_transduction_algebra.ipynb index 50022e5bd..43c190a14 100644 --- a/tutorials/logical_transduction_algebra.ipynb +++ b/tutorials/logical_transduction_algebra.ipynb @@ -28,6 +28,7 @@ "from typing import Optional\n", "from agentics.core.atype import *\n", "from agentics.core.transducible_functions import With\n", + "import pprint\n", "\n", "class GenericInput(BaseModel):\n", " content: Optional[str] = None\n", @@ -63,12 +64,13 @@ "metadata": {}, "outputs": [], "source": [ + "from agentics.core.transducible_functions import _unpack_if_needed\n", "input = GenericInput(content=\n", " \"\"\"Zoran Mamdani become the NYC mayor\"\"\")\n", "\n", "write_tweet = Email << GenericInput\n", - "tweet = await write_tweet(input)\n", - "print(tweet.model_dump_json(indent=2))\n" + "tweet, explanation = _unpack_if_needed(await write_tweet(input))\n", + "pprint.pp(tweet.model_dump_json(indent=2))\n" ] }, { @@ -112,10 +114,10 @@ "write_mail_to_alfio = Email<< With(\n", " GenericInput,\n", " instructions=\"Write an email to Alfio Gliozzo\",\n", - " prompyt_template=\"{content}\" )\n", + " prompt_template=\"{content}\" )\n", "news = GenericInput(content=\"Zoran Mandani won the Election in NYC\")\n", - "mail = await write_mail_to_alfio(news)\n", - "print(mail)" + "mail, explanations = _unpack_if_needed(await write_mail_to_alfio(news))\n", + "pprint.pp(mail)" ] }, { @@ -146,14 +148,13 @@ "source": [ "news = GenericInput(content=\"Zoran Mandani won the Election in NYC, make up a story about that.\")\n", "\n", - "\n", "summary_composite_1 = Summary << write_mail_to_alfio\n", "summary = await summary_composite_1(news)\n", - "print(summary.model_dump_json(indent=2))\n", + "pprint.pp(summary.model_dump_json(indent=2))\n", "\n", "summary_composite_2 = Summary <<(Email< Date: Tue, 17 Feb 2026 08:21:22 -0500 Subject: [PATCH 4/7] remove llm setting options for transducibile functions Signed-off-by: Junkyu Lee --- tutorials/semantic_operators.ipynb | 36 +++++++----------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/tutorials/semantic_operators.ipynb b/tutorials/semantic_operators.ipynb index 7a648dcfd..f828431b3 100644 --- a/tutorials/semantic_operators.ipynb +++ b/tutorials/semantic_operators.ipynb @@ -24,7 +24,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2", + "id": "3", "metadata": {}, "outputs": [], "source": [ @@ -36,18 +36,6 @@ "import pandas as pd\n", "from pydantic import BaseModel, Field\n", "\n", - "# Select a model \"watsonx\", \"gemini\", \"openai\", etc. \n", - "# Make sure to set up credentials for the model you choose in your environment variables.\n", - "my_llm = AG.get_llm_provider()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ "# Sample data\n", "df = pd.DataFrame({\n", " 'review': [\n", @@ -65,15 +53,13 @@ "result = await sem_map(\n", " source=df,\n", " target_type=Sentiment,\n", - " instructions=\"Analyze the sentiment of the review and provide a confidence score between 0 and 1.\",\n", - " llm=my_llm)\n", + " instructions=\"Analyze the sentiment of the review and provide a confidence score between 0 and 1.\")\n", "print(result)\n", "\n", "result = await sem_map(\n", " source=df,\n", " target_type=\"category\",\n", - " instructions=\"Classify the review into one of: positive, negative, neutral\",\n", - " llm=my_llm)\n", + " instructions=\"Classify the review into one of: positive, negative, neutral\")\n", "print(result)" ] }, @@ -108,7 +94,6 @@ "result = await sem_filter(\n", " source=df,\n", " predicate_template=\"The product is premium or high-end\",\n", - " llm=AG.get_llm_provider(\"litellm_proxy\"),\n", " verbose_agent=False,\n", " verbose_transduction=False\n", ")\n", @@ -118,8 +103,7 @@ "# Use field placeholders in the predicate\n", "result = await sem_filter(\n", " source=df,\n", - " predicate_template=\"The {product} described as '{description}' is suitable for gaming\",\n", - " llm=my_llm)\n", + " predicate_template=\"The {product} described as '{description}' is suitable for gaming\")\n", "\n", "print(result)" ] @@ -160,8 +144,7 @@ "result = await sem_agg(\n", " source=df,\n", " target_type=ReviewSummary,\n", - " instructions=\"Summarize all reviews, identify key themes, and provide an overall recommendation\",\n", - " llm=my_llm)\n", + " instructions=\"Summarize all reviews, identify key themes, and provide an overall recommendation\")\n", "\n", "pprint(result)" ] @@ -182,8 +165,7 @@ "result = await sem_agg(\n", " source=df,\n", " target_type=Statistics,\n", - " instructions=\"Count total reviews, positive reviews, negative reviews, and determine average sentiment\",\n", - " llm=my_llm)\n", + " instructions=\"Count total reviews, positive reviews, negative reviews, and determine average sentiment\")\n", "pprint(result)" ] }, @@ -225,14 +207,12 @@ "mapped = await sem_map(\n", " source=filtered,\n", " target_type=\"price_category\",\n", - " instructions=\"Classify the price of the product into one of: high, medium, low\", \n", - " llm=my_llm)\n", + " instructions=\"Classify the price of the product into one of: high, medium, low\")\n", "pprint(mapped)\n", "result = await sem_agg(\n", " source=mapped,\n", " target_type=\"summary\",\n", - " instructions=\"Summarize all descriptions\",\n", - " llm=my_llm)\n", + " instructions=\"Summarize all descriptions\")\n", "pprint(result)" ] } From d305789c15371cc3b2f60cc42446f70737b39315 Mon Sep 17 00:00:00 2001 From: Junkyu Lee Date: Tue, 17 Feb 2026 08:26:39 -0500 Subject: [PATCH 5/7] clean up tutorial notebook Signed-off-by: Junkyu Lee --- tutorials/transducible_functions.ipynb | 107 +++++++++++++++++++------ 1 file changed, 81 insertions(+), 26 deletions(-) diff --git a/tutorials/transducible_functions.ipynb b/tutorials/transducible_functions.ipynb index f417d22ea..46783b785 100644 --- a/tutorials/transducible_functions.ipynb +++ b/tutorials/transducible_functions.ipynb @@ -42,21 +42,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "3", "metadata": {}, "outputs": [], "source": [ "from typing import Optional\n", - "from agentics import AG\n", "from pydantic import BaseModel, Field\n", "from agentics.core.transducible_functions import transducible, Transduce\n", - "from dotenv import load_dotenv\n", - "\n", - "# Load .env from project root (current working directory)\n", - "load_dotenv()\n", - "\n", - "llm=AG.get_llm_provider()\n", "\n", "class GenericInput(BaseModel):\n", " content: Optional[str] = None\n", @@ -85,12 +78,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "5", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "Write an email about the provided content. Elaborate on that and make up content as needed\n", + "\n", + "{\n", + " \"to\": \"Lisa\",\n", + " \"subject\": \"Exciting Progress Update: Agentics 2.0 New Release\",\n", + " \"body\": \"Hi Lisa,\\n\\nI hope you're having a great week. I wanted to reach out and share some exciting news regarding our recent development cycle. I've made great progress with the new release of Agentics 2.0.\\n\\nThe core functionalities are now stable, and the performance improvements we discussed are exceeding our initial benchmarks. I’m currently finalizing the documentation and polishing the user interface to ensure a seamless transition for our users. \\n\\nI’d love to walk you through a demo of the new features once I have the final build ready later this week. Let me know when you might have a few minutes to catch up.\\n\\nBest regards,\\n\\n[Your Name]\"\n", + "}\n" + ] + } + ], "source": [ - "@transducible(provide_explanation=False, llm=llm)\n", + "@transducible(provide_explanation=False)\n", "async def write_an_email(state: GenericInput) -> Email:\n", " \"\"\"Write an email about the provided content. Elaborate on that and make up content as needed\"\"\"\n", " return Transduce(state)\n", @@ -128,14 +137,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"to\": \"Lisa\",\n", + " \"subject\": \"\",\n", + " \"body\": \"I have made great progress with agentics\"\n", + "}\n", + "{\n", + " \"to\": \"Lisa\",\n", + " \"subject\": \"Update on Agentics Progress\",\n", + " \"body\": \"Hi Lisa,\\n\\nI am writing to share some exciting news regarding my recent work. I have made significant progress with agentics and have successfully reached several key milestones in the development process. The systems are becoming increasingly autonomous and efficient, exceeding the initial performance benchmarks.\\n\\nI wanted to ensure you were kept in the loop on these advancements. Please let me know if you would like to schedule a brief meeting to review the latest updates in more detail.\\n\\nBest regards,\"\n", + "}\n", + "explanation=\"The transduction is partially supported but contains significant hallucinated content. The 'to' field ('Lisa') is directly derived from the source instruction 'send it to Lisa'. The 'subject' and 'body' fields are logically linked to the source phrase 'made great progress with agentics', but the specific details (milestones, autonomy, efficiency benchmarks, and the request for a meeting) are not present in the source and were generated as filler. While the intent is correct, the specific content of the body is largely unsupported by the source text.\" relevant_source_attributes={'to': ['content'], 'subject': ['content'], 'body': ['content']} confidence=0.4\n" + ] + } + ], "source": [ "import re\n", "\n", - "@transducible(provide_explanation=False, llm=llm)\n", + "@transducible(provide_explanation=True)\n", "async def write_an_email_code_only(state: GenericInput) -> Email: \n", " match = re.match(r\"^(Hi|Dear|Hello|Hey)\\s+([^,]+),\\s*(.+)$\", state.content)\n", " if match:\n", @@ -143,7 +170,7 @@ " return Email(body= body, to=name, subject=\"\")\n", " else: return Email()\n", "\n", - "@transducible(provide_explanation=False, llm=llm)\n", + "@transducible(provide_explanation=True)\n", "async def write_an_email_to_lisa(state: GenericInput) -> Email:\n", " \"\"\"Write an email about the provided content. Elaborate on that and make up content as needed\"\"\"\n", " # example code to modify states before transduction\n", @@ -171,7 +198,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "9", "metadata": {}, "outputs": [], @@ -207,17 +234,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "11", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"report_summary\": \"In 1998, the Mayor of New York City was Rudolph W. Giuliani, who held the office from 1994 to 2001. In 2025, the Mayor of New York City was Eric L. Adams, who served from January 1, 2022, through 2025. Following the mayoral election on November 4, 2025, Zohran Mamdani was elected as the next mayor of the city.\",\n", + " \"relevant_sources\": [\n", + " \"https://www.nyc.gov/site/dcas/about/green-book-mayors-of-the-city-of-new-york.page\",\n", + " \"https://en.wikipedia.org/wiki/List_of_mayors_of_New_York_City\",\n", + " \"https://abcnews.com/Politics/new-york-city-2025-mayoral-election-results-mamdani/story?id=126345335\",\n", + " \"https://www.dw.com/en/new-york-city-mayoral-election/a-74591495\"\n", + " ]\n", + "}\n", + "None\n" + ] + } + ], "source": [ "class WebSearchResult(BaseModel):\n", " report_summary:Optional[str]=None\n", " relevant_sources:Optional[list[str]]=None\n", "\n", "\n", - "@transducible(tools=[web_search], llm=llm, reasoning=True, max_iter=20, provide_explanation=False)\n", + "@transducible(tools=[web_search], reasoning=True, max_iter=20, provide_explanation=False)\n", "async def answer_question_after_lookup(query: GenericInput) -> WebSearchResult:\n", " \"perform an extensive web search to provide an answer to the input question with supporting evidence. Use your tool to look it up\" \n", " return Transduce(query)\n", @@ -247,27 +291,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "13", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"genre\": \"Crime Drama\"\n", + "}\n" + ] + } + ], "source": [ "from agentics.core.transducible_functions import Transduce, transducible\n", "\n", "\n", - "@transducible(provide_explanation=False, llm=llm, prompt_template=\"{movie_name}: {description}\")\n", + "@transducible(provide_explanation=False, prompt_template=\"{movie_name}: {description}\")\n", "async def classify_genre(state:Movie)-> Genre:\n", " \"\"\"Classify the genre of the source Movie \"\"\"\n", " return Transduce(state)\n", "\n", - "genre = await classify_genre(Movie(\n", + "from agentics.core.transducible_functions import _unpack_if_needed\n", + "\n", + "genre, explanation = _unpack_if_needed(await classify_genre(Movie(\n", " movie_name=\"The Godfather\",\n", " description=\"The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.\",\n", " year=1972\n", - "))\n", - "\n", + ")))\n", "print(genre.model_dump_json(indent=2))\n", - "print(explanation.model_dump_json(indent=2))\n" + "\n" ] } ], From 19d8c3e9474a16274b8d18797efd68b267df4a15 Mon Sep 17 00:00:00 2001 From: Junkyu Lee Date: Tue, 17 Feb 2026 08:31:23 -0500 Subject: [PATCH 6/7] clean up map_reduce notebook Signed-off-by: Junkyu Lee --- tutorials/map_reduce.ipynb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tutorials/map_reduce.ipynb b/tutorials/map_reduce.ipynb index 8fea9b224..05808fece 100644 --- a/tutorials/map_reduce.ipynb +++ b/tutorials/map_reduce.ipynb @@ -29,12 +29,8 @@ "from typing import Optional\n", "from agentics import AG\n", "from pydantic import BaseModel, Field\n", - "from dotenv import load_dotenv\n", + "from agentics.core.transducible_functions import _unpack_if_needed\n", "\n", - "# Load .env from project root (current working directory)\n", - "load_dotenv()\n", - "\n", - "llm=AG.get_llm_provider(\"litellm_proxy\")\n", "\n", "class Number(BaseModel):\n", " number:Optional[int] = Field(None, description=\"An integer number\")\n", @@ -147,7 +143,9 @@ "to_number = Number << RomanNumber\n", "reduce = Number << With(Number, \n", " areduce=True,\n", - " instructions=\"return the sum of the input numbers' number fields\")\n", + " instructions=\"return the sum of the input numbers' number fields\",\n", + " provide_explanation=False)\n", + "\n", "\n", "await reduce(await to_number(roman_numbers ))" ] From 570cda8a9b3cdb6c5abbb1cbbe93516f2c5b2383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nahuel=20Defoss=C3=A9?= Date: Tue, 17 Feb 2026 16:56:13 +0300 Subject: [PATCH 7/7] pre-commit fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nahuel Defossé --- src/agentics/core/llm_connections.py | 8 +-- tutorials/semantic_operators.ipynb | 16 ++--- tutorials/transducible_functions.ipynb | 81 ++++---------------------- 3 files changed, 21 insertions(+), 84 deletions(-) diff --git a/src/agentics/core/llm_connections.py b/src/agentics/core/llm_connections.py index 0b413d178..00b1d5152 100644 --- a/src/agentics/core/llm_connections.py +++ b/src/agentics/core/llm_connections.py @@ -56,7 +56,7 @@ def _check_env(*var_names: str) -> bool: def get_cached_available_llms() -> dict[str, LLM | AsyncOpenAI]: """ Get cached LLMs or compute and cache them on first call. - + This avoids repeatedly scanning environment variables on every access. Call refresh_llm_cache() if you need to reload the configuration. """ @@ -69,7 +69,7 @@ def get_cached_available_llms() -> dict[str, LLM | AsyncOpenAI]: def refresh_llm_cache() -> dict[str, LLM | AsyncOpenAI]: """ Force refresh the LLM cache. - + Call this if environment variables change at runtime. """ global _available_llms_cache @@ -159,8 +159,6 @@ def get_available_llms() -> dict[str, LLM | AsyncOpenAI]: _llms_env_vars["openai_compatible_llm"] = env_vars _llms_env_vars["openai_compatible"] = env_vars - - # VLLM (AsyncOpenAI) if _check_env("VLLM_URL"): llms["vllm_llm"] = AsyncOpenAI( @@ -278,7 +276,7 @@ def __getattr__(name: str) -> dict[str, LLM | AsyncOpenAI] | LLM | AsyncOpenAI | """ if name == "available_llms": # return get_available_llms() - return get_cached_available_llms() + return get_cached_available_llms() # llms = get_available_llms() llms = get_cached_available_llms() diff --git a/tutorials/semantic_operators.ipynb b/tutorials/semantic_operators.ipynb index f828431b3..f77ae6426 100644 --- a/tutorials/semantic_operators.ipynb +++ b/tutorials/semantic_operators.ipynb @@ -24,7 +24,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3", + "id": "2", "metadata": {}, "outputs": [], "source": [ @@ -65,7 +65,7 @@ }, { "cell_type": "markdown", - "id": "4", + "id": "3", "metadata": {}, "source": [ "### Semantic Filter\n", @@ -76,7 +76,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "4", "metadata": {}, "outputs": [], "source": [ @@ -110,7 +110,7 @@ }, { "cell_type": "markdown", - "id": "6", + "id": "5", "metadata": {}, "source": [ "### Semantic Aggregator\n", @@ -121,7 +121,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7", + "id": "6", "metadata": {}, "outputs": [], "source": [ @@ -152,7 +152,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8", + "id": "7", "metadata": {}, "outputs": [], "source": [ @@ -171,7 +171,7 @@ }, { "cell_type": "markdown", - "id": "9", + "id": "8", "metadata": {}, "source": [ "### Integration with Agentics Workflows\n", @@ -182,7 +182,7 @@ { "cell_type": "code", "execution_count": null, - "id": "10", + "id": "9", "metadata": {}, "outputs": [], "source": [ diff --git a/tutorials/transducible_functions.ipynb b/tutorials/transducible_functions.ipynb index 46783b785..263cbc5d1 100644 --- a/tutorials/transducible_functions.ipynb +++ b/tutorials/transducible_functions.ipynb @@ -42,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "3", "metadata": {}, "outputs": [], @@ -78,26 +78,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "5", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "Write an email about the provided content. Elaborate on that and make up content as needed\n", - "\n", - "{\n", - " \"to\": \"Lisa\",\n", - " \"subject\": \"Exciting Progress Update: Agentics 2.0 New Release\",\n", - " \"body\": \"Hi Lisa,\\n\\nI hope you're having a great week. I wanted to reach out and share some exciting news regarding our recent development cycle. I've made great progress with the new release of Agentics 2.0.\\n\\nThe core functionalities are now stable, and the performance improvements we discussed are exceeding our initial benchmarks. I’m currently finalizing the documentation and polishing the user interface to ensure a seamless transition for our users. \\n\\nI’d love to walk you through a demo of the new features once I have the final build ready later this week. Let me know when you might have a few minutes to catch up.\\n\\nBest regards,\\n\\n[Your Name]\"\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "@transducible(provide_explanation=False)\n", "async def write_an_email(state: GenericInput) -> Email:\n", @@ -137,28 +121,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "7", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"to\": \"Lisa\",\n", - " \"subject\": \"\",\n", - " \"body\": \"I have made great progress with agentics\"\n", - "}\n", - "{\n", - " \"to\": \"Lisa\",\n", - " \"subject\": \"Update on Agentics Progress\",\n", - " \"body\": \"Hi Lisa,\\n\\nI am writing to share some exciting news regarding my recent work. I have made significant progress with agentics and have successfully reached several key milestones in the development process. The systems are becoming increasingly autonomous and efficient, exceeding the initial performance benchmarks.\\n\\nI wanted to ensure you were kept in the loop on these advancements. Please let me know if you would like to schedule a brief meeting to review the latest updates in more detail.\\n\\nBest regards,\"\n", - "}\n", - "explanation=\"The transduction is partially supported but contains significant hallucinated content. The 'to' field ('Lisa') is directly derived from the source instruction 'send it to Lisa'. The 'subject' and 'body' fields are logically linked to the source phrase 'made great progress with agentics', but the specific details (milestones, autonomy, efficiency benchmarks, and the request for a meeting) are not present in the source and were generated as filler. While the intent is correct, the specific content of the body is largely unsupported by the source text.\" relevant_source_attributes={'to': ['content'], 'subject': ['content'], 'body': ['content']} confidence=0.4\n" - ] - } - ], + "outputs": [], "source": [ "import re\n", "\n", @@ -198,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "9", "metadata": {}, "outputs": [], @@ -234,27 +200,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "11", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"report_summary\": \"In 1998, the Mayor of New York City was Rudolph W. Giuliani, who held the office from 1994 to 2001. In 2025, the Mayor of New York City was Eric L. Adams, who served from January 1, 2022, through 2025. Following the mayoral election on November 4, 2025, Zohran Mamdani was elected as the next mayor of the city.\",\n", - " \"relevant_sources\": [\n", - " \"https://www.nyc.gov/site/dcas/about/green-book-mayors-of-the-city-of-new-york.page\",\n", - " \"https://en.wikipedia.org/wiki/List_of_mayors_of_New_York_City\",\n", - " \"https://abcnews.com/Politics/new-york-city-2025-mayoral-election-results-mamdani/story?id=126345335\",\n", - " \"https://www.dw.com/en/new-york-city-mayoral-election/a-74591495\"\n", - " ]\n", - "}\n", - "None\n" - ] - } - ], + "outputs": [], "source": [ "class WebSearchResult(BaseModel):\n", " report_summary:Optional[str]=None\n", @@ -291,20 +240,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "13", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"genre\": \"Crime Drama\"\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "from agentics.core.transducible_functions import Transduce, transducible\n", "\n",