From 35340272c44966a37acaebc0e9806214bafda048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20G=C3=BCnd=C3=BCz?= Date: Tue, 9 Sep 2025 18:50:50 +0300 Subject: [PATCH 1/5] Test (#663) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Dev to Test (#654) * Merge to prod (#530) * Merge to test (#246) * Update Finetuner search metadata functional tests (#172) * Downgrade dataclasses-json for compatibility (#170) Co-authored-by: Thiago Castro Ferreira * Fix model cost parameters (#179) Co-authored-by: Thiago Castro Ferreira * Treat label URLs (#176) Co-authored-by: Thiago Castro Ferreira * Add new metric test (#181) * Add new metric test * Enable testing new pipeline executor --------- Co-authored-by: Thiago Castro Ferreira * LLMModel class and parameters (#184) * LLMModel class and parameters * Change in the documentation * Changing LLMModel for LLM * Remove frequency penalty --------- Co-authored-by: Thiago Castro Ferreira * Gpus (#185) * Release. (#141) * Merge dev to test (#107) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Development to Test (#109) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> * Merge to test (#111) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#118) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge to test (#124) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#126) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#129) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge to test (#135) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) * Enabling dataset ID and model ID as parameters for finetuner creation (#131) Co-authored-by: Thiago Castro Ferreira * Fix supplier representation of a model (#132) * Fix supplier representation of a model * Fixing parameter typing --------- Co-authored-by: Thiago Castro Ferreira * Fixing indentation in documentation sample code (#134) Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#137) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) * Enabling dataset ID and model ID as parameters for finetuner creation (#131) Co-authored-by: Thiago Castro Ferreira * Fix supplier representation of a model (#132) * Fix supplier representation of a model * Fixing parameter typing --------- Co-authored-by: Thiago Castro Ferreira * Fixing indentation in documentation sample code (#134) Co-authored-by: Thiago Castro Ferreira * Update FineTune unit and functional tests (#136) --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira * Merge to prod. (#152) * Merge dev to test (#107) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Development to Test (#109) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> * Merge to test (#111) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#118) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge to test (#124) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored… * Dev to test (#656) * Merge to prod (#530) * Merge to test (#246) * Update Finetuner search metadata functional tests (#172) * Downgrade dataclasses-json for compatibility (#170) Co-authored-by: Thiago Castro Ferreira * Fix model cost parameters (#179) Co-authored-by: Thiago Castro Ferreira * Treat label URLs (#176) Co-authored-by: Thiago Castro Ferreira * Add new metric test (#181) * Add new metric test * Enable testing new pipeline executor --------- Co-authored-by: Thiago Castro Ferreira * LLMModel class and parameters (#184) * LLMModel class and parameters * Change in the documentation * Changing LLMModel for LLM * Remove frequency penalty --------- Co-authored-by: Thiago Castro Ferreira * Gpus (#185) * Release. (#141) * Merge dev to test (#107) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Development to Test (#109) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> * Merge to test (#111) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#118) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge to test (#124) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#126) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#129) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge to test (#135) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) * Enabling dataset ID and model ID as parameters for finetuner creation (#131) Co-authored-by: Thiago Castro Ferreira * Fix supplier representation of a model (#132) * Fix supplier representation of a model * Fixing parameter typing --------- Co-authored-by: Thiago Castro Ferreira * Fixing indentation in documentation sample code (#134) Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#137) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) * Enabling dataset ID and model ID as parameters for finetuner creation (#131) Co-authored-by: Thiago Castro Ferreira * Fix supplier representation of a model (#132) * Fix supplier representation of a model * Fixing parameter typing --------- Co-authored-by: Thiago Castro Ferreira * Fixing indentation in documentation sample code (#134) Co-authored-by: Thiago Castro Ferreira * Update FineTune unit and functional tests (#136) --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira * Merge to prod. (#152) * Merge dev to test (#107) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Development to Test (#109) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> * Merge to test (#111) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#118) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge to test (#124) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored… * Dev to test (#660) * Merge to prod (#530) * Merge to test (#246) * Update Finetuner search metadata functional tests (#172) * Downgrade dataclasses-json for compatibility (#170) Co-authored-by: Thiago Castro Ferreira * Fix model cost parameters (#179) Co-authored-by: Thiago Castro Ferreira * Treat label URLs (#176) Co-authored-by: Thiago Castro Ferreira * Add new metric test (#181) * Add new metric test * Enable testing new pipeline executor --------- Co-authored-by: Thiago Castro Ferreira * LLMModel class and parameters (#184) * LLMModel class and parameters * Change in the documentation * Changing LLMModel for LLM * Remove frequency penalty --------- Co-authored-by: Thiago Castro Ferreira * Gpus (#185) * Release. (#141) * Merge dev to test (#107) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Development to Test (#109) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> * Merge to test (#111) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#118) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge to test (#124) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#126) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#129) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira * Merge to test (#135) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) * Enabling dataset ID and model ID as parameters for finetuner creation (#131) Co-authored-by: Thiago Castro Ferreira * Fix supplier representation of a model (#132) * Fix supplier representation of a model * Fixing parameter typing --------- Co-authored-by: Thiago Castro Ferreira * Fixing indentation in documentation sample code (#134) Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira * Merge dev to test (#137) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Do not download textual URLs (#120) * Do not download textual URLs * Treat as string --------- Co-authored-by: Thiago Castro Ferreira * Enable api key parameter in data asset creation (#122) Co-authored-by: Thiago Castro Ferreira * Update Finetuner hyperparameters (#125) * Update Finetuner hyperparameters * Change hyperparameters error message * Add new LLMs finetuner models (mistral and solar) (#128) * Enabling dataset ID and model ID as parameters for finetuner creation (#131) Co-authored-by: Thiago Castro Ferreira * Fix supplier representation of a model (#132) * Fix supplier representation of a model * Fixing parameter typing --------- Co-authored-by: Thiago Castro Ferreira * Fixing indentation in documentation sample code (#134) Co-authored-by: Thiago Castro Ferreira * Update FineTune unit and functional tests (#136) --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira * Merge to prod. (#152) * Merge dev to test (#107) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Development to Test (#109) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> * Merge to test (#111) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) --------- Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#118) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Merge to test (#124) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) * Hf deployment test (#115) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Hf deployment test (#117) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain * Merge dev to test (#113) * Create bounds for FineTune hyperparameters (#103) * Test bound to hyperparameters * Update finetune llm hyperparameters * Remove option to use PEFT, always on use now * Fixing pipeline general asset test (#106) * Update Finetuner functional tests (#112) --------- Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> * Hf deployment test (#114) * Started adding Hugging Face deployment to aiXplain SDK Signed-off-by: mikelam-us-aixplain * Added model status function to SDK Signed-off-by: mikelam-us-aixplain * Updating Signed-off-by: mikelam-us-aixplain * Updated CLI Signed-off-by: mikelam-us * Adding CLI Signed-off-by: mikelam-us-aixplain * Corrected request error Signed-off-by: mikelam-us-aixplain * Clearing out unnecessary information in return Signed-off-by: mikelam-us-aixplain * Adding status Signed-off-by: mikelam-us-aixplain * Simplifying status Signed-off-by: mikelam-us-aixplain * Adding tests and correcting tokens Signed-off-by: mikelam-us-aixplain * Added bad repo ID test Signed-off-by: mikelam-us-aixplain * Finished rough draft of tests Signed-off-by: mikelam-us-aixplain * Adding tests Signed-off-by: mikelam-us-aixplain * Fixing hf token Signed-off-by: mikelam-us-aixplain * Adding hf token Signed-off-by: mikelam-us-aixplain * Correcting first test Signed-off-by: mikelam-us-aixplain * Testing Signed-off-by: mikelam-us-aixplain * Adding config Signed-off-by: mikelam-us-aixplain * Added user doc Signed-off-by: mikelam-us-aixplain * Added gated model test Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us * Adding HF token Signed-off-by: mikelam-us-aixplain --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored… * fix(tests): delete groq model * safe delet in agent tests added * fix evolver tests * hotfix: inspector tests --------- Signed-off-by: mikelam-us-aixplain Signed-off-by: mikelam-us Signed-off-by: Michael Lam Signed-off-by: root Signed-off-by: dependabot[bot] Co-authored-by: ikxplain <88332269+ikxplain@users.noreply.github.com> Co-authored-by: Lucas Pavanelli <86805709+lucas-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira <85182544+thiago-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira Co-authored-by: mikelam-us-aixplain <131073216+mikelam-us-aixplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Shreyas Sharma <85180538+shreyasXplain@users.noreply.github.com> Co-authored-by: Thiago Castro Ferreira Co-authored-by: Thiago Castro Ferreira Co-authored-by: Lucas Pavanelli Co-authored-by: kadirpekel Co-authored-by: kadir pekel Co-authored-by: root Co-authored-by: Zaina Abu Shaban Co-authored-by: xainaz Co-authored-by: xainaz Co-authored-by: Lucas Pavanelli Co-authored-by: OsujiCC Co-authored-by: Hadi Nasrallah <87204330+hadi-aix@users.noreply.github.com> Co-authored-by: Yunsu Kim Co-authored-by: Yunsu Kim Co-authored-by: Muhammad-Elmallah <145364766+Muhammad-Elmallah@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Abdul Basit Anees <50206820+basitanees@users.noreply.github.com> Co-authored-by: ikxplain Co-authored-by: Zaina Co-authored-by: Hadi Co-authored-by: Abdelrahman El-Sheikh <139810675+elsheikhams99@users.noreply.github.com> --- .github/workflows/main.yaml | 2 +- .pre-commit-config.yaml | 18 +- aixplain/enums/__init__.py | 1 + aixplain/enums/evolve_type.py | 6 + aixplain/factories/agent_factory/__init__.py | 51 +- aixplain/factories/model_factory/utils.py | 8 +- .../team_agent_factory/inspector_factory.py | 26 +- .../factories/team_agent_factory/utils.py | 201 +++++- aixplain/modules/agent/__init__.py | 168 ++++- aixplain/modules/agent/agent_response.py | 7 +- aixplain/modules/agent/agent_response_data.py | 3 + aixplain/modules/agent/agent_task.py | 47 +- aixplain/modules/agent/evolve_param.py | 269 ++++++++ aixplain/modules/model/index_model.py | 76 ++- aixplain/modules/model/utils.py | 4 +- aixplain/modules/team_agent/__init__.py | 234 ++++++- .../team_agent/evolver_response_data.py | 70 ++ aixplain/modules/team_agent/inspector.py | 274 +++++++- aixplain/utils/evolve_utils.py | 29 + pyproject.toml | 8 +- .../functional/agent/agent_functional_test.py | 16 +- .../agent/data/agent_test_end2end.json | 4 +- .../model/data/test_file_parser_input.pdf | Bin 0 -> 16202 bytes tests/functional/model/run_model_test.py | 100 ++- .../data/team_agent_test_end2end.json | 12 +- tests/functional/team_agent/evolver_test.py | 141 ++++ .../team_agent/inspector_functional_test.py | 633 ++++++++++++++++-- .../team_agent/team_agent_functional_test.py | 33 +- tests/test_deletion_utils.py | 126 ++++ tests/unit/agent/agent_factory_utils_test.py | 76 ++- tests/unit/agent/agent_test.py | 4 +- tests/unit/agent/evolve_param_test.py | 187 ++++++ tests/unit/agent/test_agent_evolve.py | 214 ++++++ tests/unit/agent/test_evolver_llm_utils.py | 129 ++++ tests/unit/index_model_test.py | 57 ++ tests/unit/team_agent/inspector_test.py | 580 +++++++++++++--- 36 files changed, 3495 insertions(+), 319 deletions(-) create mode 100644 aixplain/enums/evolve_type.py create mode 100644 aixplain/modules/agent/evolve_param.py create mode 100644 aixplain/modules/team_agent/evolver_response_data.py create mode 100644 aixplain/utils/evolve_utils.py create mode 100644 tests/functional/model/data/test_file_parser_input.pdf create mode 100644 tests/functional/team_agent/evolver_test.py create mode 100644 tests/test_deletion_utils.py create mode 100644 tests/unit/agent/evolve_param_test.py create mode 100644 tests/unit/agent/test_agent_evolve.py create mode 100644 tests/unit/agent/test_evolver_llm_utils.py diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index eddfff31..9286cae1 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -89,7 +89,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.9" cache: 'pip' - name: Install dependencies diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2500c2c8..4ad3e5bc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,18 +8,26 @@ repos: pass_filenames: false types: [python] always_run: true - + - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 25.1.0 hooks: - id: black language_version: python3 args: # arguments to configure black - --line-length=128 - + - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.0.0 # Use the latest version + rev: v5.0.0 # Use the latest version + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-merge-conflict + - id: check-added-large-files + + - repo: https://github.com/pycqa/flake8 + rev: 7.2.0 hooks: - id: flake8 args: # arguments to configure flake8 - - --ignore=E402,E501,E203,W503 \ No newline at end of file + - --ignore=E402,E501,E203,W503 diff --git a/aixplain/enums/__init__.py b/aixplain/enums/__init__.py index 17308467..5c3a71f5 100644 --- a/aixplain/enums/__init__.py +++ b/aixplain/enums/__init__.py @@ -20,4 +20,5 @@ from .asset_status import AssetStatus from .index_stores import IndexStores from .function_type import FunctionType +from .evolve_type import EvolveType from .code_interpreter import CodeInterpreterModel diff --git a/aixplain/enums/evolve_type.py b/aixplain/enums/evolve_type.py new file mode 100644 index 00000000..555fdb53 --- /dev/null +++ b/aixplain/enums/evolve_type.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class EvolveType(str, Enum): + TEAM_TUNING = "team_tuning" + INSTRUCTION_TUNING = "instruction_tuning" diff --git a/aixplain/factories/agent_factory/__init__.py b/aixplain/factories/agent_factory/__init__.py index 95037f65..0caf0814 100644 --- a/aixplain/factories/agent_factory/__init__.py +++ b/aixplain/factories/agent_factory/__init__.py @@ -28,7 +28,7 @@ from aixplain.enums.function import Function from aixplain.enums.supplier import Supplier -from aixplain.modules.agent import Agent, AgentTask, Tool +from aixplain.modules.agent import Agent, Tool, WorkflowTask from aixplain.modules.agent.output_format import OutputFormat from aixplain.modules.agent.tool.model_tool import ModelTool from aixplain.modules.agent.tool.pipeline_tool import PipelineTool @@ -67,7 +67,8 @@ def create( api_key: Text = config.TEAM_API_KEY, supplier: Union[Dict, Text, Supplier, int] = "aiXplain", version: Optional[Text] = None, - tasks: List[AgentTask] = [], + tasks: List[WorkflowTask] = None, + workflow_tasks: List[WorkflowTask] = [], output_format: Optional[OutputFormat] = None, expected_output: Optional[Union[BaseModel, Text, dict]] = None, ) -> Agent: @@ -80,7 +81,7 @@ def create( Args: name (Text): name of the agent - description (Text): description of the agent role. + description (Text): description of the agent instructions. instructions (Text): instructions of the agent. llm (Optional[Union[LLM, Text]], optional): LLM instance to use as an object or as an ID. llm_id (Optional[Text], optional): ID of LLM to use if no LLM instance provided. Defaults to None. @@ -88,7 +89,7 @@ def create( api_key (Text, optional): team/user API key. Defaults to config.TEAM_API_KEY. supplier (Union[Dict, Text, Supplier, int], optional): owner of the agent. Defaults to "aiXplain". version (Optional[Text], optional): version of the agent. Defaults to None. - tasks (List[AgentTask], optional): list of tasks for the agent. Defaults to []. + workflow_tasks (List[WorkflowTask], optional): list of tasks for the agent. Defaults to []. output_format (OutputFormat, optional): default output format for agent responses. Defaults to OutputFormat.TEXT. expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None. Returns: @@ -127,6 +128,16 @@ def create( elif isinstance(supplier, Supplier): supplier = supplier.value["code"] + if tasks is not None: + warnings.warn( + "The 'tasks' parameter is deprecated and will be removed in a future version. " "Use 'workflow_tasks' instead.", + DeprecationWarning, + stacklevel=2, + ) + workflow_tasks = tasks if workflow_tasks is None or workflow_tasks == [] else workflow_tasks + + workflow_tasks = workflow_tasks or [] + payload = { "name": name, "assets": [build_tool_payload(tool) for tool in tools], @@ -136,7 +147,7 @@ def create( "version": version, "llmId": llm_id, "status": "draft", - "tasks": [task.to_dict() for task in tasks], + "tasks": [task.to_dict() for task in workflow_tasks], "tools": [], } @@ -206,32 +217,30 @@ def create_from_dict(cls, dict: Dict) -> Agent: return agent @classmethod - def create_task( + def create_workflow_task( cls, name: Text, description: Text, expected_output: Text, - dependencies: Optional[List[Text]] = None, - ) -> AgentTask: - """Create a new task for an agent. - - Args: - name (Text): Name of the task. - description (Text): Description of what the task should accomplish. - expected_output (Text): Description of the expected output format. - dependencies (Optional[List[Text]], optional): List of task names that must - complete before this task can start. Defaults to None. - - Returns: - AgentTask: Created task object. - """ - return AgentTask( + dependencies: Optional[List[Text]] = [], + ) -> WorkflowTask: + return WorkflowTask( name=name, description=description, expected_output=expected_output, dependencies=dependencies, ) + @classmethod + def create_task(cls, *args, **kwargs): + warnings.warn( + "The 'create_task' method is deprecated and will be removed in a future version. " + "Use 'create_workflow_task' instead.", + DeprecationWarning, + stacklevel=2, + ) + return cls.create_workflow_task(*args, **kwargs) + @classmethod def create_model_tool( cls, diff --git a/aixplain/factories/model_factory/utils.py b/aixplain/factories/model_factory/utils.py index 212d9ae2..a831a7c7 100644 --- a/aixplain/factories/model_factory/utils.py +++ b/aixplain/factories/model_factory/utils.py @@ -58,10 +58,14 @@ def create_model_from_response(response: Dict) -> Model: additional_kwargs = {} attributes = response.get("attributes", None) if attributes: - embedding_model = next((item["code"] for item in attributes if item["name"] == "embeddingmodel"), None) + embedding_model = next( + (item.get("code") for item in attributes if item.get("name") == "embeddingmodel" and "code" in item), None + ) if embedding_model: additional_kwargs["embedding_model"] = embedding_model - embedding_size = next((item["value"] for item in attributes if item["name"] == "embeddingSize"), None) + embedding_size = next( + (item.get("value") for item in attributes if item.get("name") == "embeddingSize" and "value" in item), None + ) if embedding_size: additional_kwargs["embedding_size"] = embedding_size diff --git a/aixplain/factories/team_agent_factory/inspector_factory.py b/aixplain/factories/team_agent_factory/inspector_factory.py index e7d88324..ce6c4927 100644 --- a/aixplain/factories/team_agent_factory/inspector_factory.py +++ b/aixplain/factories/team_agent_factory/inspector_factory.py @@ -21,7 +21,7 @@ """ import logging -from typing import Dict, Optional, Text, Union +from typing import Dict, Optional, Text, Union, Callable from urllib.parse import urljoin from aixplain.enums.asset_status import AssetStatus @@ -33,7 +33,7 @@ from aixplain.utils.file_utils import _request_with_retry -INSPECTOR_SUPPORTED_FUNCTIONS = [Function.GUARDRAILS, Function.TEXT_GENERATION] +INSPECTOR_SUPPORTED_FUNCTIONS = [Function.GUARDRAILS, Function.TEXT_GENERATION, Function.UTILITIES] class InspectorFactory: @@ -50,7 +50,7 @@ def create_from_model( name: Text, model: Union[Text, Model], model_config: Optional[Dict] = None, - policy: InspectorPolicy = InspectorPolicy.ADAPTIVE, # default: doing something dynamically + policy: Union[InspectorPolicy, Callable] = InspectorPolicy.ADAPTIVE, # default: doing something dynamically ) -> Inspector: """Create a new inspector agent from an onboarded model. @@ -64,11 +64,10 @@ def create_from_model( to use for the inspector. model_config (Optional[Dict], optional): Configuration parameters for the inspector model (e.g., prompts, thresholds). Defaults to None. - policy (InspectorPolicy, optional): Action to take upon negative feedback: - - WARN: Log warning but continue execution - - ABORT: Stop execution on negative feedback - - ADAPTIVE: Dynamically decide based on context - Defaults to InspectorPolicy.ADAPTIVE. + policy: Action to take upon negative feedback (WARN/ABORT/ADAPTIVE) + or a callable function. If callable, must have name "process_response", + arguments "model_response" and "input_content" (both strings), and + return InspectorAction. Defaults to ADAPTIVE. Returns: Inspector: Created and configured inspector agent. @@ -126,7 +125,7 @@ def create_auto( cls, auto: InspectorAuto, name: Optional[Text] = None, - policy: InspectorPolicy = InspectorPolicy.ADAPTIVE, + policy: Union[InspectorPolicy, Callable] = InspectorPolicy.ADAPTIVE, ) -> Inspector: """Create a new inspector agent using automatic configuration. @@ -138,11 +137,10 @@ def create_auto( auto (InspectorAuto): Pre-configured automatic inspector instance. name (Optional[Text], optional): Name for the inspector. If not provided, uses the name from the auto configuration. Defaults to None. - policy (InspectorPolicy, optional): Action to take upon negative feedback: - - WARN: Log warning but continue execution - - ABORT: Stop execution on negative feedback - - ADAPTIVE: Dynamically decide based on context - Defaults to InspectorPolicy.ADAPTIVE. + policy: Action to take upon negative feedback (WARN/ABORT/ADAPTIVE) + or a callable function. If callable, must have name "process_response", + arguments "model_response" and "input_content" (both strings), and + return InspectorAction. Defaults to ADAPTIVE. Returns: Inspector: Created and configured inspector agent using automatic diff --git a/aixplain/factories/team_agent_factory/utils.py b/aixplain/factories/team_agent_factory/utils.py index 08c7e93f..773ad59b 100644 --- a/aixplain/factories/team_agent_factory/utils.py +++ b/aixplain/factories/team_agent_factory/utils.py @@ -1,12 +1,14 @@ __author__ = "lucaspavanelli" import logging -from typing import Dict, Text, List +from typing import Dict, Text, List, Optional from urllib.parse import urljoin import aixplain.utils.config as config from aixplain.enums.asset_status import AssetStatus from aixplain.modules.agent import Agent +from aixplain.modules.agent.agent_task import AgentTask +from aixplain.modules.agent.tool.model_tool import ModelTool from aixplain.modules.team_agent import TeamAgent, InspectorTarget from aixplain.modules.team_agent.inspector import Inspector from aixplain.factories.agent_factory import AgentFactory @@ -15,6 +17,7 @@ from aixplain.modules.agent.output_format import OutputFormat GPT_4o_ID = "6646261c6eb563165658bbb1" +SUPPORTED_TOOLS = ["llm", "website_search", "website_scrape", "website_crawl", "serper_search"] def build_team_agent(payload: Dict, agents: List[Agent] = None, api_key: Text = config.TEAM_API_KEY) -> TeamAgent: @@ -29,7 +32,7 @@ def build_team_agent(payload: Dict, agents: List[Agent] = None, api_key: Text = - name: Team agent name - agents: List of agent configurations - description: Optional description - - role: Optional instructions + - instructions: Optional instructions - teamId: Optional supplier information - version: Optional version - cost: Optional cost information @@ -67,9 +70,21 @@ def build_team_agent(payload: Dict, agents: List[Agent] = None, api_key: Text = continue # Ensure custom classes are instantiated: for compatibility with backend return format - inspectors = [ - inspector if isinstance(inspector, Inspector) else Inspector(**inspector) for inspector in payload.get("inspectors", []) - ] + inspectors = [] + for inspector_data in payload.get("inspectors", []): + try: + if isinstance(inspector_data, Inspector): + inspectors.append(inspector_data) + else: + # Handle both old format and new format with policy_type + if hasattr(Inspector, "model_validate"): + inspectors.append(Inspector.model_validate(inspector_data)) + else: + inspectors.append(Inspector(**inspector_data)) + except Exception as e: + logging.warning(f"Failed to create inspector from data: {e}") + continue + inspector_targets = [InspectorTarget(target.lower()) for target in payload.get("inspectorTargets", [])] # Get LLMs from tools if present @@ -85,7 +100,14 @@ def build_team_agent(payload: Dict, agents: List[Agent] = None, api_key: Text = elif "tools" in payload: for tool in payload["tools"]: if tool["type"] == "llm": - llm = ModelFactory.get(payload["llmId"], api_key=api_key) + try: + llm = ModelFactory.get(payload["llmId"], api_key=api_key) + except Exception: + logging.warning( + f"LLM {payload['llmId']} not found. Make sure it exists or you have access to it. " + "If you think this is an error, please contact the administrators." + ) + continue # Set parameters from the tool if "parameters" in tool: # Apply all parameters directly to the LLM properties @@ -100,7 +122,10 @@ def build_team_agent(payload: Dict, agents: List[Agent] = None, api_key: Text = # Convert parameters list to dictionary format expected by ModelParameters params_dict = {} for param in tool["parameters"]: - params_dict[param["name"]] = {"required": False, "value": param["value"]} + params_dict[param["name"]] = { + "required": False, + "value": param["value"], + } # Create ModelParameters and set it on the LLM llm.model_params = ModelParameters(params_dict) @@ -146,5 +171,165 @@ def build_team_agent(payload: Dict, agents: List[Agent] = None, api_key: Text = if task_dependency: team_agent.agents[idx].tasks[i].dependencies[j] = task_dependency else: - raise Exception(f"Team Agent Creation Error: Task dependency not found - {dependency}") + team_agent.agents[idx].tasks[i].dependencies[j] = None + return team_agent + + +def parse_tool_from_yaml(tool: str) -> ModelTool: + from aixplain.enums import Function + + tool_name = tool.strip() + if tool_name == "translation": + return ModelTool( + function=Function.TRANSLATION, + ) + elif tool_name == "speech-recognition": + return ModelTool( + function=Function.SPEECH_RECOGNITION, + ) + elif tool_name == "text-to-speech": + return ModelTool( + function=Function.SPEECH_SYNTHESIS, + ) + elif tool_name == "llm": + return ModelTool(function=Function.TEXT_GENERATION) + elif tool_name == "serper_search": + return ModelTool(model="65c51c556eb563350f6e1bb1") + elif tool.strip() == "website_search": + return ModelTool(model="6736411cf127849667606689") + elif tool.strip() == "website_scrape": + return ModelTool(model="6748e4746eb5633559668a15") + elif tool.strip() == "website_crawl": + return ModelTool(model="6748d4cff12784b6014324e2") + else: + raise Exception(f"Tool {tool} in yaml not found.") + + +import yaml + + +def is_yaml_formatted(text): + """ + Check if a string is valid YAML format with additional validation. + + Args: + text (str): The string to check + + Returns: + bool: True if valid YAML, False otherwise + """ + if not text or not isinstance(text, str): + return False + + # Strip whitespace + text = text.strip() + + # Empty string is valid YAML + if not text: + return True + + try: + parsed = yaml.safe_load(text) + + # If it's just a plain string without YAML structure, + # we might want to consider it as non-YAML + # This is optional depending on your requirements + if isinstance(parsed, str) and "\n" not in text and ":" not in text: + return False + + return True + except yaml.YAMLError: + return False + + +def build_team_agent_from_yaml(yaml_code: str, llm_id: str, api_key: str, team_id: Optional[str] = None) -> TeamAgent: + import yaml + from aixplain.factories import AgentFactory, TeamAgentFactory + + # check if it is a yaml or just as string + if not is_yaml_formatted(yaml_code): + return None + team_config = yaml.safe_load(yaml_code) + + agents_data = team_config.get("agents", []) + tasks_data = team_config.get("tasks", []) + system_data = team_config.get("system", {"query": "", "name": "Test Team"}) + team_name = system_data.get("name", "") + team_description = system_data.get("description", "") + team_instructions = system_data.get("instructions", "") + llm = ModelFactory.get(llm_id) + # Create agent mapping by name for easier task assignment + agents_mapping = {} + agent_objs = [] + + # Parse agents + for agent_entry in agents_data: + agent_name = list(agent_entry.keys())[0] + agent_info = agent_entry[agent_name] + agent_instructions = agent_info.get("instructions", "") + agent_description = agent_info["description"] + agent_name = agent_name.replace("_", " ") + agent_name = f"{agent_name} agent" if not agent_name.endswith(" agent") else agent_name + agent_obj = Agent( + id="", + name=agent_name, + description=agent_description, + instructions=agent_instructions, + tasks=[], # Tasks will be assigned later + tools=[parse_tool_from_yaml(tool) for tool in agent_info.get("tools", []) if tool in SUPPORTED_TOOLS], + llm=llm, + ) + agents_mapping[agent_name] = agent_obj + agent_objs.append(agent_obj) + + # Create task collections for each agent (clean approach) + agent_tasks = {agent_name: [] for agent_name in agents_mapping.keys()} + + # Parse tasks and collect them by agent + for task in tasks_data: + for task_name, task_info in task.items(): + task_description = task_info.get("description", "") + expected_output = task_info.get("expected_output", "") + dependencies = task_info.get("dependencies", []) + agent_name = task_info.get("agent", "") + agent_name = agent_name.replace("_", " ") + agent_name = f"{agent_name} agent" if not agent_name.endswith(" agent") else agent_name + + task_obj = AgentTask( + name=task_name, + description=task_description, + expected_output=expected_output, + dependencies=dependencies, + ) + + # Add task to the corresponding agent's collection + if agent_name in agent_tasks: + # Check for duplicates within this build + existing_task_names = [task.name for task in agent_tasks[agent_name]] + if task_name not in existing_task_names: + agent_tasks[agent_name].append(task_obj) + else: + raise Exception(f"Agent '{agent_name}' referenced in tasks not found.") + + # Create agents with their respective task collections + for i, agent in enumerate(agent_objs): + agent_name = agent.name + agent_objs[i] = AgentFactory.create( + name=agent.name, + description=agent.description, + instructions=agent.instructions, + tools=agent.tools, + llm=llm, + tasks=agent_tasks.get(agent_name, []), # Use collected tasks + ) + return TeamAgentFactory.create( + name=team_name, + description=team_description, + instructions=team_instructions, + agents=agent_objs, + llm=llm, + api_key=api_key, + use_mentalist=True, + inspectors=[], + ) diff --git a/aixplain/modules/agent/__init__.py b/aixplain/modules/agent/__init__.py index 7973ac00..23a39c9a 100644 --- a/aixplain/modules/agent/__init__.py +++ b/aixplain/modules/agent/__init__.py @@ -29,20 +29,23 @@ from aixplain.utils.file_utils import _request_with_retry from aixplain.enums import Function, Supplier, AssetStatus, StorageType, ResponseStatus +from aixplain.enums.evolve_type import EvolveType from aixplain.modules.model import Model -from aixplain.modules.agent.agent_task import AgentTask +from aixplain.modules.agent.agent_task import WorkflowTask, AgentTask from aixplain.modules.agent.output_format import OutputFormat from aixplain.modules.agent.tool import Tool from aixplain.modules.agent.agent_response import AgentResponse from aixplain.modules.agent.agent_response_data import AgentResponseData from aixplain.modules.agent.utils import process_variables, validate_history from pydantic import BaseModel -from typing import Dict, List, Text, Optional, Union +from typing import Dict, List, Text, Optional, Union, Any +from aixplain.modules.agent.evolve_param import EvolveParam, validate_evolve_param from urllib.parse import urljoin from aixplain.modules.model.llm_model import LLM from aixplain.utils import config from aixplain.modules.mixins import DeployableMixin +import warnings class Agent(Model, DeployableMixin[Tool]): @@ -92,6 +95,7 @@ def __init__( cost: Optional[Dict] = None, status: AssetStatus = AssetStatus.DRAFT, tasks: List[AgentTask] = [], + workflow_tasks: List[WorkflowTask] = [], output_format: OutputFormat = OutputFormat.TEXT, expected_output: Optional[Union[BaseModel, Text, dict]] = None, **additional_info, @@ -138,7 +142,16 @@ def __init__( except Exception: status = AssetStatus.DRAFT self.status = status - self.tasks = tasks + if tasks: + warnings.warn( + "The 'tasks' parameter is deprecated and will be removed in a future version. " "Use 'workflow_tasks' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.workflow_tasks = tasks + else: + self.workflow_tasks = workflow_tasks + self.tasks = self.workflow_tasks self.output_format = output_format self.expected_output = expected_output self.is_valid = True @@ -375,6 +388,7 @@ def run_async( max_iterations: int = 5, output_format: Optional[OutputFormat] = None, expected_output: Optional[Union[BaseModel, Text, dict]] = None, + evolve: Union[Dict[str, Any], EvolveParam, None] = None, ) -> AgentResponse: """Runs asynchronously an agent call. @@ -390,6 +404,8 @@ def run_async( max_iterations (int, optional): maximum number of iterations between the agent and the tools. Defaults to 10. output_format (OutputFormat, optional): response format. If not provided, uses the format set during initialization. expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None. + output_format (ResponseFormat, optional): response format. Defaults to TEXT. + evolve (Union[Dict[str, Any], EvolveParam, None], optional): evolve the agent configuration. Can be a dictionary, EvolveParam instance, or None. Returns: dict: polling URL in response """ @@ -406,8 +422,9 @@ def run_async( from aixplain.factories.file_factory import FileFactory - if not self.is_valid: - raise Exception("Agent is not valid. Please validate the agent before running.") + # Validate and normalize evolve parameters using the base model + evolve_param = validate_evolve_param(evolve) + evolve_dict = evolve_param.to_dict() if output_format == OutputFormat.JSON: assert expected_output is not None and ( @@ -469,6 +486,7 @@ def run_async( "outputFormat": output_format, "expectedOutput": expected_output, }, + "evolve": json.dumps(evolve_dict), } payload.update(parameters) payload = json.dumps(payload) @@ -505,7 +523,7 @@ def to_dict(self) -> Dict: "version": self.version, "llmId": self.llm_id if self.llm is None else self.llm.id, "status": self.status.value, - "tasks": [task.to_dict() for task in self.tasks], + "tasks": [task.to_dict() for task in self.workflow_tasks], "tools": ( [ { @@ -535,7 +553,7 @@ def from_dict(cls, data: Dict) -> "Agent": """ from aixplain.factories.agent_factory.utils import build_tool from aixplain.enums import AssetStatus - from aixplain.modules.agent_task import AgentTask + from aixplain.modules.agent import WorkflowTask # Extract tools from assets using proper tool building tools = [] @@ -551,10 +569,10 @@ def from_dict(cls, data: Dict) -> "Agent": logging.warning(f"Failed to build tool from asset data: {e}") # Extract tasks using from_dict method - tasks = [] + workflow_tasks = [] if "tasks" in data: for task_data in data["tasks"]: - tasks.append(AgentTask.from_dict(task_data)) + workflow_tasks.append(WorkflowTask.from_dict(task_data)) # Extract LLM from tools section (main LLM info) llm = None @@ -585,7 +603,7 @@ def from_dict(cls, data: Dict) -> "Agent": id=data["id"], name=data["name"], description=data["description"], - instructions=data.get("role"), + instructions=data.get("instructions"), tools=tools, llm_id=data.get("llmId", "6646261c6eb563165658bbb1"), llm=llm, @@ -594,7 +612,7 @@ def from_dict(cls, data: Dict) -> "Agent": version=data.get("version"), cost=data.get("cost"), status=status, - tasks=tasks, + workflow_tasks=workflow_tasks, output_format=OutputFormat(data.get("outputFormat", OutputFormat.TEXT)), expected_output=data.get("expectedOutput"), ) @@ -727,3 +745,131 @@ def __repr__(self) -> str: str: A string in the format "Agent: (id=)". """ return f"Agent: {self.name} (id={self.id})" + + def evolve_async( + self, + evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None, + ) -> AgentResponse: + """Asynchronously evolve the Agent and return a polling URL in the AgentResponse. + + Args: + evolve_type (Union[EvolveType, str]): Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. + max_successful_generations (int): Maximum number of successful generations to evolve. Defaults to 3. + max_failed_generation_retries (int): Maximum retry attempts for failed generations. Defaults to 3. + max_iterations (int): Maximum number of iterations. Defaults to 50. + max_non_improving_generations (Optional[int]): Stop condition parameter for non-improving generations. Defaults to 2, can be None. + llm (Optional[Union[Text, LLM]]): LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + Returns: + AgentResponse: Response containing polling URL and status. + """ + from aixplain.utils.evolve_utils import create_llm_dict + + query = "" + + # Create EvolveParam from individual parameters + evolve_parameters = EvolveParam( + to_evolve=True, + evolve_type=evolve_type, + max_successful_generations=max_successful_generations, + max_failed_generation_retries=max_failed_generation_retries, + max_iterations=max_iterations, + max_non_improving_generations=max_non_improving_generations, + llm=create_llm_dict(llm), + ) + + return self.run_async(query=query, evolve=evolve_parameters) + + def evolve( + self, + evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None, + ) -> AgentResponse: + """Synchronously evolve the Agent and poll for the result. + + Args: + evolve_type (Union[EvolveType, str]): Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. + max_successful_generations (int): Maximum number of successful generations to evolve. Defaults to 3. + max_failed_generation_retries (int): Maximum retry attempts for failed generations. Defaults to 3. + max_iterations (int): Maximum number of iterations. Defaults to 50. + max_non_improving_generations (Optional[int]): Stop condition parameter for non-improving generations. Defaults to 2, can be None. + llm (Optional[Union[Text, LLM]]): LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + Returns: + AgentResponse: Final response from the evolution process. + """ + from aixplain.utils.evolve_utils import create_llm_dict + from aixplain.factories.team_agent_factory.utils import build_team_agent_from_yaml + + # Create EvolveParam from individual parameters + evolve_parameters = EvolveParam( + to_evolve=True, + evolve_type=evolve_type, + max_successful_generations=max_successful_generations, + max_failed_generation_retries=max_failed_generation_retries, + max_iterations=max_iterations, + max_non_improving_generations=max_non_improving_generations, + llm=create_llm_dict(llm), + ) + + start = time.time() + try: + logging.info(f"Evolve started with parameters: {evolve_parameters}") + logging.info("It might take a while...") + response = self.evolve_async( + evolve_type=evolve_type, + max_successful_generations=max_successful_generations, + max_failed_generation_retries=max_failed_generation_retries, + max_iterations=max_iterations, + max_non_improving_generations=max_non_improving_generations, + llm=llm, + ) + if response["status"] == ResponseStatus.FAILED: + end = time.time() + response["elapsed_time"] = end - start + return response + poll_url = response["url"] + end = time.time() + result = self.sync_poll(poll_url, name="evolve_process", timeout=600) + result_data = result.data + + if "current_code" in result_data and result_data["current_code"] is not None: + if evolve_parameters.evolve_type == EvolveType.TEAM_TUNING: + result_data["evolved_agent"] = build_team_agent_from_yaml( + result_data["current_code"], + self.llm_id, + self.api_key, + self.id, + ) + elif evolve_parameters.evolve_type == EvolveType.INSTRUCTION_TUNING: + self.instructions = result_data["current_code"] + self.update() + result_data["evolved_agent"] = self + else: + raise ValueError( + "evolve_parameters.evolve_type must be one of the following: TEAM_TUNING, INSTRUCTION_TUNING" + ) + return AgentResponse( + status=ResponseStatus.SUCCESS, + completed=True, + data=result_data, + used_credits=getattr(result, "used_credits", 0.0), + run_time=getattr(result, "run_time", end - start), + ) + except Exception as e: + logging.error(f"Agent Evolve: Error in evolving: {e}") + end = time.time() + return AgentResponse( + status=ResponseStatus.FAILED, + completed=False, + error_message="No response from the service.", + ) diff --git a/aixplain/modules/agent/agent_response.py b/aixplain/modules/agent/agent_response.py index fc35e072..d10cff29 100644 --- a/aixplain/modules/agent/agent_response.py +++ b/aixplain/modules/agent/agent_response.py @@ -1,8 +1,11 @@ from aixplain.enums import ResponseStatus -from typing import Any, Dict, Optional, Text, Union, List +from typing import Any, Dict, Optional, Text, Union, List, TYPE_CHECKING from aixplain.modules.agent.agent_response_data import AgentResponseData from aixplain.modules.model.response import ModelResponse +if TYPE_CHECKING: + from aixplain.modules.team_agent.evolver_response_data import EvolverResponseData + class AgentResponse(ModelResponse): """A response object for agent execution results. @@ -25,7 +28,7 @@ class AgentResponse(ModelResponse): def __init__( self, status: ResponseStatus = ResponseStatus.FAILED, - data: Optional[AgentResponseData] = None, + data: Optional[Union[AgentResponseData, "EvolverResponseData"]] = None, details: Optional[Union[Dict, List]] = {}, completed: bool = False, error_message: Text = "", diff --git a/aixplain/modules/agent/agent_response_data.py b/aixplain/modules/agent/agent_response_data.py index 4de10d12..b97b16c1 100644 --- a/aixplain/modules/agent/agent_response_data.py +++ b/aixplain/modules/agent/agent_response_data.py @@ -95,6 +95,9 @@ def to_dict(self) -> Dict[str, Any]: "critiques": self.critiques, } + def get(self, key: str, default: Optional[Any] = None) -> Any: + return getattr(self, key, default) + def __getitem__(self, key: str) -> Any: """Get an attribute value using dictionary-style access. diff --git a/aixplain/modules/agent/agent_task.py b/aixplain/modules/agent/agent_task.py index 469beba1..433d58c0 100644 --- a/aixplain/modules/agent/agent_task.py +++ b/aixplain/modules/agent/agent_task.py @@ -1,7 +1,7 @@ -from typing import List, Optional, Text, Union +from typing import List, Text, Union, Optional -class AgentTask: +class WorkflowTask: """A task definition for an AI agent to execute. This class represents a task that can be assigned to an agent, including its @@ -11,23 +11,24 @@ class AgentTask: name (Text): The unique identifier/name of the task. description (Text): Detailed description of what the task should accomplish. expected_output (Text): Description of the expected output format or content. - dependencies (Optional[List[Union[Text, AgentTask]]]): List of tasks or task + dependencies (Optional[List[Union[Text, WorkflowTask]]]): List of tasks or task names that must be completed before this task. Defaults to None. """ + def __init__( self, name: Text, description: Text, expected_output: Text, - dependencies: Optional[List[Union[Text, "AgentTask"]]] = None, + dependencies: Optional[List[Union[Text, "WorkflowTask"]]] = [], ): - """Initialize a new AgentTask instance. + """Initialize a new WorkflowTask instance. Args: name (Text): The unique identifier/name of the task. description (Text): Detailed description of what the task should accomplish. expected_output (Text): Description of the expected output format or content. - dependencies (Optional[List[Union[Text, AgentTask]]], optional): List of + dependencies (Optional[List[Union[Text, WorkflowTask]]], optional): List of tasks or task names that must be completed before this task. Defaults to None. """ @@ -39,7 +40,7 @@ def __init__( def to_dict(self) -> dict: """Convert the task to a dictionary representation. - This method serializes the task data, converting any AgentTask dependencies + This method serializes the task data, converting any WorkflowTask dependencies to their name strings. Returns: @@ -49,7 +50,7 @@ def to_dict(self) -> dict: - expectedOutput: The expected output description - dependencies: List of dependency names or None """ - agent_task_dict = { + workflow_task_dict = { "name": self.name, "description": self.description, "expectedOutput": self.expected_output, @@ -57,20 +58,20 @@ def to_dict(self) -> dict: } if self.dependencies: - for i, dependency in enumerate(agent_task_dict["dependencies"]): - if isinstance(dependency, AgentTask): - agent_task_dict["dependencies"][i] = dependency.name - return agent_task_dict + for i, dependency in enumerate(workflow_task_dict["dependencies"]): + if isinstance(dependency, WorkflowTask): + workflow_task_dict["dependencies"][i] = dependency.name + return workflow_task_dict @classmethod - def from_dict(cls, data: dict) -> "AgentTask": - """Create an AgentTask instance from a dictionary representation. + def from_dict(cls, data: dict) -> "WorkflowTask": + """Create an WorkflowTask instance from a dictionary representation. Args: - data: Dictionary containing AgentTask parameters + data: Dictionary containing WorkflowTask parameters Returns: - AgentTask instance + WorkflowTask instance """ return cls( name=data["name"], @@ -78,3 +79,17 @@ def from_dict(cls, data: dict) -> "AgentTask": expected_output=data["expectedOutput"], dependencies=data.get("dependencies", None), ) + + +# !this is a backward compatibility for the AgentTask class +# it will be removed in the future +class AgentTask(WorkflowTask): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def to_dict(self): + return super().to_dict() + + @classmethod + def from_dict(cls, data: dict) -> "AgentTask": + return super().from_dict(data) diff --git a/aixplain/modules/agent/evolve_param.py b/aixplain/modules/agent/evolve_param.py new file mode 100644 index 00000000..1693293e --- /dev/null +++ b/aixplain/modules/agent/evolve_param.py @@ -0,0 +1,269 @@ +__author__ = "aiXplain" + +""" +Copyright 2024 The aiXplain SDK authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: aiXplain Team +Date: December 2024 +Description: + EvolveParam Base Model Class for Agent and TeamAgent evolve functionality +""" +from aixplain.enums import EvolveType +from dataclasses import dataclass, field +from typing import Any, Dict, Optional, Union + + +@dataclass +class EvolveParam: + """Base model for evolve parameters used in Agent and TeamAgent evolution. + + Attributes: + to_evolve (bool): Whether to enable evolution. Defaults to False. + evolve_type (Optional[EvolveType]): Type of evolve. + max_successful_generations (int): Maximum number of successful generations. + max_failed_generation_retries (int): Maximum number of failed generation retries. + max_iterations (int): Maximum number of iterations. + max_non_improving_generations (Optional[int]): Maximum number of non-improving generations. + llm (Optional[Dict[str, Any]]): LLM configuration with all parameters. + additional_params (Optional[Dict[str, Any]]): Additional parameters. + """ + + to_evolve: bool = False + evolve_type: Optional[EvolveType] = EvolveType.TEAM_TUNING + max_successful_generations: int = 3 + max_failed_generation_retries: int = 3 + max_iterations: int = 50 + max_non_improving_generations: Optional[int] = 2 + llm: Optional[Dict[str, Any]] = None + additional_params: Optional[Dict[str, Any]] = field(default_factory=dict) + + def __post_init__(self): + """Validate parameters after initialization.""" + self.validate() + + def validate(self) -> None: + """Validate evolve parameters. + + Raises: + ValueError: If any parameter is invalid. + """ + if self.evolve_type is not None: + if isinstance(self.evolve_type, str): + # Convert string to EvolveType + try: + self.evolve_type = EvolveType(self.evolve_type) + except ValueError: + raise ValueError( + f"evolve_type '{self.evolve_type}' is not a valid EvolveType. Valid values are: {list(EvolveType)}" + ) + elif not isinstance(self.evolve_type, EvolveType): + raise ValueError("evolve_type must be a valid EvolveType or string") + if self.additional_params is not None: + if not isinstance(self.additional_params, dict): + raise ValueError("additional_params must be a dictionary") + + if self.max_successful_generations is not None: + if not isinstance(self.max_successful_generations, int): + raise ValueError("max_successful_generations must be an integer") + if self.max_successful_generations <= 0: + raise ValueError("max_successful_generations must be positive") + + if self.max_failed_generation_retries is not None: + if not isinstance(self.max_failed_generation_retries, int): + raise ValueError("max_failed_generation_retries must be an integer") + if self.max_failed_generation_retries <= 0: + raise ValueError("max_failed_generation_retries must be positive") + + if self.max_iterations is not None: + if not isinstance(self.max_iterations, int): + raise ValueError("max_iterations must be an integer") + if self.max_iterations <= 0: + raise ValueError("max_iterations must be positive") + + if self.max_non_improving_generations is not None: + if not isinstance(self.max_non_improving_generations, int): + raise ValueError("max_non_improving_generations must be an integer or None") + if self.max_non_improving_generations <= 0: + raise ValueError("max_non_improving_generations must be positive or None") + + # Add validation for llm parameter + if self.llm is not None: + if not isinstance(self.llm, dict): + raise ValueError("llm must be a dictionary or None") + + @classmethod + def from_dict(cls, data: Union[Dict[str, Any], None]) -> "EvolveParam": + """Create EvolveParam instance from dictionary. + + Args: + data (Union[Dict[str, Any], None]): Dictionary containing evolve parameters. + + Returns: + EvolveParam: Instance with parameters set from dictionary. + + Raises: + ValueError: If data format is invalid. + """ + if data is None: + return cls() + + if not isinstance(data, dict): + raise ValueError("evolve parameter must be a dictionary or None") + + # Extract known parameters + known_params = { + "to_evolve": data.get("toEvolve", data.get("to_evolve", False)), + "evolve_type": data.get("evolve_type"), + "max_successful_generations": data.get("max_successful_generations"), + "max_failed_generation_retries": data.get("max_failed_generation_retries"), + "max_iterations": data.get("max_iterations"), + "max_non_improving_generations": data.get("max_non_improving_generations"), + "llm": data.get("llm"), + "additional_params": data.get("additional_params"), + } + + # Remove None values + known_params = {k: v for k, v in known_params.items() if v is not None} + + # Collect additional parameters + additional_params = { + k: v + for k, v in data.items() + if k + not in [ + "toEvolve", + "to_evolve", + "evolve_type", + "max_successful_generations", + "max_failed_generation_retries", + "max_iterations", + "max_non_improving_generations", + "llm", + "additional_params", + ] + } + + return cls(additional_params=additional_params, **known_params) + + def to_dict(self) -> Dict[str, Any]: + """Convert EvolveParam instance to dictionary for API calls. + + Returns: + Dict[str, Any]: Dictionary representation with API-compatible keys. + """ + result = { + "toEvolve": self.to_evolve, + } + + # Add optional parameters if they are set + if self.evolve_type is not None: + result["evolve_type"] = self.evolve_type + if self.max_successful_generations is not None: + result["max_successful_generations"] = self.max_successful_generations + if self.max_failed_generation_retries is not None: + result["max_failed_generation_retries"] = self.max_failed_generation_retries + if self.max_iterations is not None: + result["max_iterations"] = self.max_iterations + # Always include max_non_improving_generations, even if None + result["max_non_improving_generations"] = self.max_non_improving_generations + if self.llm is not None: + result["llm"] = self.llm + if self.additional_params is not None: + result.update(self.additional_params) + + return result + + def merge(self, other: Union[Dict[str, Any], "EvolveParam"]) -> "EvolveParam": + """Merge this EvolveParam with another set of parameters. + + Args: + other (Union[Dict[str, Any], EvolveParam]): Other parameters to merge. + + Returns: + EvolveParam: New instance with merged parameters. + """ + if isinstance(other, dict): + other = EvolveParam.from_dict(other) + elif not isinstance(other, EvolveParam): + raise ValueError("other must be a dictionary or EvolveParam instance") + + # Create merged parameters + merged_additional = {**self.additional_params, **other.additional_params} + + return EvolveParam( + to_evolve=other.to_evolve if other.to_evolve else self.to_evolve, + evolve_type=(other.evolve_type if other.evolve_type is not None else self.evolve_type), + max_successful_generations=( + other.max_successful_generations + if other.max_successful_generations is not None + else self.max_successful_generations + ), + max_failed_generation_retries=( + other.max_failed_generation_retries + if other.max_failed_generation_retries is not None + else self.max_failed_generation_retries + ), + max_iterations=(other.max_iterations if other.max_iterations is not None else self.max_iterations), + max_non_improving_generations=( + other.max_non_improving_generations + if other.max_non_improving_generations is not None + else self.max_non_improving_generations + ), + llm=(other.llm if other.llm is not None else self.llm), + additional_params=merged_additional, + ) + + def __repr__(self) -> str: + return ( + f"EvolveParam(" + f"to_evolve={self.to_evolve}, " + f"evolve_type={self.evolve_type}, " + f"max_successful_generations={self.max_successful_generations}, " + f"max_failed_generation_retries={self.max_failed_generation_retries}, " + f"max_iterations={self.max_iterations}, " + f"max_non_improving_generations={self.max_non_improving_generations}, " + f"llm={self.llm}, " + f"additional_params={self.additional_params})" + ) + + +def validate_evolve_param( + evolve_param: Union[Dict[str, Any], EvolveParam, None], +) -> EvolveParam: + """Utility function to validate and convert evolve parameters. + + Args: + evolve_param (Union[Dict[str, Any], EvolveParam, None]): Input evolve parameters. + + Returns: + EvolveParam: Validated EvolveParam instance. + + Raises: + ValueError: If parameters are invalid. + """ + if evolve_param is None: + return EvolveParam() + + if isinstance(evolve_param, EvolveParam): + evolve_param.validate() + return evolve_param + + if isinstance(evolve_param, dict): + # Check for required toEvolve key for backward compatibility + if "toEvolve" not in evolve_param and "to_evolve" not in evolve_param: + raise ValueError("evolve parameter must contain 'toEvolve' key") + return EvolveParam.from_dict(evolve_param) + + raise ValueError("evolve parameter must be a dictionary, EvolveParam instance, or None") diff --git a/aixplain/modules/model/index_model.py b/aixplain/modules/model/index_model.py index b9420f52..61488c12 100644 --- a/aixplain/modules/model/index_model.py +++ b/aixplain/modules/model/index_model.py @@ -1,3 +1,6 @@ +import os +import warnings +from uuid import uuid4 from aixplain.enums import EmbeddingModel, Function, Supplier, ResponseStatus, StorageType, FunctionType from aixplain.modules.model import Model from aixplain.utils import config @@ -9,9 +12,7 @@ from aixplain.enums.splitting_options import SplittingOptions import os -from urllib.parse import urljoin -from aixplain.utils.file_utils import _request_with_retry - +DOCLING_MODEL_ID = "677bee6c6eb56331f9192a91" class IndexFilterOperator(Enum): """Enumeration of operators available for filtering index records. @@ -177,8 +178,6 @@ def __init__( model = ModelFactory.get(embedding_model) self.embedding_size = model.additional_info["embedding_size"] except Exception as e: - import warnings - warnings.warn(f"Failed to get embedding size for embedding model {embedding_model}: {e}") self.embedding_size = None @@ -231,11 +230,11 @@ def search(self, query: str, top_k: int = 10, filters: List[IndexFilter] = []) - } return self.run(data=data) - def upsert(self, documents: List[Record], splitter: Optional[Splitter] = None) -> ModelResponse: + def upsert(self, documents: Union[List[Record], str], splitter: Optional[Splitter] = None) -> ModelResponse: """Upsert documents into the index Args: - documents (List[Record]): List of documents to be upserted + documents (Union[List[Record], str]): List of documents to be upserted or a file path splitter (Splitter, optional): Splitter to be applied. Defaults to None. Returns: @@ -244,8 +243,12 @@ def upsert(self, documents: List[Record], splitter: Optional[Splitter] = None) - Examples: index_model.upsert([Record(value="Hello, world!", value_type="text", uri="", id="1", attributes={})]) index_model.upsert([Record(value="Hello, world!", value_type="text", uri="", id="1", attributes={})], splitter=Splitter(split=True, split_by=SplittingOptions.WORD, split_length=1, split_overlap=0)) + index_model.upsert("my_file.pdf") + index_model.upsert("my_file.pdf", splitter=Splitter(split=True, split_by=SplittingOptions.WORD, split_length=400, split_overlap=50)) Splitter in the above example is optional and can be used to split the documents into smaller chunks. """ + if isinstance(documents, str): + documents = [self.prepare_record_from_file(documents)] # Validate documents for doc in documents: doc.validate() @@ -272,7 +275,7 @@ def upsert(self, documents: List[Record], splitter: Optional[Splitter] = None) - return response raise Exception(f"Failed to upsert documents: {response.error_message}") - def count(self) -> float: + def count(self) -> int: """Get the total number of documents in the index. Returns: @@ -335,6 +338,63 @@ def delete_record(self, record_id: Text) -> ModelResponse: return response raise Exception(f"Failed to delete record: {response.error_message}") + def prepare_record_from_file(self, file_path: str, file_id: str = None) -> Record: + """Prepare a record from a file. + + Args: + file_path (str): The path to the file to be processed. + file_id (str, optional): The ID to assign to the record. If not provided, a unique ID is generated. + + Returns: + Record: A Record object containing the file's content and metadata. + + Raises: + Exception: If the file cannot be parsed. + + Example: + >>> record = index_model.prepare_record_from_file("/path/to/file.txt") + """ + response = self.parse_file(file_path) + file_name = file_path.split("/")[-1] + if not file_id: + file_id = file_name + "_" + str(uuid4()) + return Record(value=response.data, value_type="text", id=file_id, attributes={"file_name": file_name}) + + @staticmethod + def parse_file(file_path: str) -> ModelResponse: + """Parse a file using the Docling model. + + Args: + file_path (str): The path to the file to be parsed. + + Returns: + ModelResponse: The response containing the parsed file content. + + Raises: + Exception: If the file does not exist or cannot be parsed. + + Example: + >>> response = IndexModel.parse_file("/path/to/file.pdf") + """ + if not os.path.exists(file_path): + raise Exception(f"File {file_path} does not exist") + if file_path.endswith(".txt"): + with open(file_path, "r") as file: + data = file.read() + if not data: + warnings.warn(f"File {file_path} is empty") + return ModelResponse(status=ResponseStatus.SUCCESS, data=data, completed=True) + try: + from aixplain.factories import ModelFactory + + model = ModelFactory.get(DOCLING_MODEL_ID) + response = model.run(file_path) + if not response.data: + warnings.warn(f"File {file_path} is empty") + return response + except Exception as e: + raise Exception(f"Failed to parse file: {e}") + def retrieve_records_with_filter(self, filter: IndexFilter) -> ModelResponse: """ Retrieve records from the index that match the given filter. diff --git a/aixplain/modules/model/utils.py b/aixplain/modules/model/utils.py index 24baea26..9fa3bf2d 100644 --- a/aixplain/modules/model/utils.py +++ b/aixplain/modules/model/utils.py @@ -372,9 +372,7 @@ def parse_code_decorated(code: Union[Text, Callable]) -> Tuple[Text, List, Text, description = ( getattr(code, "_tool_description", None) if hasattr(code, "_tool_description") - else code.__doc__.strip() - if code.__doc__ - else "" + else code.__doc__.strip() if code.__doc__ else "" ) name = getattr(code, "_tool_name", None) if hasattr(code, "_tool_name") else "" if hasattr(code, "_tool_inputs") and code._tool_inputs != []: diff --git a/aixplain/modules/team_agent/__init__.py b/aixplain/modules/team_agent/__init__.py index b5270bd8..b5669ece 100644 --- a/aixplain/modules/team_agent/__init__.py +++ b/aixplain/modules/team_agent/__init__.py @@ -27,7 +27,7 @@ import traceback import re from enum import Enum -from typing import Dict, List, Text, Optional, Union +from typing import Dict, List, Text, Optional, Union, Any from urllib.parse import urljoin from datetime import datetime @@ -36,12 +36,15 @@ from aixplain.enums.supplier import Supplier from aixplain.enums.asset_status import AssetStatus from aixplain.enums.storage_type import StorageType +from aixplain.enums.evolve_type import EvolveType from aixplain.modules.model import Model from aixplain.modules.agent import Agent, OutputFormat from aixplain.modules.agent.agent_response import AgentResponse from aixplain.modules.agent.agent_response_data import AgentResponseData +from aixplain.modules.agent.evolve_param import EvolveParam, validate_evolve_param from aixplain.modules.agent.utils import process_variables, validate_history from aixplain.modules.team_agent.inspector import Inspector +from aixplain.modules.team_agent.evolver_response_data import EvolverResponseData from aixplain.utils import config from aixplain.utils.request_utils import _request_with_retry from aixplain.modules.model.llm_model import LLM @@ -123,6 +126,7 @@ def __init__( self.agents = agents self.llm_id = llm_id self.llm = llm + self.api_key = api_key self.use_mentalist = use_mentalist self.inspectors = inspectors self.inspector_targets = inspector_targets @@ -213,7 +217,7 @@ def run( output_format (OutputFormat, optional): response format. If not provided, uses the format set during initialization. expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None. Returns: - Dict: parsed output from model + AgentResponse: parsed output from model """ start = time.time() result_data = {} @@ -283,6 +287,7 @@ def run_async( max_iterations: int = 30, output_format: Optional[OutputFormat] = None, expected_output: Optional[Union[BaseModel, Text, dict]] = None, + evolve: Union[Dict[str, Any], EvolveParam, None] = None, ) -> AgentResponse: """Runs asynchronously a Team Agent call. @@ -298,8 +303,9 @@ def run_async( max_iterations (int, optional): maximum number of iterations between the agents. Defaults to 30. output_format (OutputFormat, optional): response format. If not provided, uses the format set during initialization. expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None. + evolve (Union[Dict[str, Any], EvolveParam, None], optional): evolve the team agent configuration. Can be a dictionary, EvolveParam instance, or None. Returns: - dict: polling URL in response + AgentResponse: polling URL in response """ if session_id is not None and history is not None: raise ValueError("Provide either `session_id` or `history`, not both.") @@ -313,6 +319,10 @@ def run_async( from aixplain.factories.file_factory import FileFactory + # Validate and normalize evolve parameters using the base model + evolve_param = validate_evolve_param(evolve) + evolve_dict = evolve_param.to_dict() + if not self.is_valid: raise Exception("Team Agent is not valid. Please validate the team agent before running.") @@ -371,6 +381,7 @@ def run_async( "outputFormat": output_format, "expectedOutput": expected_output, }, + "evolve": json.dumps(evolve_dict), } payload.update(parameters) payload = json.dumps(payload) @@ -384,7 +395,7 @@ def run_async( logging.info(f"Result of request for {name} - {r.status_code} - {resp}") poll_url = resp["data"] - return AgentResponse( + response = AgentResponse( status=ResponseStatus.IN_PROGRESS, url=poll_url, data=AgentResponseData(input=input_data), @@ -394,10 +405,69 @@ def run_async( except Exception: msg = f"Error in request for {name} - {traceback.format_exc()}" logging.error(f"Team Agent Run Async: Error in running for {name}: {resp}") - return AgentResponse( - status=ResponseStatus.FAILED, - error=msg, + if resp is not None: + response = AgentResponse( + status=ResponseStatus.FAILED, + error=msg, + ) + return response + + def poll(self, poll_url: Text, name: Text = "model_process") -> AgentResponse: + used_credits, run_time = 0.0, 0.0 + resp, error_message, status = None, None, ResponseStatus.SUCCESS + headers = {"x-api-key": self.api_key, "Content-Type": "application/json"} + r = _request_with_retry("get", poll_url, headers=headers) + try: + resp = r.json() + if resp["completed"] is True: + status = ResponseStatus(resp.get("status", "FAILED")) + if "error_message" in resp or "supplierError" in resp: + status = ResponseStatus.FAILED + error_message = resp.get("error_message") + else: + status = ResponseStatus.IN_PROGRESS + logging.debug(f"Single Poll for Team Agent: Status of polling for {name}: {resp}") + + resp_data = resp.get("data") or {} + used_credits = resp_data.get("usedCredits", 0.0) + run_time = resp_data.get("runTime", 0.0) + evolve_type = resp_data.get("evolve_type", EvolveType.TEAM_TUNING.value) + if "evolved_agent" in resp_data and status == ResponseStatus.SUCCESS: + if evolve_type == EvolveType.INSTRUCTION_TUNING.value: + # return this class as it is but replace its description and instructions + evolved_agent = self + current_code = resp_data.get("current_code", "") + evolved_agent.description = current_code + evolved_agent.update() + resp_data["evolved_agent"] = evolved_agent + else: + resp_data = EvolverResponseData.from_dict(resp_data, llm_id=self.llm_id, api_key=self.api_key) + else: + resp_data = AgentResponseData( + input=resp_data.get("input"), + output=resp_data.get("output"), + session_id=resp_data.get("session_id"), + intermediate_steps=resp_data.get("intermediate_steps"), + execution_stats=resp_data.get("executionStats"), + ) + except Exception as e: + import traceback + + logging.error(f"Single Poll for Team Agent: Error of polling for {name}: {e}, traceback: {traceback.format_exc()}") + status = ResponseStatus.FAILED + error_message = str(e) + finally: + response = AgentResponse( + status=status, + data=resp_data, + details=resp.get("details", {}), + completed=resp.get("completed", False), + used_credits=used_credits, + run_time=run_time, + usage=resp.get("usage", None), + error_message=error_message, ) + return response def delete(self) -> None: """Delete Corpus service""" @@ -480,7 +550,7 @@ def to_dict(self) -> Dict: - supplier (str): The supplier code - version (str): The version number - status (str): The current status - - role (str): The team agent's instructions + - instructions (str): The team agent's instructions """ if self.use_mentalist: planner_id = self.mentalist_llm.id if self.mentalist_llm else self.llm_id @@ -493,11 +563,11 @@ def to_dict(self) -> Dict: "links": [], "description": self.description, "llmId": self.llm.id if self.llm else self.llm_id, - "supervisorId": self.supervisor_llm.id if self.supervisor_llm else self.llm_id, + "supervisorId": (self.supervisor_llm.id if self.supervisor_llm else self.llm_id), "plannerId": planner_id, "inspectors": [inspector.model_dump(by_alias=True) for inspector in self.inspectors], "inspectorTargets": [target.value for target in self.inspector_targets], - "supplier": self.supplier.value["code"] if isinstance(self.supplier, Supplier) else self.supplier, + "supplier": (self.supplier.value["code"] if isinstance(self.supplier, Supplier) else self.supplier), "version": self.version, "status": self.status.value, "instructions": self.instructions, @@ -515,10 +585,10 @@ def from_dict(cls, data: Dict) -> "TeamAgent": Returns: TeamAgent instance """ - from aixplain.factories.agent_factory import AgentFactory from aixplain.factories.model_factory import ModelFactory from aixplain.enums import AssetStatus from aixplain.modules.team_agent import Inspector, InspectorTarget + from aixplain.modules.agent import Agent # Extract agents from agents list using proper agent loading agents = [] @@ -527,20 +597,23 @@ def from_dict(cls, data: Dict) -> "TeamAgent": if "assetId" in agent_data: try: # Load agent using AgentFactory - agent = AgentFactory.get(agent_data["assetId"]) + agent = Agent.from_dict(agent_data) agents.append(agent) except Exception as e: # Log warning but continue processing other agents import logging logging.warning(f"Failed to load agent {agent_data['assetId']}: {e}") - + else: + agents.append(Agent.from_dict(agent_data)) # Extract inspectors using proper model validation inspectors = [] if "inspectors" in data: for inspector_data in data["inspectors"]: try: - if hasattr(Inspector, "model_validate"): + if isinstance(inspector_data, Inspector): + inspectors.append(inspector_data) + elif hasattr(Inspector, "model_validate"): inspectors.append(Inspector.model_validate(inspector_data)) else: inspectors.append(Inspector(**inspector_data)) @@ -548,6 +621,7 @@ def from_dict(cls, data: Dict) -> "TeamAgent": import logging logging.warning(f"Failed to create inspector from data: {e}") + continue # Extract inspector targets inspector_targets = [InspectorTarget.STEPS] # default @@ -601,7 +675,7 @@ def from_dict(cls, data: Dict) -> "TeamAgent": version=data.get("version"), use_mentalist=use_mentalist, status=status, - instructions=data.get("role"), + instructions=data.get("instructions"), inspectors=inspectors, inspector_targets=inspector_targets, output_format=OutputFormat(data.get("outputFormat", OutputFormat.TEXT)), @@ -726,3 +800,133 @@ def __repr__(self): str: A string in the format "TeamAgent: (id=)". """ return f"TeamAgent: {self.name} (id={self.id})" + + def evolve_async( + self, + evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None, + ) -> AgentResponse: + """Asynchronously evolve the Team Agent and return a polling URL in the AgentResponse. + + Args: + evolve_type (Union[EvolveType, str]): Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. + max_successful_generations (int): Maximum number of successful generations to evolve. Defaults to 3. + max_failed_generation_retries (int): Maximum retry attempts for failed generations. Defaults to 3. + max_iterations (int): Maximum number of iterations. Defaults to 50. + max_non_improving_generations (Optional[int]): Stop condition parameter for non-improving generations. Defaults to 2, can be None. + llm (Optional[Union[Text, LLM]]): LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + Returns: + AgentResponse: Response containing polling URL and status. + """ + from aixplain.utils.evolve_utils import create_llm_dict + + query = "" + + # Create EvolveParam from individual parameters + evolve_parameters = EvolveParam( + to_evolve=True, + evolve_type=evolve_type, + max_successful_generations=max_successful_generations, + max_failed_generation_retries=max_failed_generation_retries, + max_iterations=max_iterations, + max_non_improving_generations=max_non_improving_generations, + llm=create_llm_dict(llm), + ) + + response = self.run_async(query=query, evolve=evolve_parameters) + return response + + def evolve( + self, + evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None, + ) -> AgentResponse: + """Synchronously evolve the Team Agent and poll for the result. + + Args: + evolve_type (Union[EvolveType, str]): Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. + max_successful_generations (int): Maximum number of successful generations to evolve. Defaults to 3. + max_failed_generation_retries (int): Maximum retry attempts for failed generations. Defaults to 3. + max_iterations (int): Maximum number of iterations. Defaults to 50. + max_non_improving_generations (Optional[int]): Stop condition parameter for non-improving generations. Defaults to 2, can be None. + llm (Optional[Union[Text, LLM]]): LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + Returns: + AgentResponse: Final response from the evolution process. + """ + from aixplain.enums import EvolveType + from aixplain.utils.evolve_utils import create_llm_dict + from aixplain.factories.team_agent_factory.utils import build_team_agent_from_yaml + + # Create EvolveParam from individual parameters + evolve_parameters = EvolveParam( + to_evolve=True, + evolve_type=evolve_type, + max_successful_generations=max_successful_generations, + max_failed_generation_retries=max_failed_generation_retries, + max_iterations=max_iterations, + max_non_improving_generations=max_non_improving_generations, + llm=create_llm_dict(llm), + ) + start = time.time() + try: + logging.info(f"Evolve started with parameters: {evolve_parameters}") + logging.info("It might take a while...") + response = self.evolve_async( + evolve_type=evolve_type, + max_successful_generations=max_successful_generations, + max_failed_generation_retries=max_failed_generation_retries, + max_iterations=max_iterations, + max_non_improving_generations=max_non_improving_generations, + llm=llm, + ) + if response["status"] == ResponseStatus.FAILED: + end = time.time() + response["elapsed_time"] = end - start + return response + poll_url = response["url"] + end = time.time() + result = self.sync_poll(poll_url, name="evolve_process", timeout=600) + result_data = result.data + current_code = result_data.get("current_code") if isinstance(result_data, dict) else result_data.current_code + if current_code is not None: + if evolve_parameters.evolve_type == EvolveType.TEAM_TUNING: + result_data["evolved_agent"] = build_team_agent_from_yaml( + result_data["current_code"], + self.llm_id, + self.api_key, + self.id, + ) + elif evolve_parameters.evolve_type == EvolveType.INSTRUCTION_TUNING: + self.instructions = result_data["current_code"] + self.description = result_data["current_code"] + self.update() + result_data["evolved_agent"] = self + else: + raise ValueError( + "evolve_parameters.evolve_type must be one of the following: TEAM_TUNING, INSTRUCTION_TUNING" + ) + return AgentResponse( + status=ResponseStatus.SUCCESS, + completed=True, + data=result_data, + used_credits=getattr(result, "used_credits", 0.0), + run_time=getattr(result, "run_time", end - start), + ) + except Exception as e: + logging.error(f"Team Agent Evolve: Error in evolving: {e}") + end = time.time() + return AgentResponse( + status=ResponseStatus.FAILED, + completed=False, + error_message="No response from the service.", + ) diff --git a/aixplain/modules/team_agent/evolver_response_data.py b/aixplain/modules/team_agent/evolver_response_data.py new file mode 100644 index 00000000..06479e4e --- /dev/null +++ b/aixplain/modules/team_agent/evolver_response_data.py @@ -0,0 +1,70 @@ +from typing import Any, Dict, List, Text, TYPE_CHECKING + +if TYPE_CHECKING: + from aixplain.modules.team_agent import TeamAgent + + +class EvolverResponseData: + def __init__( + self, + evolved_agent: "TeamAgent", + current_code: Text, + evaluation_report: Text, + comparison_report: Text, + criteria: Text, + archive: List[Text], + current_output: Text = "", + ) -> None: + self.evolved_agent = evolved_agent + self.current_code = current_code + self.evaluation_report = evaluation_report + self.comparison_report = comparison_report + self.criteria = criteria + self.archive = archive + self.current_output = current_output + + @classmethod + def from_dict(cls, data: Dict[str, Any], llm_id: Text, api_key: Text) -> "EvolverResponseData": + from aixplain.factories.team_agent_factory.utils import build_team_agent_from_yaml + + yaml_code = data.get("current_code", "") + evolved_team_agent = build_team_agent_from_yaml(yaml_code=yaml_code, llm_id=llm_id, api_key=api_key) + return cls( + evolved_agent=evolved_team_agent, + current_code=yaml_code, + evaluation_report=data.get("evaluation_report", ""), + comparison_report=data.get("comparison_report", ""), + criteria=data.get("criteria", ""), + archive=data.get("archive", []), + current_output=data.get("current_output", ""), + ) + + def to_dict(self) -> Dict[str, Any]: + return { + "evolved_agent": self.evolved_agent, + "current_code": self.current_code, + "evaluation_report": self.evaluation_report, + "comparison_report": self.comparison_report, + "criteria": self.criteria, + "archive": self.archive, + "current_output": self.current_output, + } + + def __getitem__(self, key: str) -> Any: + return getattr(self, key, None) + + def __setitem__(self, key: str, value: Any) -> None: + if hasattr(self, key): + setattr(self, key, value) + else: + raise KeyError(f"{key} is not a valid attribute of {self.__class__.__name__}") + + def __repr__(self) -> str: + return ( + f"{self.__class__.__name__}(" + f"evolved_agent='{self.evolved_agent}', " + f"evaluation_report='{self.evaluation_report}', " + f"comparison_report='{self.comparison_report}', " + f"criteria='{self.criteria}', " + f"archive='{self.archive}', " + ) diff --git a/aixplain/modules/team_agent/inspector.py b/aixplain/modules/team_agent/inspector.py index 6e930fb9..d0a10932 100644 --- a/aixplain/modules/team_agent/inspector.py +++ b/aixplain/modules/team_agent/inspector.py @@ -1,4 +1,5 @@ """Pre-defined agent for inspecting the data flow within a team agent. +WARNING: This feature is currently in private beta. WARNING: This feature is currently in private beta. @@ -21,17 +22,40 @@ ) """ +import inspect from enum import Enum -from typing import Dict, Optional, Text +from typing import Dict, Optional, Text, Union, Callable -from pydantic import field_validator +import textwrap +from pydantic import BaseModel, field_validator from aixplain.modules.agent.model_with_params import ModelWithParams +from aixplain.modules.model.response import ModelResponse AUTO_DEFAULT_MODEL_ID = "67fd9e2bef0365783d06e2f0" # GPT-4.1 Nano +class InspectorAction(str, Enum): + """ + Inspector's decision on the next action. + """ + + CONTINUE = "continue" + RERUN = "rerun" + ABORT = "abort" + + +class InspectorOutput(BaseModel): + """ + Inspector's output. + """ + + critiques: Text + content_edited: Text + action: InspectorAction + + class InspectorAuto(str, Enum): """A list of keywords for inspectors configured automatically in the backend.""" @@ -57,6 +81,202 @@ class InspectorPolicy(str, Enum): ADAPTIVE = "adaptive" # adjust execution according to feedback +def validate_policy_callable(policy_func: Callable) -> bool: + """Validate that the policy callable meets the required constraints.""" + # Check function name + if policy_func.__name__ != "process_response": + return False + + # Get function signature + sig = inspect.signature(policy_func) + params = list(sig.parameters.keys()) + + # Check arguments - should have exactly 2 parameters: model_response and input_content + if len(params) != 2 or params[0] != "model_response" or params[1] != "input_content": + return False + + # Check return type annotation - should return InspectorOutput + return_annotation = sig.return_annotation + if return_annotation != InspectorOutput: + return False + + return True + + +def callable_to_code_string(policy_func: Callable) -> str: + """Convert a callable policy function to a code string for serialization.""" + try: + source_code = get_policy_source(policy_func) + if source_code is None: + # If we can't get the source code, create a minimal representation + sig = inspect.signature(policy_func) + return f"def process_response{str(sig)}:\n # Function source not available\n pass" + + # Dedent the source code to remove leading whitespace + source_code = textwrap.dedent(source_code) + return source_code + except (OSError, TypeError): + # If we can't get the source code, create a minimal representation + sig = inspect.signature(policy_func) + return f"def process_response{str(sig)}:\n # Function source not available\n pass" + + +def code_string_to_callable(code_string: str) -> Callable: + """Convert a code string back to a callable function for deserialization.""" + try: + # Create a namespace to execute the code + namespace = { + "InspectorAction": InspectorAction, + "InspectorOutput": InspectorOutput, + "ModelResponse": ModelResponse, + "str": str, + "int": int, + "float": float, + "bool": bool, + "list": list, + "dict": dict, + "tuple": tuple, + "set": set, + "len": len, + "print": print, + "range": range, + "enumerate": enumerate, + "zip": zip, + "map": map, + "filter": filter, + "any": any, + "all": all, + "sum": sum, + "min": min, + "max": max, + "abs": abs, + "round": round, + "sorted": sorted, + "reversed": reversed, + "isinstance": isinstance, + "hasattr": hasattr, + "getattr": getattr, + "setattr": setattr, + "dir": dir, + "type": type, + "id": id, + "hash": hash, + "repr": repr, + "str": str, + "format": format, + "ord": ord, + "chr": chr, + "bin": bin, + "oct": oct, + "hex": hex, + "pow": pow, + "divmod": divmod, + "complex": complex, + "bytes": bytes, + "bytearray": bytearray, + "memoryview": memoryview, + "slice": slice, + "property": property, + "staticmethod": staticmethod, + "classmethod": classmethod, + "super": super, + "object": object, + "Exception": Exception, + "ValueError": ValueError, + "TypeError": TypeError, + "AttributeError": AttributeError, + "KeyError": KeyError, + "IndexError": IndexError, + "RuntimeError": RuntimeError, + "AssertionError": AssertionError, + "ImportError": ImportError, + "ModuleNotFoundError": ModuleNotFoundError, + "NameError": NameError, + "SyntaxError": SyntaxError, + "IndentationError": IndentationError, + "TabError": TabError, + "UnboundLocalError": UnboundLocalError, + "UnicodeError": UnicodeError, + "UnicodeDecodeError": UnicodeDecodeError, + "UnicodeEncodeError": UnicodeEncodeError, + "UnicodeTranslateError": UnicodeTranslateError, + "OSError": OSError, + "FileNotFoundError": FileNotFoundError, + "PermissionError": PermissionError, + "ProcessLookupError": ProcessLookupError, + "TimeoutError": TimeoutError, + "ConnectionError": ConnectionError, + "BrokenPipeError": BrokenPipeError, + "ConnectionAbortedError": ConnectionAbortedError, + "ConnectionRefusedError": ConnectionRefusedError, + "ConnectionResetError": ConnectionResetError, + "BlockingIOError": BlockingIOError, + "ChildProcessError": ChildProcessError, + "NotADirectoryError": NotADirectoryError, + "IsADirectoryError": IsADirectoryError, + "InterruptedError": InterruptedError, + "EnvironmentError": EnvironmentError, + "IOError": IOError, + "EOFError": EOFError, + "MemoryError": MemoryError, + "RecursionError": RecursionError, + "SystemError": SystemError, + "ReferenceError": ReferenceError, + "FloatingPointError": FloatingPointError, + "OverflowError": OverflowError, + "ZeroDivisionError": ZeroDivisionError, + "ArithmeticError": ArithmeticError, + "BufferError": BufferError, + "LookupError": LookupError, + "StopIteration": StopIteration, + "GeneratorExit": GeneratorExit, + "KeyboardInterrupt": KeyboardInterrupt, + "SystemExit": SystemExit, + "BaseException": BaseException, + } + + # Execute the code string in the namespace + exec(code_string, namespace) + + # Get the function from the namespace + if "process_response" not in namespace: + raise ValueError("Code string must define a function named 'process_response'") + + func = namespace["process_response"] + + # Store the original source code as an attribute for later retrieval + func._source_code = code_string + + # Validate the function + if not validate_policy_callable(func): + raise ValueError("Deserialized function does not meet the required constraints") + + return func + except Exception as e: + raise ValueError(f"Failed to deserialize code string to callable: {e}") + + +def get_policy_source(func: Callable) -> Optional[str]: + """Get the source code of a policy function. + + This function tries to retrieve the source code of a policy function. + It first checks if the function has a stored _source_code attribute (for functions + created via code_string_to_callable), then falls back to inspect.getsource(). + + Args: + func: The function to get source code for + + Returns: + The source code string if available, None otherwise + """ + if hasattr(func, "_source_code"): + return func._source_code + try: + return inspect.getsource(func) + except (OSError, TypeError): + return None + + class Inspector(ModelWithParams): """Pre-defined agent for inspecting the data flow within a team agent. @@ -66,13 +286,15 @@ class Inspector(ModelWithParams): name: The name of the inspector. model_id: The ID of the model to wrap. model_params: The configuration for the model. - policy: The policy for the inspector. Default is ADAPTIVE. + policy: The policy for the inspector. Can be InspectorPolicy enum or a callable function. + If callable, must have name "process_response", arguments "model_response" and "input_content" (both strings), + and return InspectorAction. Default is ADAPTIVE. """ name: Text model_params: Optional[Dict] = None auto: Optional[InspectorAuto] = None - policy: InspectorPolicy = InspectorPolicy.ADAPTIVE + policy: Union[InspectorPolicy, Callable] = InspectorPolicy.ADAPTIVE def __init__(self, *args, **kwargs): """Initialize an Inspector instance. @@ -116,3 +338,47 @@ def validate_name(cls, v: Text) -> Text: if v == "": raise ValueError("name cannot be empty") return v + + @field_validator("policy") + def validate_policy(cls, v: Union[InspectorPolicy, Callable]) -> Union[InspectorPolicy, Callable]: + if callable(v): + if not validate_policy_callable(v): + raise ValueError( + "Policy callable must have name 'process_response', arguments 'model_response' and 'input_content' (both strings), and return InspectorAction" + ) + elif not isinstance(v, InspectorPolicy): + raise ValueError(f"Policy must be InspectorPolicy enum or a valid callable function, got {type(v)}") + return v + + def model_dump(self, by_alias: bool = False, **kwargs) -> Dict: + """Override model_dump to handle callable policy serialization.""" + data = super().model_dump(by_alias=by_alias, **kwargs) + + # Handle callable policy serialization + if callable(self.policy): + data["policy"] = callable_to_code_string(self.policy) + data["policy_type"] = "callable" + elif isinstance(self.policy, InspectorPolicy): + data["policy"] = self.policy.value + data["policy_type"] = "enum" + + return data + + @classmethod + def model_validate(cls, data: Union[Dict, "Inspector"]) -> "Inspector": + """Override model_validate to handle callable policy deserialization.""" + if isinstance(data, cls): + return data + + # Handle callable policy deserialization + if isinstance(data, dict) and data.get("policy_type") == "callable": + policy_code = data.get("policy") + if isinstance(policy_code, str): + try: + data["policy"] = code_string_to_callable(policy_code) + except Exception: + # If deserialization fails, fall back to default policy + data["policy"] = InspectorPolicy.ADAPTIVE + data.pop("policy_type", None) # Remove the type indicator + + return super().model_validate(data) diff --git a/aixplain/utils/evolve_utils.py b/aixplain/utils/evolve_utils.py new file mode 100644 index 00000000..437e1a31 --- /dev/null +++ b/aixplain/utils/evolve_utils.py @@ -0,0 +1,29 @@ +from typing import Union, Dict, Any, Optional, Text +from aixplain.modules.model.llm_model import LLM + + +def create_llm_dict(llm: Optional[Union[Text, LLM]]) -> Optional[Dict[str, Any]]: + """Create a dictionary representation of an LLM for evolution parameters. + + Args: + llm: Either an LLM ID string or an LLM object instance. + + Returns: + Dictionary with LLM information if llm is provided, None otherwise. + """ + if llm is None: + return None + + if isinstance(llm, LLM): + return { + "id": llm.id, + "name": llm.name, + "description": llm.description, + "supplier": llm.supplier, + "version": llm.version, + "function": llm.function, + "parameters": (llm.get_parameters().to_list() if llm.get_parameters() else None), + "temperature": getattr(llm, "temperature", None), + } + else: + return {"id": llm} diff --git a/pyproject.toml b/pyproject.toml index a606361e..c1af1a1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,10 +10,10 @@ namespaces = true [project] name = "aiXplain" -version = "0.2.34" +version = "0.2.35rc1" description = "aiXplain SDK adds AI functions to software." readme = "README.md" -requires-python = ">=3.5, <4" +requires-python = ">=3.9, <4" license = { text = "Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0" } authors = [ {email = "ahmet@aixplain.com"}, @@ -30,10 +30,6 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", diff --git a/tests/functional/agent/agent_functional_test.py b/tests/functional/agent/agent_functional_test.py index 578abe67..e0ab8942 100644 --- a/tests/functional/agent/agent_functional_test.py +++ b/tests/functional/agent/agent_functional_test.py @@ -46,17 +46,15 @@ def run_input_map(request): @pytest.fixture(scope="function") def delete_agents_and_team_agents(): - for team_agent in TeamAgentFactory.list()["results"]: - team_agent.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + from tests.test_deletion_utils import safe_delete_all_agents_and_team_agents + + # Clean up before test + safe_delete_all_agents_and_team_agents() yield True - for team_agent in TeamAgentFactory.list()["results"]: - team_agent.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + # Clean up after test + safe_delete_all_agents_and_team_agents() @pytest.mark.parametrize("AgentFactory", [AgentFactory, v2.Agent]) @@ -98,7 +96,6 @@ def test_end2end(run_input_map, delete_agents_and_team_agents, AgentFactory): assert response["completed"] is True assert response["status"].lower() == "success" assert "data" in response - assert response["data"]["session_id"] is None assert response["data"]["output"] is not None agent.delete() @@ -524,7 +521,6 @@ def test_instructions(delete_agents_and_team_agents, AgentFactory): assert response["completed"] is True assert response["status"].lower() == "success" assert "data" in response - assert response["data"]["session_id"] is None assert response["data"]["output"] is not None assert "aixplain" in response["data"]["output"].lower() agent.delete() diff --git a/tests/functional/agent/data/agent_test_end2end.json b/tests/functional/agent/data/agent_test_end2end.json index 595d22a9..f21b0196 100644 --- a/tests/functional/agent/data/agent_test_end2end.json +++ b/tests/functional/agent/data/agent_test_end2end.json @@ -1,8 +1,8 @@ [ { "agent_name": "TEST Translation agent", - "llm_id": "6626a3a8c8f1d089790cf5a2", - "llm_name": "Groq Llama 3 70B", + "llm_id": "67fd9ddfef0365783d06e2ef", + "llm_name": "GPT-4.1 Mini", "query": "Who is the president of Brazil right now? Translate to pt", "model_tools": [ { diff --git a/tests/functional/model/data/test_file_parser_input.pdf b/tests/functional/model/data/test_file_parser_input.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5882d1bcfe60dcf21b6436f78e916071a8c91d87 GIT binary patch literal 16202 zcmaL81yEeg()f)NB)CghAh_)Uiv)KFF2Nxzu(-2Wu;35~?jAfya1ZVhB)EHU2m}d% zz_&bd?{n{czyGOIoO61nyQh1)r)sJCF{nw)a)3B_F&U-~_ct&>03g88)CN;nm`lqV zW(Nf@!=SFP*A~`x(AQ277gwmuYikE5Hy8^hmzs;Cxtkf(1;DInYYpLo+X2{vcmx4* zj*gaaMQKMfSAYi8!5r!Wbzu<|#e}~;TITt;2Qvr&gvlkT4B%36bg_rn{d*Gl-;-pm z?O<>xT(Wi$7*rZ+=4cMZ6uyaYRP69i03<}vxm+t zr1KsvIppM2=XKs0foK}b=r6^e zR~$}oX)2d492z@B3x3D)HKr?kh)UVrV42ioEs%s z$;En#W~N%=#ZEu`4Qv|Zr2s^B3c6gSR%M2k88bsSBPG8Sj)-5Td~D_L-pQpQar1I6 z(Kc_B9eRmp2<0SR8Jk=Kx^tIM%gETbV?aJPT)08c`XpQy5DqgA*Sz~7ON&v)s~10L zSC(nMa#dgqQ#{tiUpx3$g>e6S^R>L3pa3p4h$Vc_HK4AJZZ2j}R{*>?;l*dB355X+ z{-`@HEvP39z@=ahpD6j)Q|hm$f)OT{j3-P^69%uJM^!lD3j#{ z@ct=#lqy5bts#<*o&Wv%^H*SxpMN*kzXEf8wCe_62D}v%t<7Bl29NP;82!5$1piy@ zProvDPQ zW0w9}J?JqRk46ms7%=*m{GVsWUtv9FM9T#V-!&CCdw57dz#rQGjOx+N|FNV;Ee%IU z_(~N271JNdd>l}LZ?huQ>oHY-X82JE06i|?p9}q;0+NEjAa;(Hk6M=S`uSs9;M)vw zu~l%eaC|I)KMU<|$)96Ta{zpUp^p{uXS)7g+uteDwuX8@UDRBl7VtC9;jha4)6)M8 zVRA`ZyE@rHyx^(+^JM+owi3j_62J^~_{SLu`o|&p=TQd&aP#tlx#1Q2|2PgoJRn~1 zKM%xX9}FKN8ItR=gY5n0VoUC8CGG?z3j*!{aU3Mt_yDThxLaVCGy%XxQ4&F2y_+=< zKgmsGl2}++4#F4&d*bX^ok$p6uVSaB9X^&$h!V}!lP9rRy@G>X2GLgktr2a{t+;Sw+Ggv z8MRhJNByX~<+(paxoWQUmYZtyW~}XcYHC5$O}Wm_3AK>H+d=GPoypGyZfWtz{IqT1 zN&H;)HaKm94!Cbm(GY&;096s5s#PJV6BUqi*>2b}hpYt!-*9ht!R(G>bag_k5q}n% zSM&LQ>)tJlYuox@7)rRLV#xj@(@%$Ee6kDh`PF+xN=pfoD;Y&n36qnrMIm^pbG)`J zC?sIcRs^KtMU*7(snjT$6QzJCEt>Z;p#f#iK2<1gAA1$4 z5==}15#{Z1neWb4*&Yp*sY={ornzpmdr7P(Y?mfxdS%Evq#=-=lt|1 z!nVfqM!f(5bhMARC0x|^waGhTR|I0RIQM1ab=`WxXsO{a;!vAyMa=$uP&vJSz~xYj z{OeDC2(#5b*u?A>Hy4Pyk>e>Fu4$vq}o)! z09+3Sq)u(m@X@d^6I@}1=uOQf6H-|B>#m4~AMU!S{3ebz(+?fpubAhCO8SVMke#=p z#)5>@Gfsn3s!jx*$dAy_omp~vY;@T^hpJYf(wpaoDoNWnhh|o=%PH2s{!GO&uuvlM zr9k4~&Ti#DUa^K6H?iI&uI(Pn#Kq`+YBSZ~T8luDB} z1+CMGT@T4Wu%lCy;JJU1q88e#cGl7sT`%g2Jv>9}v4Gp}L#jiK7u=t9u*ToL8n(*3 zw%urqTKbOdBQN|sMhP&rkI)jlO3N-|n=xX!MU|D+fQLi%>=w{`JrvHU{=b(v!Yjgv9Kl)bloI)$=6hd(AX43TlW8+%`d z#wlzYa>ta@9S%AURctfV#8Bns?`gHfKEwZp!O=~)Y4y1{ykc{wlC{1SZ@=2=AxgAZ5`Bh5!>%I zzKV+(+}*Z4e|i&;S6yIpP`J;FdJ+s&mR35L?t@kdaq@b} zEC%J7pY%_)i*Rol)SJx87KM7f`d62^2MROl^%B3{qw#XxdwQs_{0RE|+MEe$OA^!LZk%Up!5+dU$yI=AHrsI2C>#7WLec-qIo-wIHNiTE$p`FHY=x zwV2W~InFkj==Ie1(*py-;UtrjFr?MpNybG<{;!ADOuh-(c+VxcQc+uD>7(!uLKq=w zPH|2Nc!b78tE8d?(O6=e72z)?xh%pVAi8LL%XcGvLcQa?<63T|q*^&8ZU=n_Y%@j& z{_;|VabKmaw>2m;FSSwrO3_4NTQ`y&_7>D@G-9GRTD z=Dv1Kw(-js)5vYTg9L}SFx=~NKI)%FZ=psD2Tl1m?h9GZpfcW+67|sQyXkSB? zHXt8D3^8LSUcxl}ChWvTo~cemcWK3|wi8ZJ7H+9Wz6*)jaM6{2KnrtzRvDHtMCHtB zh=poS?1Of_Sx%PQBA%7skg&VwQ=L^5tCG9<+m4zxO}nLX019`(T9-v;A;*mCh6(i8-amw3AQV4SZVQB&eSq){JIxbldt!( zuz3=_H?*OghPj5g$dk{?HMJp;1{;J;I1TajZ7J*e>7hKk$Sw_~?@nI5VnMbR^372B zz<-&-*Ua?!uax6WgT0|-7Rp3^wbt6n?p4fMC$M0+;|=i@Pg!b$b$~Fzov-XU`(;dS8UY%h8p>;5VWIW)^Jt=qQm>vKznZ^9GdI0VM7WZjo1N_) z)IZ|xTn%n}b@w|xFp0ewA^|9R8jUk%`+DMS-dWv%$+^rv^)ppiiVK2pQoz+maMy)y z8o%z6?#7Zs(A5y>v6CF~$vp$IYvV|=fLUY4C`Px*ks@yv`xa5btRvJr%UFVNng4osL zf0{FuI;bAD?f5oMNmZqkBAIDl_c_7H5QLR3DPPGsir%Zm%H-r7Cj~a&2x3&MFA(2r zN!K7g>_}DB5~;m~4YL-AZ=0b-sETfq+=!g#6}L!cZ^E!LL~zTi{WY0g@WxXL58RyK zy>gYx=yN{KE~LS_o75Y=<*%_!#8sJ1P@c`3Pr8oO?PIqmn+^QI~Riou$!VNCC7 z9hhevkdmh{n^ita01izh>lOp+90(f4qt(an#)`jEav-A|&^LPXtJ0@LQE)hWbMoT= zK~GeY^si#M3&m^7><>nrh+7(ZB5tzYt)E_#m+F7+;UUDg5mu^Dz)c)5p%@#*yLV$* z>Cr8@?9UslanVM+Tk~oYXl|)cJCca)cAe9V%8Ib%6{P_2UPjlD5EpfeTKk} zuawx!7KjnT&kcuN^cWRUbdgFi+Rf2tzW-V^Qh&>5%zBQUoxLLScGo)I3&p}?(la}A zG(VN8|3{v1jL~R+qH4u{nTXHJS)6UGXF>yIQ?|UtS*>@&iYsCtw991b)AMR`B?zSJ zbJ2o~Z%^wvE>%ky6gtK16uA@#!c&p*jnU5tlOO6E3a6Gx7=V;O8NT1% z_LRREVYyR>GjFIHIELZ!;;#Wl$*NPu{>ApldzWbS#+9b_hfm+cRxvp(lot=(=@=Ka zW6+Z+$qt!ofaX@rc?0?ZX`P2vAkf2M$}&F$En$H@?aLrSeUBYq&};!ns&wh>v_9)= z2YoHOtvNY4pc!gjJ60Y?yY807_yg_*Ymg*z%oJ+xT|t7i2dyCf+IHe!Y482ez@Z&E zmTtF%`39?j`usK(^Y>v&tz$PDi+jeHgQflLvAYmi`3s?Kb2OEy;@4hYzdX!6Uc6Uf z!qG_ChrQ@B=MjLY2@GoOz3%Y&E#&e>m@y`-p8CpD*uF#YipCsbj=Uu@+a0m)^&{2 zdT)C~NTPLFlbK276m~2KgpLkQ!7g=-LwpH?0G1Pgxm*dW>vA)+ zrxYmdRJ(u@N*%99?Xop;7es7U=Ije(d@Uho> zk}Zl1OhbA?CEm0_d&%A%z^D1}pOn{C5nSs=e zJ^L*Ak5)NB6!i82Wc1Z2`MoI)Qe85eTn2`Qy{q)BGPH? zk(HO6d1>uI(?S>2RExIMeLX)soay3I0CyiyHZB;Sl+kxYwlALjMwl)EzN7#jfM}6l z)rt@9J$ZWOf$=H&>&-pqud`_J-VW%r$*&i^K%maG+tH2N6O+{N4~SAcXkZOTx=Y47 z$b2{iE0hdvnp>J&>aA$Zh77i2w+Xg7HX+DruN~*8DDvd^Nz7G@%S6il>xt(-_Z2TH zh5h10N47}!c!d3Mws@m*ipSjxZXk)zMi6u2K*^x79v9-@Kcbb&UXw#Vc*lD9^$KG{ z$rw#iBQ{=O+q8sPz(&sus^bRMy4ixNq)&#VMtq=z7X>C7cy_Ea z;Pt>{RBG4@c8-1QhORde-8i?(>SIv)*op3u`xx z$&Ff@OQy%mMs@`>ke8FZFN`Gf@Uy);F`&1Sv)-@2cp)z%VW-qP=jM}ha7xz*3#R!I zQ8M$W49E?)Q1ndUNd0bs*gSX zbxGvwHab27R7I}7gRiwU4|DDjob7xlFhPlS>Uq`&OywCL`YnSW&9INU0(FJZl zt@Nfj4vzcV7!L}it*0t%Cv-pZn!hS*yyummVBJw{)@a#I(O{@FpV9@_^cR4vU`@om z)JdV6_Y<>)RN=DojtF)(_sF>QgZ_A()@eu&3WyJB2n-aMmJ;kTB}FruvIz&e*LEe@ z#NpIA1V?l&3OuHz>sAD{+ESO(lhu&815SlBDz<2?fr5zLSv#ifMg7tDlb1#)MYAyc z5NO3^&5scy@o?xd*qFq!vaP6r#4wr|`ic8ce&l=UyPSYf6j>FcPku0)qoM;Aa5cJy zt=UbKnucweS%(>VX6xYGwiUFG^Bk9CX7-3cHolULsn!Q#E@N-+Mw&KuDDn0V`S3&k zUC`XrdiUsogm?l;Wh09*SMa!5n-U2`WcgF5XIrfH$YDhA%+hMQo?f*GPr{rtT5i&u zwHw;6SufFGH%VIKfl0LSA1}s*7Im}c<&FDxdswYSjYB*;2g-hihv}sGmA*928-B%9 zX4vOVF!=FByC?NlfI0ORVmaYWz0TC0eDD#Ox=?F0H4Z-tTLzG~_meSboY*#l_=#PP zQHB5*hkrC(B&P4Za`mE#ri`6?6f2at0iaWQa5v0I4%0jbYJ(CSDM1V_sCXBov3qkYmJce zZAT6_&u~iTKD6_BPT9%{ZGVe1^pY!R<@|9X>j-7rqpt@^Il)H51Bjneft`rhx&`~* zDIH;n=MB0ogu_l9YQXBx%^Da4DCkC#8#&Q+cJAK&e9dN@T5l(4=1E0g(E)?#LD?5| zCtI*{UnKJszR>2gmi^+c(7lXy^|CtNJlpv7LLqE`2OVO8F+voaK&)rXGBRaDNbJx0 zuoKag`6ZC=*E|k^GW|$yy>@uvE7d|P%p%5UeUE&uzT~i3eV;CE0@{ipK7yWTX+SpG z)!0y#omb$?@1}Zm(P9xXb&Ps0=cc3YGPmcs?P86Po&+1QN&tvflu`~(e>wbA$*-d4 zE=-{oU=ca83V+~~h_OOI&clxiXNrTD_Xs#uw41V2 zlOdi+%j?pM$PNW<>k=2vN~m0>6h9MBCoiGlOA5U(m|aI0_7eaaen*dpR9)3Xp>)}Zec|*FGE;JFo%T@XL_l;Pet7-|qH3x$ z8Z|^qfOfZhFDtWVbT?TzU37?gxMjChZ>@l~l;GxqT7UpfX(Bx^dkcjuNC3Z|P9=~h zsnUddfW?VqQ>#Q9r-zp;OdxAZ5csSbjgi?uOg}YT0Qn4~t&wSwjiV16`+LaL5^bt@MM8V2M+z+85m7w1= zO%1sr?X>G#6K-mxM$QjAlaFeOhU@@ooKe}uKjWPd>SAEwa|QN=llGv7 zr#Km+D&ld4SoDtM$_PFw6Ks%R+oaG9{Yk0&sp|BY4X<*&iG)*2G>{F#u=%3tiL;1d zlqa!ap3jrxD$FyRCL&ipfZvn3PH6aCw@vS%$-&~IjipY|Ai zH|TBMc+=~>?h)?)mNM~r-MC5Ji}WNY1Fy0BOZc^`4}yb)51xa}9sP3XPrQM!4fkIA z@7}#+%K=T)XViOdzk~~!V3{&47k+*k)44LdX2LWexACl(^C$8qXA`M2|GgVBQbI@BoKTks@kCA_k8E4;FsaM<=c#b(*}7k3zEPv?Vv zGQ!v@I}NBF&{XN#pQ_TfBdgN4kDQ5kqMiAAlAIy`jI6=Eaur4xXYt;U@_cqi?}>P3 z7LC3k)2q79(5t!u?HxDCIp?O@{3-Z3@F(i$($6TbyKTe$cRk6B3p56yhPQ|>Mv79a1N#(n?a51mDt_qd1)<6bCNOQ|r$7KY%?dzQr*#1FRv zC76^?!dH&=ynt_;4C*NleevANK6U}$r1z?G>|e^eJ~tY^&WaLO_o1l=zO3LTt4^gS zd6*b_!hTO{14(>W6oG_#KLxcXwO_%lci7#nGrJNHjCTorOkG zn^wcue!@#8aHd{7IT%3$lKT>FJPJW+C|U3-W22*qp;4Ym86E&$P?bMuaV9B#C@-%o zh7Fpy9DK(lS4(tIZJbD4)v9irE8`Zun27L4k{R)mzlflBCT1xz$Zyuq=NquU*v1Ba z+s5X{sVDVTbQv4{$UnQw4jdb|CR=v+?9$0NV4r>a{>qN(MU9LIM`T-2hWd32&EV?3 zAN#HK_3Dw%@u{UPE7kJ~MZr+RF48J}@=|Q<$oYW)jHq*=-=E|iR5qNPJx|g$=a=`> z7YA?BZ{mnU-9mS<*C;z;bl+hqODF!|#>%?c=bIZvR79IVY!}u{+kY`-kzlG}&u7m= z4ZzEA?=|BF8k_!#RO#0zq?Bx7FROkFnkeAQ!0(YIN*e0xwdcM;u_W~c*uZvb z&FS~(_1X)994@Oah-|@=o?5%Bl5H$72&rTekZAmgWes~v(#O>Vf50Ycu2Z9q&1O0 zp|?7#{O~)THW|1G6$>5r^qEQ{Hd9a55h_VdQ5FTCn&n_pTrs5n2R3__rRiy0O0!&> zj`HsVZt$z6rZ-Ev)L?&Ed(+Qal=EyQMn}ZcXncO5HtbOBS0i?x4`_ShF^7_Bc7U58 zl;(DZZp;H*8by-iE8yKWA+wO7J5a;DiOFTclsbEEcY#D{Yt6~D`b8KnIrb%cPMrw~ z2W|a}RD4cWsuy*sYce5v8z!Op!xRcw=hQgGJr0e6nO#-6$x1{+fj-&_%vrUzT@3>R zbbCDN_svVNL zZ^oi-&!5EZm!!5VNX}2oAD!%W7J_z|y(dZ6&WO-c&D&e&&EF@e5N+E&k9cERqe#JM z6EPyr4J4Q6P6+5FzxsMO&dv8MIp@>3C1lXV5f(Koe%F4U=(3xb$TAk1h_-8g!3Rk= zdv^0IM#2nsNHTHLjWpvTRa^bVvvLFfSY?GCEvUz-aKnr>mD?gcB~>Q_l?UQVCrmb< zOW~wT>Fg%@mc$Utg6Edp+9gVq>cy1heW+D;o_3M!H>HHo@kVT}M%X}n?M~Sqg=hfx zCB7J~_>+iqIxB^IrDOTT89J%v{rB7q^y)?3=Iol>n-Gq89$)uQ1ApFEqiqCdico?i zr6Z8Sz_Wy=8OUeKFJ55+y#_xo6t>89rZnFfbnu=fY#NErtA4D8?N>jM8Z+0@82K*T zd=Iz>RoKy9a@1o;DP}5hb!k{pzq8p(>{epgI$(mgyvX@?p|&;7-*=^9t3MoFE3>Qb z1H3=!I&tV7`oOpp7+S;#S}c~bRzo7Q-yDBo@()UG#&ok5`=m@F&)}U`2GimVjSA_< z%r70(-WCc|nNe;~KKoMWs-?WR(17;3@xg6|lI65jOyQ>2z4xZ@HenjsukZBxEq%6z z+{fa@siU>M6tqdDEr1*b2eWb`0@)!MLvckiwicY>|GHm@|!u!-fHG=nBy%`94G^)|f#0BUzrLvs)=}nWABFXdCjdqmp#b zc8XG}vD1=mFyR@a)YDun&+JZ(BNOpcI(`y@rFX|{uzJ^fYNF^sZ9Axr$6v&q(lUA} zK9-o5CK#fiH(=?zjD+%QaAjcUStGG1r!#tr=x|$8%(D7moU_t5bP%rFx+m7iR{Gn` zlP=|o#3S;+p?6=L_Zkt^A zaT|Yl#GR-7T($dEXtu}R^PZ}Gor;zmC6Cn=g*#~gTKvkb#Obw*$0vvj$h_cC`>>F zw*F2!`Z~*LPk3-(Vq~ZG#A(|}#MMJ_a)U!icsVeNtAp7lfy1VvU^Z8b-nPQHs^p6? z0c~6+*j658ck3&XVpU0QNtGwFid@~)sL~SFk%Z#Fw=XQ&BRZKzyVS{I&8DZukg3q* zkdRlqy8e}AHmUU+13#RL~0qzL}y^^35@@u*0mYq>nGD^AbS(tdO$p6#hJ&5K<2#+R>?j0H_>eoZ6( zC|uaDMd#ga*lAC2WBy&X9>*Rz^`XII@;GauohX8<&jq28-Hz6w$Nrn>aszBqF~4Sb zm*H>f`Qqt zg6+}v?EL;Zl)0h_Y*9bWPTknA@~xsqFQ_+S+fWQYYXEGSmKF@?8BZGe^Ui4=_&oP{ ztvpqxqj^*qQRHd1 zO>!{QVA0R;`^st(E~a25?9}V*qh*e1tvj`Y>cT^z2|fP_61oaYYpt3|2HlBTSTEfN zjd^<_ujG||PM8flTBNcXKJZp6Ub&Lz`JADY#xfdXGgZHwlsqK|nSP0tLSwSP&%ncQ z?hTt-!NpXQdOJ%~$kEJsR>W-20p#SYDYu@F(TYQpT7)t|dw`LJZEfgzF7>GiiHZ2e zM0e^|Nf4h>2z)g0xy0X_$_0oG^W#g3)}i02MqnDy&3nBma&l*9bv{h`bJ2G*7eaC- zEd@z)MFZCSl5A(S^^$MQ&b?vY@t*0a{w`Lx7&OFO7W3VDO z&(>+r1n7IWtez-`=9(T#CX6K_tvuZN#m)N?Ig#9N$q zWpBsYPF23NO^dq5@Q78vv?Wl4o$o2A$A_t7;CFgfcRWeOo=3}32r!s06x$KVFiP<# zb4y z{U{(KhGsmFDI#&3f|UuwHooe4L}CF;azZdzK{q})?l_7J3#@>|vA>qLb!~JO z@_XV&LHsiG!1L`3a6sef4 zg$NnIn#P3!5s#T{89pU(U(-N8W!xQMP(`?H3>2VyvD<86NgFcUP+*>ns*&n7)B7s< za|JAgH;Hjw4{c{l<$&`oeW03s#T-qCa=Qe_LjpHdKJ%OAyXrj&BVk?11P$cu#-`xK zgb}%~rwZ+*d4+KxOXDE5lHtxu@N%c(41D zeW%1pSmu4`4=Y~eS0{97%XFu%)J`m%pxo*-I~=w*#L~yWgDA!zmXCEs+fiFgC4Qn( z+(yd@PR^B*dmvN6=^?cB-+b;>yDAYlsPg zthD6MP8lVhsoZ$_=Je5@m{V;z$aWxoP9-=)_MA@bDZaxFTg;oWhQ+I>jX)w7w;3$5 zz#o8uwyA{gUJen{JNqoivCXd3-~A31Vj6B4%M39yI3?`icPz7emf~-%%GP!s*q8sw zzk1i%{h8VaDuPIu`&)qBZp~5<;rRk+Y zb5-(I8sL2ra+pdEv)+W-LOg|;Vm8V`Dsoykb+;1Nnx$v+fxMku*EKnT*r`IMRSh9> zJFO+k+IyZrg_rMW7@hKjY=*Ikagv|N*AR7bh)!`+d$@!i$=UYVuv^HX%4amSq+*}B z`hEJ6W&*4}{+L8b;+Kml`ic4u2!Mz+)uW)##W1@MU=yPHMIn3!TSVc7dCof{zD78_ zwGLb+_$c=5W94Zj%^ev&sjNGvmaz`ujEcJQJk?`R6C5b2v%+k6E{&b& zlg?f&(j*FM>_j7dESoo*-0BteR&^8=puRkCU@q+&PT+)fEx%1TBYmu-hE-^Y>qK|6 z^@dN~-8tt;0n?4q^w)vy(wl;VMwJ167aP$s-m~|aZlhCTjd4QEb2J8T@Y4EqLtFXU zFL2Orn%#;Nb1bk8UmhfsS>NHwNqRS5eTw@rGA81yqp3qDu-B) z9}0Zq-ifWE7Ua?GB)n4oR{NpP_rtgY{k@;3(lu8->Hx1U#$~|Z=`oir>3nBVQ#-( zNM$((SOmBSI0X0wKmw|HmeZhPn3fh$9I|vlDV?$$!t8`L_9pgPjvpQ^OHb!4*D}4g z*1ciZlqX{?Ox|)o)2ir&_N^_RN0`J9DiK6nzhZhVk>$hUb`G8yO}YozC{v0`B@lD( zNvi_vNH2plM2^H+d$LAieyl)GFiz4=>`&Sp>KBeZxSUTtBK@x291i@Dz@1|cISPR- zW@a-`0tPL{+b5`Wgu^P)9`jTocPM&%dYBmGS}85eNkzYo;>jLVhOfhO7_S3zWHnPM zBHAV1bcA_wuS^o@Kt#Pihv!JQYz|t~FLm)wQk$r@ARn>tKj`m&vurCTf_7wNW5u6e zs0e zdEFoSoO`^^6)A-VT#F`uc9U}+0$;lgl_tr2SQGI+3|8-P@e|tl%4DHy8ajJZMj}Av zwaRw2EbMztn`7{0DrT9DV3yeVjyYSW_=f-y&_3|GHS6?k#C%R9euG2|1=J+q3JR@!BiAZP& z8hCj_TA8iUP@;#4xxG7|ET#_Lj`F`W4LeRY#S$`U1Yu|_xVrC`%QWj4R&T}0Y0xcL zdpIP^@vX>MIs(4tt=jTk+&LI>-adTbk~8pq`lEa&HK=>Q`1bJht0b4pp%4-X{YnP z5ighB%{qqY&xA}LRN5=tYO*5Zs+FAM9hjV>uYp|_)yk2(C1HHt4W6dY`sizLPmVH^ zBfpx+Q%z(W%GaaRAs&k!BUY3sa~3QnU|Db4X%DEH>&5u|o<28EA#qrMSd!V}68PZbj_IA014r-2)PtT~N z7m2P@Y4t~e#7W78QvR`4@4)iYX#>tw-u*@VtVWM$BjFDvNyclnTj{iBjLOXpBGh9z z)A#6f#9|?jO~S<* zVyCPHAF+d2x&nAHxg=c8;Mf#E5D4bv=I7ysOCAk8ia5AIAWlILFOcsMMS|LE19-ul z0)hg(JOXff4B{jYwYIc^0r)|1DL0S@jz=lLfhTJ-35Q1#6Aq?5u14|?qK$)(kCzh+ z2J#C4IC!{uIr)M7Kpp@$5cr5_!95Fr1$hMEtlOgooHc@S1O9-K{)t!p1J3*tc6yxq zr^de{27vwm>fm@M#1;BD;eP|ybTfth!HY>LNI%YaGzKS};9pvfathMQ5GOdoXAY0w z8s_zfSkucD9{k_PmIl<)8omo&0A>j|SPF#`sj4n;*wp%wruthAF4S~$a)Og`k7;}a z;<$7kX*2_V@FUFz1aR~7a|-alb7lkpg8>G7ARzn`o>(IQp8&uB4Cdnmfw_6$pZp*I zKR0~NUjhI>4;<9{TlpXIf6w6N=H>+P@e4kJZg5Bc`V!#b;RM3-4>AG>fB*tK|4YNb3N=z<&UKpntH1|1U(0n;-N~K+H&e#3lrYx3bG-;nmvo^U9r8 zvf9vT621O6g0d`S38=T}`)P(!uOxcBlf{@|no?eouR~HDURy?phZQ98C7EH$7pGuE zrjNSufw9Za!reu$(`8hakIVX+Uu|`lVgi0S&CH}zbE=w>e-Dsxl+BH^2^`Ux5?r>| ze^`$imK;5xK#3mPFPy9V9fcQnw1}yb;@{I5gj)652(DdwI*`6Xpkn8z`aFa)X7r#3zVxgwJJ1F}$$MFdc9 zYd)B(2XE6;H(q>ys?x3}HtkB_!_)sXfKj#b`ZO7He0(zUinYTJQO)L^=Kr?!|Jl`# zCG}U~K2|KeyZ--6T*d*;D?e7`zY3W{{_nOnhrl}wUiNT267&a93g1>O$5#&4kBBqi zj}84t*LlJzLri#&@?*kV^{)%S2L|(i0TzIN$sP?oUI2%G$@su|N9P4Ltk&aNZbB mp#tFS?;l+4ABWE0oT)1e;sX0)LqK4D0XRC(Afqaa`Tqgqqk4V- literal 0 HcmV?d00001 diff --git a/tests/functional/model/run_model_test.py b/tests/functional/model/run_model_test.py index 6574732c..9af2ccc3 100644 --- a/tests/functional/model/run_model_test.py +++ b/tests/functional/model/run_model_test.py @@ -15,14 +15,13 @@ CACHE_FOLDER = ".cache" - def pytest_generate_tests(metafunc): if "llm_model" in metafunc.fixturenames: four_weeks_ago = datetime.now(timezone.utc) - timedelta(weeks=4) models = ModelFactory.list(function=Function.TEXT_GENERATION)["results"] predefined_models = [] - for predefined_model in ["Groq Llama 3 70B", "GPT-4o"]: + for predefined_model in ["GPT-4.1 Mini", "GPT-4o"]: predefined_models.extend( [ m @@ -323,6 +322,103 @@ def test_index_model_air_with_splitter(embedding_model, supplier_params): index_model.delete() +def test_index_model_with_txt_file(): + """Testing Index Model with local txt file input""" + from aixplain.factories import IndexFactory + from uuid import uuid4 + from aixplain.factories.index_factory.utils import AirParams + from pathlib import Path + + # Create test file path + test_file_path = Path(__file__).parent / "data" / "test_input.txt" + + # Create index with OpenAI Ada 002 for text processing + params = AirParams( + name=f"File Index {uuid4()}", description="Index for file processing", embedding_model=EmbeddingModel.OPENAI_ADA002 + ) + index_model = IndexFactory.create(params=params) + + try: + # Upsert the file + response = index_model.upsert(str(test_file_path)) + assert str(response.status) == "SUCCESS" + + # Verify the content was indexed + response = index_model.search("demo") + assert str(response.status) == "SUCCESS" + assert "🤖" in response.data, "Robot emoji should be present in the response" + + # Verify count + assert index_model.count() > 0 + + finally: + # Cleanup + index_model.delete() + + +def test_index_model_with_pdf_file(): + """Testing Index Model with PDF file input""" + from aixplain.factories import IndexFactory + from uuid import uuid4 + from aixplain.factories.index_factory.utils import AirParams + from pathlib import Path + + # Create test file path + test_file_path = Path(__file__).parent / "data" / "test_file_parser_input.pdf" + + # Create index with OpenAI Ada 002 for text processing + params = AirParams( + name=f"PDF Index {uuid4()}", description="Index for PDF processing", embedding_model=EmbeddingModel.OPENAI_ADA002 + ) + index_model = IndexFactory.create(params=params) + + try: + # Upsert the PDF file + response = index_model.upsert(str(test_file_path)) + assert str(response.status) == "SUCCESS" + + # Verify the content was indexed + response = index_model.search("document") + assert str(response.status) == "SUCCESS" + assert len(response.data) > 0 + + # Verify count + assert index_model.count() > 0 + + finally: + # Cleanup + index_model.delete() + + +def test_index_model_with_invalid_file(): + """Testing Index Model with invalid file input""" + from aixplain.factories import IndexFactory + from uuid import uuid4 + from aixplain.factories.index_factory.utils import AirParams + from pathlib import Path + + # Create non-existent file path + test_file_path = Path(__file__).parent / "data" / "nonexistent.pdf" + + # Create index with OpenAI Ada 002 for text processing + params = AirParams( + name=f"Invalid File Index {uuid4()}", + description="Index for invalid file testing", + embedding_model=EmbeddingModel.OPENAI_ADA002, + ) + index_model = IndexFactory.create(params=params) + + try: + # Attempt to upsert non-existent file + with pytest.raises(Exception) as e: + index_model.upsert(str(test_file_path)) + assert "does not exist" in str(e.value) + + finally: + # Cleanup + index_model.delete() + + def _test_records(): from aixplain.modules.model.record import Record from aixplain.enums import DataType diff --git a/tests/functional/team_agent/data/team_agent_test_end2end.json b/tests/functional/team_agent/data/team_agent_test_end2end.json index ed6437d2..1034057f 100644 --- a/tests/functional/team_agent/data/team_agent_test_end2end.json +++ b/tests/functional/team_agent/data/team_agent_test_end2end.json @@ -1,14 +1,14 @@ [ { "team_agent_name": "TEST Multi agent", - "llm_id": "6626a3a8c8f1d089790cf5a2", - "llm_name": "Groq Llama 3 70B", + "llm_id": "67fd9ddfef0365783d06e2ef", + "llm_name": "GPT-4.1 Mini", "query": "Who is the president of Brazil right now? Translate to pt and synthesize in audio", "agents": [ { "agent_name": "TEST Translation agent", - "llm_id": "6626a3a8c8f1d089790cf5a2", - "llm_name": "Groq Llama 3 70B", + "llm_id": "67fd9ddfef0365783d06e2ef", + "llm_name": "GPT-4.1 Mini", "model_tools": [ { "function": "translation", @@ -18,8 +18,8 @@ }, { "agent_name": "TEST Speech Synthesis agent", - "llm_id": "6626a3a8c8f1d089790cf5a2", - "llm_name": "Groq Llama 3 70B", + "llm_id": "67fd9ddfef0365783d06e2ef", + "llm_name": "GPT-4.1 Mini", "model_tools": [ { "function": "speech-synthesis", diff --git a/tests/functional/team_agent/evolver_test.py b/tests/functional/team_agent/evolver_test.py new file mode 100644 index 00000000..e920ec88 --- /dev/null +++ b/tests/functional/team_agent/evolver_test.py @@ -0,0 +1,141 @@ +import pytest +from aixplain.enums.function import Function +from aixplain.enums.supplier import Supplier +from aixplain.enums import ResponseStatus +from aixplain.factories.agent_factory import AgentFactory +from aixplain.factories.team_agent_factory import TeamAgentFactory +import time + + +team_dict = { + "team_agent_name": "Test Text Speech Team", + "llm_id": "6646261c6eb563165658bbb1", + "llm_name": "GPT4o", + "query": "Translate this text into Portuguese: 'This is a test'. Translate to pt and synthesize in audio", + "description": "You are a text translation and speech synthesizing agent. You will be provided a text in the source language and expected to translate and synthesize in the target language.", + "agents": [ + { + "agent_name": "Text Translation agent", + "llm_id": "6646261c6eb563165658bbb1", + "llm_name": "GPT4o", + "description": "## ROLE\nText Translator\n\n## GOAL\nTranslate the text supplied into the users desired language.\n\n## BACKSTORY\nYou are a text translation agent. You will be provided a text in the source language and expected to translate in the target language.", + "tasks": [ + { + "name": "Text translation", + "description": "Translate a text from source language (English) to target language (Portuguese)", + "expected_output": "target language text", + } + ], + "model_tools": [{"function": "translation", "supplier": "AWS"}], + }, + { + "agent_name": "Test Speech Synthesis agent", + "llm_id": "6646261c6eb563165658bbb1", + "llm_name": "GPT4o", + "description": "## ROLE\nSpeech Synthesizer\n\n## GOAL\nTranscribe the translated text into speech.\n\n## BACKSTORY\nYou are a speech synthesizing agent. You will be provided a text to synthesize into audio and return the audio link.", + "tasks": [ + { + "name": "Speech synthesis", + "description": "Synthesize a text from text to speech", + "expected_output": "audio link of the synthesized text", + "dependencies": ["Text translation"], + } + ], + "model_tools": [{"function": "speech_synthesis", "supplier": "Google"}], + }, + ], +} + + +def parse_tools(tools_info): + tools = [] + for tool in tools_info: + function_enum = Function[tool["function"].upper().replace(" ", "_")] + supplier_enum = Supplier[tool["supplier"].upper().replace(" ", "_")] + tools.append(AgentFactory.create_model_tool(function=function_enum, supplier=supplier_enum)) + return tools + + +def build_team_agent_from_json(team_config: dict): + agents_data = team_config["agents"] + tasks_data = team_config.get("tasks", []) + + agent_objs = [] + for agent_entry in agents_data: + agent_name = agent_entry["agent_name"] + agent_description = agent_entry["description"] + agent_llm_id = agent_entry.get("llm_id", None) + + agent_tasks = [] + for task in tasks_data: + task_name = task.get("task_name", "") + task_info = task + + if agent_name == task_info["agent"]: + task_obj = AgentFactory.create_task( + name=task_name.replace("_", " "), + description=task_info.get("description", ""), + expected_output=task_info.get("expected_output", ""), + dependencies=[t.replace("_", " ") for t in task_info.get("dependencies", [])], + ) + agent_tasks.append(task_obj) + + if "model_tools" in agent_entry: + agent_tools = parse_tools(agent_entry["model_tools"]) + else: + agent_tools = [] + + agent_obj = AgentFactory.create( + name=agent_name.replace("_", " "), + description=agent_description, + tools=agent_tools, + tasks=agent_tasks, + llm_id=agent_llm_id, + ) + agent_objs.append(agent_obj) + + return TeamAgentFactory.create( + name=team_config["team_agent_name"], + agents=agent_objs, + description=team_config["description"], + llm_id=team_config.get("llm_id", None), + inspectors=[], + use_mentalist=True, + ) + + +@pytest.fixture +def team_agent(): + return build_team_agent_from_json(team_dict) + + +def test_evolver_output(team_agent): + response = team_agent.evolve_async() + poll_url = response["url"] + result = team_agent.poll(poll_url) + + while result.status == ResponseStatus.IN_PROGRESS: + time.sleep(30) + result = team_agent.poll(poll_url) + + assert result["status"] == ResponseStatus.SUCCESS, "Final result should have a 'SUCCESS' status" + assert "evolved_agent" in result["data"], "Data should contain 'evolved_agent'" + assert "evaluation_report" in result["data"], "Data should contain 'evaluation_report'" + assert "criteria" in result["data"], "Data should contain 'criteria'" + assert "archive" in result["data"], "Data should contain 'archive'" + assert isinstance(result.data["evolved_agent"], type(team_agent)), "Evolved agent should be an instance of the team agent" + + +def test_evolver_with_custom_llm_id(team_agent): + """Test evolver functionality with custom LLM ID""" + from aixplain.factories.model_factory import ModelFactory + custom_llm_id = "6646261c6eb563165658bbb1" # GPT-4o ID + model = ModelFactory.get(model_id=custom_llm_id) + + # Test with llm parameter + response = team_agent.evolve(llm=model) + + assert response is not None + assert response.data["evolved_agent"] is not None + assert response.data["evolved_agent"].llm_id == custom_llm_id + assert isinstance(response.data["evolved_agent"], type(team_agent)), "Evolved agent should be an instance of the team agent" diff --git a/tests/functional/team_agent/inspector_functional_test.py b/tests/functional/team_agent/inspector_functional_test.py index 73536136..08c6df58 100644 --- a/tests/functional/team_agent/inspector_functional_test.py +++ b/tests/functional/team_agent/inspector_functional_test.py @@ -12,10 +12,17 @@ import pytest from aixplain import aixplain_v2 as v2 -from aixplain.factories import AgentFactory, TeamAgentFactory +from aixplain.factories import AgentFactory, TeamAgentFactory, ModelFactory from aixplain.enums.asset_status import AssetStatus from aixplain.modules.team_agent import InspectorTarget -from aixplain.modules.team_agent.inspector import Inspector, InspectorPolicy +from aixplain.modules.team_agent.inspector import ( + Inspector, + InspectorPolicy, + InspectorAction, + InspectorOutput, +) +from aixplain.modules.model.response import ModelResponse +from aixplain.enums.response_status import ResponseStatus from tests.functional.team_agent.test_utils import ( RUN_FILE, @@ -26,19 +33,83 @@ ) +# Define callable policy functions at module level for proper serialization +def process_response( + model_response: ModelResponse, input_content: str +) -> InspectorOutput: + """Basic callable policy function for testing.""" + if ( + "error" in model_response.error_message.lower() + or "invalid" in model_response.data.lower() + ): + return InspectorOutput( + critiques="Error or invalid content detected", + content_edited="", + action=InspectorAction.ABORT, + ) + elif "warning" in model_response.data.lower(): + return InspectorOutput( + critiques="Warning detected", + content_edited="", + action=InspectorAction.RERUN, + ) + return InspectorOutput( + critiques="No issues detected", + content_edited="", + action=InspectorAction.CONTINUE, + ) + + +def process_response_abort( + model_response: ModelResponse, input_content: str +) -> InspectorOutput: + """Callable policy function that aborts on specific content.""" + abort_keywords = ["dangerous", "harmful", "illegal", "inappropriate"] + for keyword in abort_keywords: + if keyword in model_response.data.lower(): + return InspectorOutput( + critiques=f"Abort keyword '{keyword}' detected", + content_edited="", + action=InspectorAction.ABORT, + ) + return InspectorOutput( + critiques="No abort keywords detected", + content_edited="", + action=InspectorAction.CONTINUE, + ) + + +def process_response_rerun( + model_response: ModelResponse, input_content: str +) -> InspectorOutput: + """Callable policy function that triggers rerun on specific conditions.""" + if ( + len(model_response.data.strip()) < 10 + or "placeholder" in model_response.data.lower() + ): + return InspectorOutput( + critiques="Content too short or contains placeholder", + content_edited="", + action=InspectorAction.RERUN, + ) + return InspectorOutput( + critiques="Content is acceptable", + content_edited="", + action=InspectorAction.CONTINUE, + ) + + @pytest.fixture(scope="function") def delete_agents_and_team_agents(): - for team_agent in TeamAgentFactory.list()["results"]: - team_agent.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + from tests.test_deletion_utils import safe_delete_all_agents_and_team_agents + + # Clean up before test + safe_delete_all_agents_and_team_agents() yield True - for team_agent in TeamAgentFactory.list()["results"]: - team_agent.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + # Clean up after test + safe_delete_all_agents_and_team_agents() @pytest.fixture(scope="module", params=read_data(RUN_FILE)) @@ -46,12 +117,18 @@ def run_input_map(request): return request.param -def verify_inspector_steps(steps: Dict, inspector_names: List[str], inspector_targets: List[InspectorTarget]) -> None: +def verify_inspector_steps( + steps: Dict, inspector_names: List[str], inspector_targets: List[InspectorTarget] +) -> None: """Helper function to verify inspector steps""" # Count occurrences of each inspector inspector_counts = {} for inspector_name in inspector_names: - inspector_steps = [step for step in steps if inspector_name.lower() in step.get("agent", "").lower()] + inspector_steps = [ + step + for step in steps + if inspector_name.lower() in step.get("agent", "").lower() + ] inspector_counts[inspector_name] = len(inspector_steps) # Verify all inspectors are present and have the same number of steps @@ -63,33 +140,53 @@ def verify_inspector_steps(steps: Dict, inspector_names: List[str], inspector_ta first_count = next(iter(inspector_counts.values())) for inspector, count in inspector_counts.items(): assert count > 0, f"Inspector {inspector} has no steps" - assert count == first_count, f"Inspector {inspector} has {count} steps, expected {first_count}" + assert ( + count == first_count + ), f"Inspector {inspector} has {count} steps, expected {first_count}" print(f"Inspector {inspector} has {count} steps") # If OUTPUT is in inspector_targets, verify there are inspector steps after response generator if InspectorTarget.OUTPUT in inspector_targets: - response_generator_steps = [step for step in steps if "response_generator" in step.get("agent", "").lower()] - assert len(response_generator_steps) == 1, "Expected exactly one response_generator step" + response_generator_steps = [ + step + for step in steps + if "response_generator" in step.get("agent", "").lower() + ] + assert ( + len(response_generator_steps) == 1 + ), "Expected exactly one response_generator step" response_generator_index = steps.index(response_generator_steps[0]) inspector_steps_after = [ step for step in steps[response_generator_index + 1 :] - if any(inspector_name.lower() in step.get("agent", "").lower() for inspector_name in inspector_names) + if any( + inspector_name.lower() in step.get("agent", "").lower() + for inspector_name in inspector_names + ) ] - assert len(inspector_steps_after) > 0, "No inspector steps found after response generator step" - print(f"Found {len(inspector_steps_after)} inspector steps after response generator") + assert ( + len(inspector_steps_after) > 0 + ), "No inspector steps found after response generator step" + print( + f"Found {len(inspector_steps_after)} inspector steps after response generator" + ) # Verify inspector steps are the last steps last_steps = steps[response_generator_index + 1 :] assert all( - any(inspector_name.lower() in step.get("agent", "").lower() for inspector_name in inspector_names) + any( + inspector_name.lower() in step.get("agent", "").lower() + for inspector_name in inspector_names + ) for step in last_steps ), "Not all steps after response generator are inspector steps" @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_warn_inspector(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_warn_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with warn policy inspector that provides feedback but continues execution""" assert delete_agents_and_team_agents @@ -112,6 +209,7 @@ def test_team_agent_with_warn_inspector(run_input_map, delete_agents_and_team_ag inspectors=[inspector], inspector_targets=[InspectorTarget.STEPS], ) + query = "What is the translation of 'Hello' to Portuguese?" assert team_agent is not None assert team_agent.status == AssetStatus.DRAFT @@ -123,12 +221,11 @@ def test_team_agent_with_warn_inspector(run_input_map, delete_agents_and_team_ag assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data=query) assert response is not None assert response["completed"] is True assert response["status"].lower() == "success" - # Check for inspector steps if "intermediate_steps" in response["data"]: steps = response["data"]["intermediate_steps"] @@ -136,14 +233,18 @@ def test_team_agent_with_warn_inspector(run_input_map, delete_agents_and_team_ag verify_response_generator(steps) # Verify inspector runs and execution continues - inspector_steps = [step for step in steps if "warn_inspector" in step.get("agent", "").lower()] + inspector_steps = [ + step for step in steps if "warn_inspector" in step.get("agent", "").lower() + ] assert len(inspector_steps) > 0, "Warn inspector should run at least once" team_agent.delete() @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_adaptive_inspector(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_adaptive_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with adaptive inspector that runs multiple times""" assert delete_agents_and_team_agents @@ -153,7 +254,9 @@ def test_team_agent_with_adaptive_inspector(run_input_map, delete_agents_and_tea inspector = Inspector( name="adaptive_inspector", model_id=run_input_map["llm_id"], - model_params={"prompt": "Check if the steps are valid and provide feedback for improvement"}, + model_params={ + "prompt": "Check if the steps are valid and provide feedback for improvement" + }, policy=InspectorPolicy.ADAPTIVE, ) @@ -177,7 +280,7 @@ def test_team_agent_with_adaptive_inspector(run_input_map, delete_agents_and_tea assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") assert response is not None assert response["completed"] is True @@ -191,14 +294,20 @@ def test_team_agent_with_adaptive_inspector(run_input_map, delete_agents_and_tea verify_response_generator(steps) # Verify inspector runs multiple times - inspector_steps = [step for step in steps if "adaptive_inspector" in step.get("agent", "").lower()] + inspector_steps = [ + step + for step in steps + if "adaptive_inspector" in step.get("agent", "").lower() + ] assert len(inspector_steps) > 1, "Adaptive inspector should run more than once" team_agent.delete() @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_abort_inspector(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_abort_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with abort inspector that stops execution on critique""" assert delete_agents_and_team_agents @@ -232,12 +341,15 @@ def test_team_agent_with_abort_inspector(run_input_map, delete_agents_and_team_a assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") assert response is not None assert response["completed"] is True assert response["status"].lower() == "success" - assert "I couldn't provide an answer because the inspector detected issues" in response["data"]["output"] + assert ( + "I couldn't provide an answer because the inspector detected issues" + in response["data"]["output"] + ) # Check for inspector steps if "intermediate_steps" in response["data"]: @@ -246,10 +358,16 @@ def test_team_agent_with_abort_inspector(run_input_map, delete_agents_and_team_a verify_response_generator(steps) # Verify response generator comes right after first inspector critique - inspector_steps = [step for step in steps if "abort_inspector" in step.get("agent", "").lower()] + inspector_steps = [ + step for step in steps if "abort_inspector" in step.get("agent", "").lower() + ] assert len(inspector_steps) == 1, "Abort inspector should only run once" response_generator_index = steps.index( - [step for step in steps if "response_generator" in step.get("agent", "").lower()][0] + [ + step + for step in steps + if "response_generator" in step.get("agent", "").lower() + ][0] ) assert ( response_generator_index == steps.index(inspector_steps[0]) + 1 @@ -259,7 +377,9 @@ def test_team_agent_with_abort_inspector(run_input_map, delete_agents_and_team_a @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_output_inspector(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_output_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with output inspector that runs after response generator""" assert delete_agents_and_team_agents @@ -293,7 +413,7 @@ def test_team_agent_with_output_inspector(run_input_map, delete_agents_and_team_ assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") assert response is not None assert response["completed"] is True @@ -306,14 +426,25 @@ def test_team_agent_with_output_inspector(run_input_map, delete_agents_and_team_ verify_response_generator(steps) # Verify critiques are in response data - assert "critiques" in response["data"] - assert response["data"]["critiques"], "No critiques found in response data" + output_inspector_steps = [ + step + for step in steps + if "output_inspector" in step.get("agent", "").lower() + ] + assert ( + len(output_inspector_steps) > 0 + ), "There should be one output inspector step" + assert ( + "critiques" in output_inspector_steps[0]["thought"].lower() + ), "No critiques found in output inspector step" team_agent.delete() @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_multiple_inspector_targets(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_multiple_inspector_targets( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with inspectors targeting both steps and output""" assert delete_agents_and_team_agents @@ -353,7 +484,7 @@ def test_team_agent_with_multiple_inspector_targets(run_input_map, delete_agents assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") assert response is not None assert response["completed"] is True @@ -362,18 +493,102 @@ def test_team_agent_with_multiple_inspector_targets(run_input_map, delete_agents # Check for inspector steps if "intermediate_steps" in response["data"]: steps = response["data"]["intermediate_steps"] - verify_inspector_steps(steps, ["steps_inspector", "output_inspector"], [InspectorTarget.STEPS, InspectorTarget.OUTPUT]) + verify_inspector_steps( + steps, + ["steps_inspector", "output_inspector"], + [InspectorTarget.STEPS, InspectorTarget.OUTPUT], + ) verify_response_generator(steps) - # Verify critiques are in response data - assert "critiques" in response["data"] - assert response["data"]["critiques"], "No critiques found in response data" + # Critiques should be present and non-empty in the inspector step's 'thought' + steps_inspector_steps = [ + step for step in steps if "steps_inspector" in step.get("agent", "").lower() + ] + output_inspector_steps = [ + step + for step in steps + if "output_inspector" in step.get("agent", "").lower() + ] + assert ( + len(steps_inspector_steps) >= 1 + ), "There should be one steps inspector step" + assert ( + "critiques" in steps_inspector_steps[0]["thought"].lower() + ), "No critiques found in steps inspector step" + assert ( + len(output_inspector_steps) >= 1 + ), "There should be one output inspector step" + assert ( + "critiques" in output_inspector_steps[0]["thought"].lower() + ), "No critiques found in output inspector step" team_agent.delete() @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_input_inspector(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_steps_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): + """Test team agent with steps inspector that runs before any steps are executed""" + assert delete_agents_and_team_agents + + agents = create_agents_from_input_map(run_input_map) + + # Create inspector with warn policy + inspector = Inspector( + name="steps_inspector", + model_id=run_input_map["llm_id"], + model_params={"prompt": "Check if the steps are valid and provide feedback"}, + policy=InspectorPolicy.WARN, + ) + + # Create team agent with steps inspector + team_agent = create_team_agent( + TeamAgentFactory, + agents, + run_input_map, + use_mentalist=True, + inspectors=[inspector], + inspector_targets=[InspectorTarget.STEPS], + ) + + assert team_agent is not None + assert team_agent.status == AssetStatus.DRAFT + + # deploy team agent + team_agent.deploy() + team_agent = TeamAgentFactory.get(team_agent.id) + assert team_agent is not None + assert team_agent.status == AssetStatus.ONBOARDED + + # Run the team agent + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") + + assert response is not None + assert response["completed"] is True + assert response["status"].lower() == "success" + + # Check for inspector steps + if "intermediate_steps" in response["data"]: + steps = response["data"]["intermediate_steps"] + verify_inspector_steps(steps, ["steps_inspector"], [InspectorTarget.STEPS]) + verify_response_generator(steps) + + # Verify inspector runs and execution continues + inspector_steps = [ + step for step in steps if "steps_inspector" in step.get("agent", "").lower() + ] + assert len(inspector_steps) > 0, "Steps inspector should run at least once" + assert ( + "critiques" in inspector_steps[0]["thought"].lower() + ), "No critiques found in steps inspector step" + team_agent.delete() + + +@pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) +def test_team_agent_with_input_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with input inspector that runs before any steps are executed""" assert delete_agents_and_team_agents @@ -407,7 +622,7 @@ def test_team_agent_with_input_inspector(run_input_map, delete_agents_and_team_a assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") assert response is not None assert response["completed"] is True @@ -420,14 +635,18 @@ def test_team_agent_with_input_inspector(run_input_map, delete_agents_and_team_a verify_response_generator(steps) # Verify inspector runs and execution continues - inspector_steps = [step for step in steps if "input_inspector" in step.get("agent", "").lower()] + inspector_steps = [ + step for step in steps if "input_inspector" in step.get("agent", "").lower() + ] assert len(inspector_steps) > 0, "Input inspector should run at least once" team_agent.delete() @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_input_abort_inspector(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_input_abort_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with input inspector (ABORT policy): if critiques are non-empty, response_generator is called immediately after inspector.""" assert delete_agents_and_team_agents @@ -437,7 +656,9 @@ def test_team_agent_with_input_abort_inspector(run_input_map, delete_agents_and_ inspector = Inspector( name="input_abort_inspector", model_id=run_input_map["llm_id"], - model_params={"prompt": "Always find issues and provide negative feedback on input"}, + model_params={ + "prompt": "Always find issues and provide negative feedback on input" + }, policy=InspectorPolicy.ABORT, ) @@ -461,7 +682,7 @@ def test_team_agent_with_input_abort_inspector(run_input_map, delete_agents_and_ assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") assert response is not None assert response["completed"] is True @@ -470,21 +691,32 @@ def test_team_agent_with_input_abort_inspector(run_input_map, delete_agents_and_ # Check for inspector steps if "intermediate_steps" in response["data"]: steps = response["data"]["intermediate_steps"] - verify_inspector_steps(steps, ["input_abort_inspector"], [InspectorTarget.INPUT]) + verify_inspector_steps( + steps, ["input_abort_inspector"], [InspectorTarget.INPUT] + ) verify_response_generator(steps) # Critiques should be present and non-empty in the inspector step's 'thought' - inspector_steps = [step for step in steps if "input_abort_inspector" in step.get("agent", "").lower()] + inspector_steps = [ + step + for step in steps + if "input_abort_inspector" in step.get("agent", "").lower() + ] assert len(inspector_steps) == 1, "Input abort inspector should only run once" inspector_thought = inspector_steps[0].get("thought", "") assert inspector_thought, "No thought found in inspector step" assert ( - "critique" in inspector_thought.lower() or len(inspector_thought.strip()) > 0 + "critique" in inspector_thought.lower() + or len(inspector_thought.strip()) > 0 ), "Inspector step's thought does not contain critique or is empty" # Inspector should run once, then response_generator should come right after response_generator_index = next( - (i for i, step in enumerate(steps) if "response_generator" in step.get("agent", "").lower()), + ( + i + for i, step in enumerate(steps) + if "response_generator" in step.get("agent", "").lower() + ), None, ) assert response_generator_index is not None, "No response_generator step found" @@ -496,7 +728,9 @@ def test_team_agent_with_input_abort_inspector(run_input_map, delete_agents_and_ @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) -def test_team_agent_with_input_adaptive_inspector(run_input_map, delete_agents_and_team_agents, TeamAgentFactory): +def test_team_agent_with_input_adaptive_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): """Test team agent with input inspector (ADAPTIVE policy): query_manager step exists more than once and mentalist creates a plan for the revised query (output of the last query_manager).""" assert delete_agents_and_team_agents @@ -506,7 +740,9 @@ def test_team_agent_with_input_adaptive_inspector(run_input_map, delete_agents_a inspector = Inspector( name="input_adaptive_inspector", model_id=run_input_map["llm_id"], - model_params={"prompt": "If the input is not valid, suggest a revised query and critique."}, + model_params={ + "prompt": "If the input is not valid, suggest a revised query and critique." + }, policy=InspectorPolicy.ADAPTIVE, ) @@ -530,7 +766,7 @@ def test_team_agent_with_input_adaptive_inspector(run_input_map, delete_agents_a assert team_agent.status == AssetStatus.ONBOARDED # Run the team agent - response = team_agent.run(data=run_input_map["query"]) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") assert response is not None assert response["completed"] is True @@ -539,12 +775,18 @@ def test_team_agent_with_input_adaptive_inspector(run_input_map, delete_agents_a # Check for inspector steps if "intermediate_steps" in response["data"]: steps = response["data"]["intermediate_steps"] - verify_inspector_steps(steps, ["input_adaptive_inspector"], [InspectorTarget.INPUT]) + verify_inspector_steps( + steps, ["input_adaptive_inspector"], [InspectorTarget.INPUT] + ) verify_response_generator(steps) # There should be more than one query_manager step - query_manager_steps = [step for step in steps if "query_manager" in step.get("agent", "").lower()] - assert len(query_manager_steps) > 1, "There should be more than one query_manager step for adaptive input inspector" + query_manager_steps = [ + step for step in steps if "query_manager" in step.get("agent", "").lower() + ] + assert ( + len(query_manager_steps) > 1 + ), "There should be more than one query_manager step for adaptive input inspector" # The last query_manager's output should be contained in the mentalist's input last_query_manager = query_manager_steps[-1] @@ -552,10 +794,283 @@ def test_team_agent_with_input_adaptive_inspector(run_input_map, delete_agents_a assert revised_query, "No output found in the last query_manager step" # There must be only one mentalist step - mentalist_steps = [step for step in steps if "mentalist" in step.get("agent", "").lower()] + mentalist_steps = [ + step for step in steps if "mentalist" in step.get("agent", "").lower() + ] mentalist_input = mentalist_steps[0].get("input", None) assert ( mentalist_input and revised_query in mentalist_input ), "The mentalist input does not contain the revised query from the last query_manager" team_agent.delete() + + +@pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) +def test_team_agent_with_callable_policy( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): + """Comprehensive test of callable policy functionality with team agent integration""" + assert delete_agents_and_team_agents + + agents = create_agents_from_input_map(run_input_map) + + # Test 1: Create inspector with callable policy + inspector = Inspector( + name="callable_inspector", + model_id=run_input_map["llm_id"], + model_params={"prompt": "Check if the steps are valid and provide feedback"}, + policy=process_response, # Using module-level callable policy + ) + + # Test 2: Verify the inspector was created correctly + assert inspector.name == "callable_inspector" + assert callable(inspector.policy) + assert inspector.policy.__name__ == "process_response" + + # Test 3: Verify the callable policy works correctly + result1 = inspector.policy( + ModelResponse( + status=ResponseStatus.FAILED, + error_message="This is an error message", + data="input", + ), + "input", + ) + assert result1.action == InspectorAction.ABORT + + result2 = inspector.policy( + ModelResponse( + status=ResponseStatus.SUCCESS, + data="This is a warning message", + error_message="", + ), + "input", + ) + assert result2.action == InspectorAction.RERUN + + result3 = inspector.policy( + ModelResponse( + status=ResponseStatus.SUCCESS, + data="This is a normal message", + error_message="", + ), + "input", + ) + assert result3.action == InspectorAction.CONTINUE + + # Test 4: Create team agent with callable policy inspector + team_agent = create_team_agent( + TeamAgentFactory, + agents, + run_input_map, + use_mentalist=True, + inspectors=[inspector], + inspector_targets=[InspectorTarget.STEPS], + ) + + assert team_agent is not None + assert team_agent.status == AssetStatus.DRAFT + + # Test 5: Deploy team agent (backend properly handles callable policies) + team_agent.deploy() + team_agent = TeamAgentFactory.get(team_agent.id) + assert team_agent is not None + assert team_agent.status == AssetStatus.ONBOARDED + + # Test 6: Verify backend properly handles callable policies + assert len(team_agent.inspectors) == 1 + backend_inspector = team_agent.inspectors[0] + assert backend_inspector.name == "callable_inspector" + # Backend should properly handle callable policies, not fall back to ADAPTIVE + assert callable(backend_inspector.policy) + assert backend_inspector.policy.__name__ == "process_response" + + # Verify the backend-preserved callable policy still works correctly + assert ( + backend_inspector.policy( + ModelResponse( + status=ResponseStatus.FAILED, + error_message="This is an error message", + data="input", + ), + "input", + ).action + == InspectorAction.ABORT + ) + assert ( + backend_inspector.policy( + ModelResponse( + status=ResponseStatus.SUCCESS, + data="This is a warning message", + error_message="", + ), + "input", + ).action + == InspectorAction.RERUN + ) + assert ( + backend_inspector.policy( + ModelResponse( + status=ResponseStatus.SUCCESS, + data="This is a normal message", + error_message="", + ), + "input", + ).action + == InspectorAction.CONTINUE + ) + + team_agent.delete() + + +@pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) +def test_inspector_action_verification( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): + """Test that inspector actions are properly executed and their results are verified""" + assert delete_agents_and_team_agents + + agents = create_agents_from_input_map(run_input_map) + + # Create a custom callable policy that always returns ABORT + def process_response( + model_response: ModelResponse, input_content: str + ) -> InspectorOutput: + """Custom policy that always returns ABORT for safety testing.""" + return InspectorOutput( + critiques="Safety check", content_edited="", action=InspectorAction.ABORT + ) + + # Create inspector with custom callable policy + inspector = Inspector( + name="custom_abort_inspector", + model_id=run_input_map["llm_id"], + model_params={"prompt": "You are a safety inspector."}, + policy=process_response, + ) + + # Create team agent with the custom policy inspector + team_agent = create_team_agent( + TeamAgentFactory, + agents, + run_input_map, + use_mentalist=True, + inspectors=[inspector], + inspector_targets=[InspectorTarget.STEPS], + ) + + # Deploy and run team agent + team_agent.deploy() + team_agent = TeamAgentFactory.get(team_agent.id) + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") + + assert response is not None + assert response["completed"] is True + assert response["status"].lower() == "success" + + # Extract steps from response + steps = ( + getattr(response.data, "intermediate_steps", []) + if hasattr(response, "data") + else [] + ) + + # Find inspector steps + inspector_steps = [ + step for step in steps if "inspector" in step.get("agent", "").lower() + ] + + # If no inspector steps found, backend may not be using custom policies + if not inspector_steps: + print("No inspector steps found - backend may not be using custom policies") + team_agent.delete() + return + + # Verify inspector executed and took ABORT action + inspector_step = inspector_steps[0] + assert ( + inspector_step.get("action") == "abort" + ), "Inspector should have returned ABORT" + + # Verify response generator ran after inspector + response_generator_steps = [ + step for step in steps if "response_generator" in step.get("agent", "").lower() + ] + assert ( + len(response_generator_steps) == 1 + ), "Response generator should run exactly once after ABORT" + + team_agent.delete() + + +@pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) +def test_team_agent_with_utility_inspector( + run_input_map, delete_agents_and_team_agents, TeamAgentFactory +): + """Test team agent with a Utility model as inspector""" + assert delete_agents_and_team_agents + + agents = create_agents_from_input_map(run_input_map) + + def lowercase_inspector(content: str) -> bool: + if content.islower(): + return "" + else: + return "Content is not all lowercase. There are uppercase characters in the content." + + utility_model = ModelFactory.create_utility_model( + name="Lowercase Inspector Test", + description="Inspect the content of the response. If the content is not all lowercase, provide feedback.'", + code=lowercase_inspector, + ) + utility_model.deploy() + + utility_model_id = utility_model.id + inspector = Inspector( + name="utility_inspector", + model_id=utility_model_id, + policy=InspectorPolicy.WARN, + ) + + # Create team agent with steps inspector + team_agent = create_team_agent( + TeamAgentFactory, + agents, + run_input_map, + use_mentalist=True, + inspectors=[inspector], + inspector_targets=[InspectorTarget.STEPS], + ) + + assert team_agent is not None + assert team_agent.status == AssetStatus.DRAFT + + # deploy team agent + team_agent.deploy() + team_agent = TeamAgentFactory.get(team_agent.id) + assert team_agent is not None + assert team_agent.status == AssetStatus.ONBOARDED + + # Run the team agent + response = team_agent.run(data="What is the translation of 'Hello' to Portuguese?") + + assert response is not None + assert response["completed"] is True + assert response["status"].lower() == "success" + + # Check for inspector steps + if "intermediate_steps" in response["data"]: + steps = response["data"]["intermediate_steps"] + verify_inspector_steps(steps, ["utility_inspector"], [InspectorTarget.STEPS]) + verify_response_generator(steps) + + # Verify inspector runs and execution continues + inspector_steps = [ + step + for step in steps + if "utility_inspector" in step.get("agent", "").lower() + ] + assert len(inspector_steps) > 0, "Utility inspector should run at least once" + + utility_model.delete() + team_agent.delete() diff --git a/tests/functional/team_agent/team_agent_functional_test.py b/tests/functional/team_agent/team_agent_functional_test.py index a9850954..c3488333 100644 --- a/tests/functional/team_agent/team_agent_functional_test.py +++ b/tests/functional/team_agent/team_agent_functional_test.py @@ -40,17 +40,15 @@ @pytest.fixture(scope="function") def delete_agents_and_team_agents(): - for team_agent in TeamAgentFactory.list()["results"]: - team_agent.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + from tests.test_deletion_utils import safe_delete_all_agents_and_team_agents + + # Clean up before test + safe_delete_all_agents_and_team_agents() yield True - for team_agent in TeamAgentFactory.list()["results"]: - team_agent.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + # Clean up after test + safe_delete_all_agents_and_team_agents() @pytest.fixture(scope="module", params=read_data(RUN_FILE)) @@ -87,7 +85,6 @@ def test_end2end(run_input_map, delete_agents_and_team_agents, TeamAgentFactory) assert response["completed"] is True assert response["status"].lower() == "success" assert "data" in response - assert response["data"]["session_id"] is None assert response["data"]["output"] is not None team_agent.delete() @@ -95,10 +92,8 @@ def test_end2end(run_input_map, delete_agents_and_team_agents, TeamAgentFactory) @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) def test_draft_team_agent_update(run_input_map, TeamAgentFactory): - for team in TeamAgentFactory.list()["results"]: - team.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + from tests.test_deletion_utils import safe_delete_all_agents_and_team_agents + safe_delete_all_agents_and_team_agents() agents = create_agents_from_input_map(run_input_map, deploy=False) team_agent = create_team_agent( @@ -120,10 +115,8 @@ def test_draft_team_agent_update(run_input_map, TeamAgentFactory): @pytest.mark.parametrize("TeamAgentFactory", [TeamAgentFactory, v2.TeamAgent]) def test_fail_non_existent_llm(run_input_map, TeamAgentFactory): - for team in TeamAgentFactory.list()["results"]: - team.delete() - for agent in AgentFactory.list()["results"]: - agent.delete() + from tests.test_deletion_utils import safe_delete_all_agents_and_team_agents + safe_delete_all_agents_and_team_agents() agents = create_agents_from_input_map(run_input_map, deploy=False) @@ -308,7 +301,7 @@ def test_team_agent_with_instructions(delete_agents_and_team_agents): instructions="Use only 'Agent 2' to solve the tasks.", llm_id="6646261c6eb563165658bbb1", use_mentalist=True, - use_inspector=False, + inspectors=[], ) response = team_agent.run(data="Translate 'cat' to Portuguese") @@ -425,7 +418,7 @@ class Response(BaseModel): description="Team agent", llm_id="6646261c6eb563165658bbb1", use_mentalist=False, - use_inspector=False, + inspectors=[], ) # Run the team agent @@ -506,7 +499,7 @@ def test_team_agent_with_slack_connector(): description="Team agent", llm_id="6646261c6eb563165658bbb1", use_mentalist=False, - use_inspector=False, + inspectors=[], ) response = team_agent.run( diff --git a/tests/test_deletion_utils.py b/tests/test_deletion_utils.py new file mode 100644 index 00000000..42a1f74d --- /dev/null +++ b/tests/test_deletion_utils.py @@ -0,0 +1,126 @@ +""" +Utility functions for safely deleting agents and team agents in tests. + +This module provides helper functions that delete agents by ID without +building full objects, avoiding issues with missing model dependencies. +""" + +from typing import List, Dict, Any +from aixplain.utils import config +from aixplain.utils.request_utils import _request_with_retry +from urllib.parse import urljoin + + +def get_team_agent_ids() -> List[str]: + """ + Get list of team agent IDs without building full objects. + + Returns: + List[str]: List of team agent IDs, empty list if error occurs + """ + try: + url = urljoin(config.BACKEND_URL, "sdk/agent-communities") + headers = {"x-api-key": config.TEAM_API_KEY, "Content-Type": "application/json"} + r = _request_with_retry("get", url, headers=headers) + + if 200 <= r.status_code < 300: + team_agents_data = r.json() + return [ta.get('id') for ta in team_agents_data if ta.get('id')] + else: + print(f"Warning: Failed to list team agents: HTTP {r.status_code}") + return [] + except Exception as e: + print(f"Warning: Failed to list team agents: {e}") + return [] + + +def get_agent_ids() -> List[str]: + """ + Get list of agent IDs without building full objects. + + Returns: + List[str]: List of agent IDs, empty list if error occurs + """ + try: + url = urljoin(config.BACKEND_URL, "sdk/agents") + headers = {"x-api-key": config.TEAM_API_KEY, "Content-Type": "application/json"} + r = _request_with_retry("get", url, headers=headers) + + if 200 <= r.status_code < 300: + agents_data = r.json() + return [agent.get('id') for agent in agents_data if agent.get('id')] + else: + print(f"Warning: Failed to list agents: HTTP {r.status_code}") + return [] + except Exception as e: + print(f"Warning: Failed to list agents: {e}") + return [] + + +def delete_team_agent_by_id(team_agent_id: str) -> bool: + """ + Delete a team agent by ID. + + Args: + team_agent_id: The ID of the team agent to delete + + Returns: + bool: True if successful, False otherwise + """ + try: + url = urljoin(config.BACKEND_URL, f"sdk/agent-communities/{team_agent_id}") + headers = {"x-api-key": config.TEAM_API_KEY, "Content-Type": "application/json"} + r = _request_with_retry("delete", url, headers=headers) + + if r.status_code == 200: + return True + else: + print(f"Warning: Failed to delete team agent {team_agent_id}: HTTP {r.status_code}") + return False + except Exception as e: + print(f"Warning: Failed to delete team agent {team_agent_id}: {e}") + return False + + +def delete_agent_by_id(agent_id: str) -> bool: + """ + Delete an agent by ID. + + Args: + agent_id: The ID of the agent to delete + + Returns: + bool: True if successful, False otherwise + """ + try: + url = urljoin(config.BACKEND_URL, f"sdk/agents/{agent_id}") + headers = {"x-api-key": config.TEAM_API_KEY, "Content-Type": "application/json"} + r = _request_with_retry("delete", url, headers=headers) + + if r.status_code == 200: + return True + else: + print(f"Warning: Failed to delete agent {agent_id}: HTTP {r.status_code}") + return False + except Exception as e: + print(f"Warning: Failed to delete agent {agent_id}: {e}") + return False + + +def safe_delete_all_agents_and_team_agents(): + """ + Safely delete all agents and team agents. + + This function deletes team agents first (since agents might be used by team agents), + then deletes individual agents. It handles errors gracefully and continues + processing even if some deletions fail. + """ + # Delete team agents first + team_agent_ids = get_team_agent_ids() + for team_agent_id in team_agent_ids: + delete_team_agent_by_id(team_agent_id) + + # Delete agents + agent_ids = get_agent_ids() + for agent_id in agent_ids: + delete_agent_by_id(agent_id) diff --git a/tests/unit/agent/agent_factory_utils_test.py b/tests/unit/agent/agent_factory_utils_test.py index 5c7fbb77..89c1b695 100644 --- a/tests/unit/agent/agent_factory_utils_test.py +++ b/tests/unit/agent/agent_factory_utils_test.py @@ -10,7 +10,7 @@ from aixplain.modules.agent.tool.custom_python_code_tool import CustomPythonCodeTool from aixplain.modules.agent.tool.sql_tool import SQLTool from aixplain.modules.agent import Agent -from aixplain.modules.agent.agent_task import AgentTask +from aixplain.modules.agent.agent_task import WorkflowTask from aixplain.factories import ModelFactory, PipelineFactory import os @@ -50,7 +50,13 @@ def mock_tools(): "tool_dict,expected_error", [ pytest.param( - {"type": "model", "supplier": "aixplain", "version": "1.0", "assetId": "test_model", "description": "Test model"}, + { + "type": "model", + "supplier": "aixplain", + "version": "1.0", + "assetId": "test_model", + "description": "Test model", + }, "Function is required for model tools", id="missing_function", ), @@ -124,19 +130,30 @@ def test_build_tool_error_cases(tool_dict, expected_error): id="model_tool_with_params", ), pytest.param( - {"type": "pipeline", "description": "Test pipeline", "assetId": "test_pipeline"}, + { + "type": "pipeline", + "description": "Test pipeline", + "assetId": "test_pipeline", + }, PipelineTool, {"description": "Test pipeline", "pipeline": "test_pipeline"}, id="pipeline_tool", ), pytest.param( - {"type": "utility", "description": "Test utility", "utilityCode": "print('Hello World')"}, + { + "type": "utility", + "description": "Test utility", + "utilityCode": "print('Hello World')", + }, CustomPythonCodeTool, {"description": "Test utility", "code": "print('Hello World')"}, id="custom_python_tool", ), pytest.param( - {"type": "utility", "description": "Test utility"}, PythonInterpreterTool, {}, id="python_interpreter_tool" + {"type": "utility", "description": "Test utility"}, + PythonInterpreterTool, + {}, + id="python_interpreter_tool", ), pytest.param( { @@ -186,8 +203,6 @@ def test_build_tool_error_cases(tool_dict, expected_error): ), ], ) - - def test_build_tool_success_cases(tool_dict, expected_type, expected_attrs, mock_model, mocker): """Test successful tool creation with various configurations.""" mocker.patch.object(ModelFactory, "get", return_value=mock_model) @@ -195,13 +210,24 @@ def test_build_tool_success_cases(tool_dict, expected_type, expected_attrs, mock "aixplain.modules.model.utils.parse_code_decorated", return_value=("print('Hello World')", [], "Test description", "test_name"), ) - mocker.patch("os.path.exists", lambda path: True if path == "test_db.db" else os.path.exists(path)) - mocker.patch("aixplain.factories.file_factory.FileFactory.upload", return_value="s3://mocked-file-path/test_db.db") + mocker.patch( + "os.path.exists", + lambda path: True if path == "test_db.db" else os.path.exists(path), + ) + mocker.patch( + "aixplain.factories.file_factory.FileFactory.upload", + return_value="s3://mocked-file-path/test_db.db", + ) if tool_dict["type"] == "pipeline": mocker.patch.object( PipelineFactory, "get", - return_value=Pipeline(id=tool_dict["assetId"], description=tool_dict["description"], name="Pipeline", api_key=""), + return_value=Pipeline( + id=tool_dict["assetId"], + description=tool_dict["description"], + name="Pipeline", + api_key="", + ), ) tool = build_tool(tool_dict) @@ -273,7 +299,11 @@ def test_build_tool_success_cases(tool_dict, expected_type, expected_attrs, mock "description": "Test model", "function": "speech-recognition", }, - {"type": "pipeline", "description": "Test pipeline", "assetId": "test_pipeline"}, + { + "type": "pipeline", + "description": "Test pipeline", + "assetId": "test_pipeline", + }, ], }, { @@ -286,8 +316,6 @@ def test_build_tool_success_cases(tool_dict, expected_type, expected_attrs, mock ), ], ) - - def test_build_agent_success_cases(payload, expected_attrs, mock_tools, mocker): """Test successful agent creation with various configurations.""" mocker.patch.object( @@ -301,9 +329,9 @@ def test_build_agent_success_cases(payload, expected_attrs, mock_tools, mocker): for attr, value in expected_attrs.items(): if attr == "tasks": - assert len(agent.tasks) == len(value) - for task, expected_task in zip(agent.tasks, value): - assert isinstance(task, AgentTask) + assert len(agent.workflow_tasks) == len(value) + for task, expected_task in zip(agent.workflow_tasks, value): + assert isinstance(task, WorkflowTask) for task_attr, task_value in expected_task.items(): assert getattr(task, task_attr) == task_value elif attr == "tools": @@ -322,7 +350,13 @@ def test_build_agent_success_cases(payload, expected_attrs, mock_tools, mocker): "id": "test_agent", "name": "Test Agent", "status": "onboarded", - "assets": [{"type": "invalid_type", "description": "Test tool", "assetId": "invalid_asset"}], + "assets": [ + { + "type": "invalid_type", + "description": "Test tool", + "assetId": "invalid_asset", + } + ], }, "Agent Creation Error: Tool type not supported", id="invalid_tool_type", @@ -369,7 +403,13 @@ def test_build_agent_success_cases(payload, expected_attrs, mock_tools, mocker): "id": "test_agent", "name": "Test Agent", "status": "onboarded", - "assets": [{"type": "model", "assetId": "test_model", "function": "speech-recognition"}], + "assets": [ + { + "type": "model", + "assetId": "test_model", + "function": "speech-recognition", + } + ], }, "Tool test_model is not available. Make sure it exists or you have access to it. If you think this is an error, please contact the administrators.", id="generic_error", diff --git a/tests/unit/agent/agent_test.py b/tests/unit/agent/agent_test.py index fc66141b..24a78b7c 100644 --- a/tests/unit/agent/agent_test.py +++ b/tests/unit/agent/agent_test.py @@ -803,13 +803,13 @@ def test_create_agent_task(): assert task.name == "Test Task" assert task.description == "Test Description" assert task.expected_output == "Test Output" - assert task.dependencies is None + assert task.dependencies == [] task_dict = task.to_dict() assert task_dict["name"] == "Test Task" assert task_dict["description"] == "Test Description" assert task_dict["expectedOutput"] == "Test Output" - assert task_dict["dependencies"] is None + assert task_dict["dependencies"] == [] def test_agent_response(): diff --git a/tests/unit/agent/evolve_param_test.py b/tests/unit/agent/evolve_param_test.py new file mode 100644 index 00000000..2f0f744e --- /dev/null +++ b/tests/unit/agent/evolve_param_test.py @@ -0,0 +1,187 @@ +""" +Unit tests for EvolveParam base model functionality +""" + +import pytest +from aixplain.modules.agent.evolve_param import ( + EvolveParam, + EvolveType, + validate_evolve_param, +) + + +class TestEvolveParam: + """Test class for EvolveParam functionality""" + + def test_default_initialization(self): + """Test EvolveParam default initialization""" + default_param = EvolveParam() + + assert default_param is not None + assert default_param.to_evolve is False + assert default_param.evolve_type == EvolveType.TEAM_TUNING + assert default_param.max_successful_generations == 3 + assert default_param.max_failed_generation_retries == 3 + assert default_param.max_iterations == 50 + assert default_param.max_non_improving_generations == 2 + assert default_param.llm is None + assert default_param.additional_params == {} + + # Test to_dict method + result_dict = default_param.to_dict() + assert isinstance(result_dict, dict) + assert "toEvolve" in result_dict + + def test_custom_initialization(self): + """Test EvolveParam custom initialization""" + custom_param = EvolveParam( + to_evolve=True, + max_successful_generations=5, + max_failed_generation_retries=2, + max_iterations=30, + max_non_improving_generations=4, + evolve_type=EvolveType.TEAM_TUNING, + llm={"id": "test_llm_id", "name": "Test LLM"}, + additional_params={"customParam": "custom_value"}, + ) + + assert custom_param.to_evolve is True + assert custom_param.max_successful_generations == 5 + assert custom_param.max_failed_generation_retries == 2 + assert custom_param.max_iterations == 30 + assert custom_param.max_non_improving_generations == 4 + assert custom_param.evolve_type == EvolveType.TEAM_TUNING + assert custom_param.llm == {"id": "test_llm_id", "name": "Test LLM"} + assert custom_param.additional_params == {"customParam": "custom_value"} + + # Test to_dict method + result_dict = custom_param.to_dict() + assert result_dict["toEvolve"] is True + assert result_dict["max_successful_generations"] == 5 + assert result_dict["max_failed_generation_retries"] == 2 + assert result_dict["max_iterations"] == 30 + assert result_dict["max_non_improving_generations"] == 4 + assert result_dict["evolve_type"] == EvolveType.TEAM_TUNING + assert result_dict["llm"] == {"id": "test_llm_id", "name": "Test LLM"} + assert result_dict["customParam"] == "custom_value" + + def test_from_dict_with_api_format(self): + """Test EvolveParam from_dict() with API format""" + api_dict = { + "toEvolve": True, + "max_successful_generations": 10, + "max_failed_generation_retries": 4, + "max_iterations": 40, + "max_non_improving_generations": 5, + "evolve_type": EvolveType.TEAM_TUNING, + "llm": {"id": "api_llm_id", "name": "API LLM"}, + "customParam": "custom_value", + } + + from_dict_param = EvolveParam.from_dict(api_dict) + + assert from_dict_param.to_evolve is True + assert from_dict_param.max_successful_generations == 10 + assert from_dict_param.max_failed_generation_retries == 4 + assert from_dict_param.max_iterations == 40 + assert from_dict_param.max_non_improving_generations == 5 + assert from_dict_param.evolve_type == EvolveType.TEAM_TUNING + assert from_dict_param.llm == {"id": "api_llm_id", "name": "API LLM"} + + # Test round-trip conversion + result_dict = from_dict_param.to_dict() + assert result_dict["toEvolve"] is True + assert result_dict["max_successful_generations"] == 10 + assert result_dict["max_failed_generation_retries"] == 4 + assert result_dict["max_iterations"] == 40 + assert result_dict["max_non_improving_generations"] == 5 + + def test_validate_evolve_param_with_none(self): + """Test validate_evolve_param() with None input""" + validated_none = validate_evolve_param(None) + + assert validated_none is not None + assert isinstance(validated_none, EvolveParam) + assert validated_none.to_evolve is False + + result_dict = validated_none.to_dict() + assert "toEvolve" in result_dict + + def test_validate_evolve_param_with_dict(self): + """Test validate_evolve_param() with dictionary input""" + input_dict = {"toEvolve": True, "max_successful_generations": 5} + validated_dict = validate_evolve_param(input_dict) + + assert isinstance(validated_dict, EvolveParam) + assert validated_dict.to_evolve is True + assert validated_dict.max_successful_generations == 5 + + result_dict = validated_dict.to_dict() + assert result_dict["toEvolve"] is True + assert result_dict["max_successful_generations"] == 5 + + def test_validate_evolve_param_with_instance(self): + """Test validate_evolve_param() with EvolveParam instance""" + custom_param = EvolveParam( + to_evolve=True, + max_successful_generations=5, + max_failed_generation_retries=2, + max_iterations=30, + max_non_improving_generations=4, + evolve_type=EvolveType.TEAM_TUNING, + llm={"id": "instance_llm_id"}, + additional_params={"customParam": "custom_value"}, + ) + + validated_instance = validate_evolve_param(custom_param) + + assert validated_instance is custom_param # Should return the same instance + assert validated_instance.to_evolve is True + assert validated_instance.max_successful_generations == 5 + assert validated_instance.max_failed_generation_retries == 2 + + def test_invalid_max_successful_generations_raises_error(self): + """Test that invalid max_successful_generations raises ValueError""" + with pytest.raises(ValueError, match="max_successful_generations must be positive"): + EvolveParam(max_successful_generations=0) # max_successful_generations <= 0 should fail + + def test_validate_evolve_param_missing_to_evolve_key(self): + """Test that missing toEvolve key raises ValueError""" + with pytest.raises(ValueError, match="evolve parameter must contain 'toEvolve' key"): + validate_evolve_param({"no_to_evolve": True}) # Missing toEvolve key + + def test_evolve_type_enum_values(self): + """Test that EvolveType enum values work correctly""" + param_team_tuning = EvolveParam(evolve_type=EvolveType.TEAM_TUNING) + + assert param_team_tuning.evolve_type == EvolveType.TEAM_TUNING + + # Test in to_dict conversion + dict_team_tuning = param_team_tuning.to_dict() + + assert "evolve_type" in dict_team_tuning + + def test_invalid_additional_params_type(self): + """Test that invalid additional_params type raises ValueError""" + with pytest.raises(ValueError, match="additional_params must be a dictionary"): + EvolveParam(additional_params="not a dict") + + def test_merge_with_dict(self): + """Test merging with a dictionary""" + base_param = EvolveParam(to_evolve=False, max_successful_generations=3, additional_params={"base": "value"}) + merge_dict = { + "toEvolve": True, + "max_successful_generations": 5, + "llm": {"id": "merged_llm_id"}, + "customParam": "custom_value", + } + + merged = base_param.merge(merge_dict) + + assert merged.to_evolve is True + assert merged.max_successful_generations == 5 + assert merged.llm == {"id": "merged_llm_id"} + assert merged.additional_params == { + "base": "value", + "customParam": "custom_value", + } diff --git a/tests/unit/agent/test_agent_evolve.py b/tests/unit/agent/test_agent_evolve.py new file mode 100644 index 00000000..f4aa1990 --- /dev/null +++ b/tests/unit/agent/test_agent_evolve.py @@ -0,0 +1,214 @@ +""" +Unit tests for Agent evolve functionality with llm parameter +""" + +import pytest +from unittest.mock import Mock, patch +from aixplain.modules.agent import Agent +from aixplain.modules.model.llm_model import LLM +from aixplain.modules.agent.evolve_param import EvolveParam +from aixplain.enums import EvolveType, Function, Supplier, ResponseStatus +from aixplain.modules.agent.agent_response import AgentResponse +from aixplain.modules.agent.agent_response_data import AgentResponseData + + +class TestAgentEvolve: + """Test class for Agent evolve functionality""" + + @pytest.fixture + def mock_agent(self): + """Create a mock Agent for testing""" + agent = Mock(spec=Agent) + agent.id = "test_agent_id" + agent.name = "Test Agent" + agent.api_key = "test_api_key" + return agent + + @pytest.fixture + def mock_llm(self): + """Create a mock LLM for testing""" + llm = Mock(spec=LLM) + llm.id = "test_llm_id" + llm.name = "Test LLM" + llm.description = "Test LLM Description" + llm.supplier = Supplier.OPENAI + llm.version = "1.0.0" + llm.function = Function.TEXT_GENERATION + llm.temperature = 0.7 + + # Mock get_parameters + mock_params = Mock() + mock_params.to_list.return_value = [{"name": "temperature", "type": "float"}] + llm.get_parameters.return_value = mock_params + + return llm + + def test_evolve_async_with_llm_string(self, mock_agent): + """Test evolve_async with llm as string ID""" + from aixplain.modules.agent import Agent + + # Create a real Agent instance but mock its methods + agent = Agent( + id="test_agent_id", + name="Test Agent", + description="Test Description", + instructions="Test Instructions", + tools=[], + llm_id="6646261c6eb563165658bbb1", + ) + + # Mock the run_async method + mock_response = AgentResponse( + status=ResponseStatus.IN_PROGRESS, + url="http://test-poll-url.com", + data=AgentResponseData(input="test input"), + run_time=0.0, + used_credits=0.0, + ) + + with patch.object(agent, "run_async", return_value=mock_response) as mock_run_async: + result = agent.evolve_async(llm="custom_llm_id_123") + + # Verify run_async was called with correct evolve parameter + mock_run_async.assert_called_once() + call_args = mock_run_async.call_args + + # Check that evolve parameter contains llm + evolve_param = call_args[1]["evolve"] + assert isinstance(evolve_param, EvolveParam) + assert evolve_param.llm == {"id": "custom_llm_id_123"} + + assert result == mock_response + + def test_evolve_async_with_llm_object(self, mock_agent, mock_llm): + """Test evolve_async with llm as LLM object""" + from aixplain.modules.agent import Agent + + # Create a real Agent instance but mock its methods + agent = Agent( + id="test_agent_id", + name="Test Agent", + description="Test Description", + instructions="Test Instructions", + tools=[], + llm_id="6646261c6eb563165658bbb1", + ) + + # Mock the run_async method + mock_response = AgentResponse( + status=ResponseStatus.IN_PROGRESS, + url="http://test-poll-url.com", + data=AgentResponseData(input="test input"), + run_time=0.0, + used_credits=0.0, + ) + + with patch.object(agent, "run_async", return_value=mock_response) as mock_run_async: + result = agent.evolve_async(llm=mock_llm) + + # Verify run_async was called with correct evolve parameter + mock_run_async.assert_called_once() + call_args = mock_run_async.call_args + + # Check that evolve parameter contains llm + evolve_param = call_args[1]["evolve"] + assert isinstance(evolve_param, EvolveParam) + + expected_llm_dict = { + "id": "test_llm_id", + "name": "Test LLM", + "description": "Test LLM Description", + "supplier": Supplier.OPENAI, + "version": "1.0.0", + "function": Function.TEXT_GENERATION, + "parameters": [{"name": "temperature", "type": "float"}], + "temperature": 0.7, + } + assert evolve_param.llm == expected_llm_dict + + assert result == mock_response + + def test_evolve_async_without_llm(self, mock_agent): + """Test evolve_async without llm parameter""" + from aixplain.modules.agent import Agent + + # Create a real Agent instance but mock its methods + agent = Agent( + id="test_agent_id", + name="Test Agent", + description="Test Description", + instructions="Test Instructions", + tools=[], + llm_id="6646261c6eb563165658bbb1", + ) + + # Mock the run_async method + mock_response = AgentResponse( + status=ResponseStatus.IN_PROGRESS, + url="http://test-poll-url.com", + data=AgentResponseData(input="test input"), + run_time=0.0, + used_credits=0.0, + ) + + with patch.object(agent, "run_async", return_value=mock_response) as mock_run_async: + result = agent.evolve_async() + + # Verify run_async was called with correct evolve parameter + mock_run_async.assert_called_once() + call_args = mock_run_async.call_args + + # Check that evolve parameter has llm as None + evolve_param = call_args[1]["evolve"] + assert isinstance(evolve_param, EvolveParam) + assert evolve_param.llm is None + + assert result == mock_response + + def test_evolve_with_custom_parameters(self, mock_agent): + """Test evolve with custom parameters including llm""" + from aixplain.modules.agent import Agent + + # Create a real Agent instance but mock its methods + agent = Agent( + id="test_agent_id", + name="Test Agent", + description="Test Description", + instructions="Test Instructions", + tools=[], + llm_id="6646261c6eb563165658bbb1", + ) + + with patch.object(agent, "evolve_async") as mock_evolve_async, patch.object(agent, "sync_poll") as mock_sync_poll: + + # Mock evolve_async response + mock_evolve_async.return_value = {"status": ResponseStatus.IN_PROGRESS, "url": "http://test-poll-url.com"} + + # Mock sync_poll response + mock_result = Mock() + mock_result.data = {"current_code": "test code", "evolved_agent": "evolved_agent_data"} + mock_sync_poll.return_value = mock_result + + result = agent.evolve( + evolve_type=EvolveType.TEAM_TUNING, + max_successful_generations=5, + max_failed_generation_retries=3, + max_iterations=40, + max_non_improving_generations=3, + llm="custom_llm_id", + ) + + # Verify evolve_async was called with correct parameters + mock_evolve_async.assert_called_once_with( + evolve_type=EvolveType.TEAM_TUNING, + max_successful_generations=5, + max_failed_generation_retries=3, + max_iterations=40, + max_non_improving_generations=3, + llm="custom_llm_id", + ) + + # Verify sync_poll was called + mock_sync_poll.assert_called_once_with("http://test-poll-url.com", name="evolve_process", timeout=600) + + assert result is not None diff --git a/tests/unit/agent/test_evolver_llm_utils.py b/tests/unit/agent/test_evolver_llm_utils.py new file mode 100644 index 00000000..1997115b --- /dev/null +++ b/tests/unit/agent/test_evolver_llm_utils.py @@ -0,0 +1,129 @@ +""" +Unit tests for evolver LLM utility functions +""" + +from unittest.mock import Mock +from aixplain.utils.evolve_utils import create_llm_dict +from aixplain.modules.model.llm_model import LLM +from aixplain.enums import Function, Supplier + + +class TestCreateLLMDict: + """Test class for create_llm_dict functionality""" + + def test_create_llm_dict_with_none(self): + """Test create_llm_dict with None input""" + result = create_llm_dict(None) + assert result is None + + def test_create_llm_dict_with_string_id(self): + """Test create_llm_dict with LLM ID string""" + llm_id = "test_llm_id_123" + result = create_llm_dict(llm_id) + + expected = {"id": llm_id} + assert result == expected + + def test_create_llm_dict_with_llm_object(self): + """Test create_llm_dict with LLM object""" + # Create a mock LLM object + mock_llm = Mock(spec=LLM) + mock_llm.id = "llm_id_456" + mock_llm.name = "Test LLM Model" + mock_llm.description = "A test LLM model for unit testing" + mock_llm.supplier = Supplier.OPENAI + mock_llm.version = "1.0.0" + mock_llm.function = Function.TEXT_GENERATION + mock_llm.temperature = 0.7 + + # Mock the get_parameters method + mock_parameters = Mock() + mock_parameters.to_list.return_value = [ + {"name": "max_tokens", "type": "integer", "default": 2048}, + {"name": "temperature", "type": "float", "default": 0.7}, + ] + mock_llm.get_parameters.return_value = mock_parameters + + result = create_llm_dict(mock_llm) + + expected = { + "id": "llm_id_456", + "name": "Test LLM Model", + "description": "A test LLM model for unit testing", + "supplier": Supplier.OPENAI, + "version": "1.0.0", + "function": Function.TEXT_GENERATION, + "parameters": [ + {"name": "max_tokens", "type": "integer", "default": 2048}, + {"name": "temperature", "type": "float", "default": 0.7}, + ], + "temperature": 0.7, + } + assert result == expected + + def test_create_llm_dict_with_llm_object_no_parameters(self): + """Test create_llm_dict with LLM object that has no parameters""" + # Create a mock LLM object + mock_llm = Mock(spec=LLM) + mock_llm.id = "llm_id_789" + mock_llm.name = "Simple LLM" + mock_llm.description = "A simple LLM without parameters" + mock_llm.supplier = Supplier.OPENAI + mock_llm.version = "2.0.0" + mock_llm.function = Function.TEXT_GENERATION + mock_llm.temperature = 0.5 + + # Mock get_parameters to return None + mock_llm.get_parameters.return_value = None + + result = create_llm_dict(mock_llm) + + expected = { + "id": "llm_id_789", + "name": "Simple LLM", + "description": "A simple LLM without parameters", + "supplier": Supplier.OPENAI, + "version": "2.0.0", + "function": Function.TEXT_GENERATION, + "parameters": None, + "temperature": 0.5, + } + assert result == expected + + def test_create_llm_dict_with_llm_object_no_temperature(self): + """Test create_llm_dict with LLM object that has no temperature attribute""" + # Create a mock LLM object without temperature + mock_llm = Mock(spec=LLM) + mock_llm.id = "llm_id_999" + mock_llm.name = "No Temp LLM" + mock_llm.description = "LLM without temperature" + mock_llm.supplier = Supplier.GOOGLE + mock_llm.version = "3.0.0" + mock_llm.function = Function.TEXT_GENERATION + + # Remove temperature attribute + del mock_llm.temperature + + # Mock get_parameters to return None + mock_llm.get_parameters.return_value = None + + result = create_llm_dict(mock_llm) + + expected = { + "id": "llm_id_999", + "name": "No Temp LLM", + "description": "LLM without temperature", + "supplier": Supplier.GOOGLE, + "version": "3.0.0", + "function": Function.TEXT_GENERATION, + "parameters": None, + "temperature": None, + } + assert result == expected + + def test_create_llm_dict_with_empty_string(self): + """Test create_llm_dict with empty string""" + result = create_llm_dict("") + + expected = {"id": ""} + assert result == expected diff --git a/tests/unit/index_model_test.py b/tests/unit/index_model_test.py index 8d5c3a74..5f5e13eb 100644 --- a/tests/unit/index_model_test.py +++ b/tests/unit/index_model_test.py @@ -252,3 +252,60 @@ def test_index_model_splitter(): assert splitter.split_by == "sentence" assert splitter.split_length == 100 assert splitter.split_overlap == 0 + + +def test_parse_file_success(mocker): + mock_response = {"status": "SUCCESS", "data": "parsed content"} + mock_model = mocker.Mock() + mock_model.run.return_value = ModelResponse(status=ResponseStatus.SUCCESS, data="parsed content") + + mocker.patch("aixplain.factories.ModelFactory.get", return_value=mock_model) + mocker.patch("os.path.exists", return_value=True) + + response = IndexModel.parse_file("test.pdf") + + assert isinstance(response, ModelResponse) + assert response.status == ResponseStatus.SUCCESS + assert response.data == "parsed content" + mock_model.run.assert_called_once_with("test.pdf") + + +def test_parse_file_not_found(): + with pytest.raises(Exception) as e: + IndexModel.parse_file("nonexistent.pdf") + assert str(e.value) == "File nonexistent.pdf does not exist" + + +def test_parse_file_error(mocker): + mocker.patch("os.path.exists", return_value=True) + mocker.patch("aixplain.factories.ModelFactory.get", side_effect=Exception("Model error")) + + with pytest.raises(Exception) as e: + IndexModel.parse_file("test.pdf") + assert str(e.value) == "Failed to parse file: Model error" + + +def test_upsert_with_file_path(mocker): + mock_parse_response = ModelResponse(status=ResponseStatus.SUCCESS, data="parsed content") + mock_upsert_response = {"status": "SUCCESS"} + + mocker.patch("aixplain.modules.model.index_model.IndexModel.parse_file", return_value=mock_parse_response) + mocker.patch("aixplain.factories.FileFactory.check_storage_type", return_value=StorageType.TEXT) + + with requests_mock.Mocker() as mock: + mock.post(execute_url, json=mock_upsert_response, status_code=200) + index_model = IndexModel(id=index_id, data=data, name="name", function=Function.SEARCH) + response = index_model.upsert("test.pdf") + + assert isinstance(response, ModelResponse) + assert response.status == ResponseStatus.SUCCESS + + +def test_upsert_with_invalid_file_path(mocker): + mocker.patch("aixplain.modules.model.index_model.IndexModel.parse_file", side_effect=Exception("File not found")) + + index_model = IndexModel(id=index_id, data=data, name="name", function=Function.SEARCH) + + with pytest.raises(Exception) as e: + index_model.upsert("nonexistent.pdf") + assert str(e.value) == "File not found" diff --git a/tests/unit/team_agent/inspector_test.py b/tests/unit/team_agent/inspector_test.py index e21d6c53..aa8933d1 100644 --- a/tests/unit/team_agent/inspector_test.py +++ b/tests/unit/team_agent/inspector_test.py @@ -1,9 +1,21 @@ import pytest from unittest.mock import patch, MagicMock -from aixplain.modules.team_agent.inspector import Inspector, InspectorPolicy, InspectorAuto, AUTO_DEFAULT_MODEL_ID +from aixplain.modules.team_agent.inspector import ( + Inspector, + InspectorPolicy, + InspectorAuto, + AUTO_DEFAULT_MODEL_ID, + InspectorAction, + InspectorOutput, + callable_to_code_string, + code_string_to_callable, + get_policy_source, +) from aixplain.factories.team_agent_factory.inspector_factory import InspectorFactory from aixplain.enums.function import Function from aixplain.enums.asset_status import AssetStatus +from aixplain.modules.model.response import ModelResponse +from aixplain.enums.response_status import ResponseStatus # Test data INSPECTOR_CONFIG = { @@ -27,118 +39,518 @@ } -def test_inspector_creation(): - """Test basic inspector creation with valid parameters""" - inspector = Inspector( - name=INSPECTOR_CONFIG["name"], - model_id=INSPECTOR_CONFIG["model_id"], - model_params=INSPECTOR_CONFIG["model_config"], - policy=INSPECTOR_CONFIG["policy"], - ) +class TestInspectorCreation: + """Test inspector creation with various configurations""" - assert inspector.name == INSPECTOR_CONFIG["name"] - assert inspector.model_id == INSPECTOR_CONFIG["model_id"] - assert inspector.model_params == INSPECTOR_CONFIG["model_config"] - assert inspector.policy == INSPECTOR_CONFIG["policy"] - assert inspector.auto is None + def test_basic_inspector_creation(self): + """Test basic inspector creation with valid parameters""" + inspector = Inspector( + name=INSPECTOR_CONFIG["name"], + model_id=INSPECTOR_CONFIG["model_id"], + model_params=INSPECTOR_CONFIG["model_config"], + policy=INSPECTOR_CONFIG["policy"], + ) + + assert inspector.name == INSPECTOR_CONFIG["name"] + assert inspector.model_id == INSPECTOR_CONFIG["model_id"] + assert inspector.model_params == INSPECTOR_CONFIG["model_config"] + assert inspector.policy == INSPECTOR_CONFIG["policy"] + assert inspector.auto is None + def test_inspector_with_callable_policy(self): + """Test inspector creation with valid callable policy""" -def test_inspector_auto_creation(): - """Test inspector creation with auto configuration""" - inspector = Inspector(name="auto_inspector", auto=InspectorAuto.CORRECTNESS, policy=InspectorPolicy.WARN) + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE) - assert inspector.name == "auto_inspector" - assert inspector.auto == InspectorAuto.CORRECTNESS - assert inspector.policy == InspectorPolicy.WARN - assert inspector.model_id == AUTO_DEFAULT_MODEL_ID - assert inspector.model_params is None + inspector = Inspector( + name=INSPECTOR_CONFIG["name"], + model_id=INSPECTOR_CONFIG["model_id"], + model_params=INSPECTOR_CONFIG["model_config"], + policy=process_response, + ) + assert inspector.name == INSPECTOR_CONFIG["name"] + assert callable(inspector.policy) + assert inspector.policy.__name__ == "process_response" -def test_inspector_name_validation(): - """Test inspector name validation""" - with pytest.raises(ValueError, match="name cannot be empty"): - Inspector(name="", model_id="test_model_id") + def test_inspector_auto_creation(self): + """Test inspector creation with auto configuration""" + inspector = Inspector(name="auto_inspector", auto=InspectorAuto.CORRECTNESS, policy=InspectorPolicy.WARN) + assert inspector.name == "auto_inspector" + assert inspector.auto == InspectorAuto.CORRECTNESS + assert inspector.policy == InspectorPolicy.WARN + assert inspector.model_id == AUTO_DEFAULT_MODEL_ID + assert inspector.model_params is None -def test_inspector_factory_create_from_model(): - """Test creating inspector from model using factory""" - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.json.return_value = { - **MOCK_MODEL_RESPONSE, - "status": AssetStatus.ONBOARDED.value, - "function": {"id": Function.GUARDRAILS.value}, - } + def test_inspector_auto_creation_with_callable_policy(self): + """Test inspector creation with auto configuration and callable policy""" - with patch("aixplain.factories.team_agent_factory.inspector_factory._request_with_retry", return_value=mock_response): - inspector = InspectorFactory.create_from_model( - name=INSPECTOR_CONFIG["name"], - model=INSPECTOR_CONFIG["model_id"], - model_config=INSPECTOR_CONFIG["model_config"], - policy=INSPECTOR_CONFIG["policy"], + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + return InspectorOutput(critiques="Test critique", content_edited="", action=InspectorAction.RERUN) + + inspector = Inspector(name="auto_inspector", auto=InspectorAuto.CORRECTNESS, policy=process_response) + + assert inspector.name == "auto_inspector" + assert inspector.auto == InspectorAuto.CORRECTNESS + assert inspector.policy == process_response + assert callable(inspector.policy) + assert inspector.model_id == AUTO_DEFAULT_MODEL_ID + assert inspector.model_params is None + + def test_inspector_name_validation(self): + """Test inspector name validation""" + with pytest.raises(ValueError, match="name cannot be empty"): + Inspector(name="", model_id="test_model_id") + + +class TestInspectorValidation: + """Test inspector validation and error handling""" + + def test_invalid_callable_name(self): + """Test inspector creation with callable that has wrong function name""" + + def wrong_name(model_response: ModelResponse, input_content: str) -> InspectorOutput: + return InspectorOutput(critiques="Test", content_edited="", action=InspectorAction.CONTINUE) + + with pytest.raises(ValueError, match="Policy callable must have name 'process_response'"): + Inspector( + name=INSPECTOR_CONFIG["name"], + model_id=INSPECTOR_CONFIG["model_id"], + model_params=INSPECTOR_CONFIG["model_config"], + policy=wrong_name, + ) + + def test_invalid_callable_arguments(self): + """Test inspector creation with callable that has wrong arguments""" + + def process_response(wrong_arg: ModelResponse, another_wrong_arg: str) -> InspectorOutput: + return InspectorOutput(critiques="Test", content_edited="", action=InspectorAction.CONTINUE) + + with pytest.raises(ValueError, match="Policy callable must have name 'process_response'"): + Inspector( + name=INSPECTOR_CONFIG["name"], + model_id=INSPECTOR_CONFIG["model_id"], + model_params=INSPECTOR_CONFIG["model_config"], + policy=process_response, + ) + + def test_invalid_callable_return_type(self): + """Test inspector creation with callable that has wrong return type""" + + def process_response(model_response: ModelResponse, input_content: str) -> str: + return "continue" + + with pytest.raises(ValueError, match="Policy callable must have name 'process_response'"): + Inspector( + name=INSPECTOR_CONFIG["name"], + model_id=INSPECTOR_CONFIG["model_id"], + model_params=INSPECTOR_CONFIG["model_config"], + policy=process_response, + ) + + def test_invalid_policy_type(self): + """Test inspector creation with invalid policy type""" + with pytest.raises(ValueError, match="Input should be"): + Inspector( + name=INSPECTOR_CONFIG["name"], + model_id=INSPECTOR_CONFIG["model_id"], + model_params=INSPECTOR_CONFIG["model_config"], + policy=123, # Invalid type + ) + + +class TestCodeStringConversion: + """Test conversion between callable functions and code strings""" + + def test_callable_to_code_string(self): + """Test converting callable to code string""" + + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE) + + code_string = callable_to_code_string(process_response) + assert isinstance(code_string, str) + assert "def process_response" in code_string + assert "model_response" in code_string + assert "input_content" in code_string + assert "InspectorAction.ABORT" in code_string + + def test_code_string_to_callable(self): + """Test converting code string back to callable""" + code_string = """def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE)""" + + func = code_string_to_callable(code_string) + assert callable(func) + assert func.__name__ == "process_response" + + # Test the function works correctly + result1 = func(ModelResponse(status=ResponseStatus.FAILED, error_message="This is an error message"), "input") + assert result1.action == InspectorAction.ABORT + + result2 = func(ModelResponse(status=ResponseStatus.SUCCESS, data="This is a normal message"), "input") + assert result2.action == InspectorAction.CONTINUE + + def test_roundtrip_conversion(self): + """Test that serialization and deserialization work correctly together""" + + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + elif "warning" in model_response.data.lower(): + return InspectorOutput(critiques="Warning detected", content_edited="", action=InspectorAction.RERUN) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE) + + # Serialize + code_string = callable_to_code_string(process_response) + + # Deserialize + deserialized_func = code_string_to_callable(code_string) + + # Test that the deserialized function works the same + assert ( + deserialized_func(ModelResponse(status=ResponseStatus.FAILED, error_message="error message"), "input").action + == InspectorAction.ABORT + ) + assert ( + deserialized_func(ModelResponse(status=ResponseStatus.SUCCESS, data="warning message"), "input").action + == InspectorAction.RERUN + ) + assert ( + deserialized_func(ModelResponse(status=ResponseStatus.SUCCESS, data="normal message"), "input").action + == InspectorAction.CONTINUE ) - assert inspector.name == INSPECTOR_CONFIG["name"] - assert inspector.model_id == INSPECTOR_CONFIG["model_id"] - assert inspector.model_params == INSPECTOR_CONFIG["model_config"] - assert inspector.policy == INSPECTOR_CONFIG["policy"] + def test_source_code_preservation(self): + """Test that code_string_to_callable preserves the original source code""" + code_string = """def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + elif "warning" in model_response.data.lower(): + return InspectorOutput(critiques="Warning detected", content_edited="", action=InspectorAction.RERUN) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE)""" + func = code_string_to_callable(code_string) -def test_inspector_factory_create_from_model_invalid_status(): - """Test creating inspector from model with invalid status""" - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.json.return_value = { - **MOCK_MODEL_RESPONSE, - "status": AssetStatus.DRAFT.value, - "function": {"id": Function.GUARDRAILS.value}, - } + # Verify the function has the _source_code attribute + assert hasattr(func, "_source_code") + assert func._source_code == code_string - with patch("aixplain.factories.team_agent_factory.inspector_factory._request_with_retry", return_value=mock_response): - with pytest.raises(ValueError, match="is not onboarded"): - InspectorFactory.create_from_model( + # Verify the function works correctly + assert ( + func(ModelResponse(status=ResponseStatus.FAILED, error_message="This is an error message"), "input").action + == InspectorAction.ABORT + ) + assert ( + func(ModelResponse(status=ResponseStatus.SUCCESS, data="This is a warning message"), "input").action + == InspectorAction.RERUN + ) + assert ( + func(ModelResponse(status=ResponseStatus.SUCCESS, data="This is a normal message"), "input").action + == InspectorAction.CONTINUE + ) + + +class TestSourceCodeRetrieval: + """Test source code retrieval functionality""" + + def test_get_policy_source_original_function(self): + """Test get_policy_source with an original function (should use inspect.getsource)""" + + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE) + + source = get_policy_source(process_response) + assert source is not None + assert "def process_response" in source + assert "InspectorAction.ABORT" in source + + def test_get_policy_source_deserialized_function(self): + """Test get_policy_source with a deserialized function (should use _source_code attribute)""" + code_string = """def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE)""" + + func = code_string_to_callable(code_string) + + # Verify get_policy_source works with the deserialized function + source = get_policy_source(func) + assert source is not None + assert source == code_string + + def test_get_policy_source_fallback(self): + """Test get_policy_source fallback when neither approach works""" + # Create a function without source code info by using exec() + # This simulates a function created dynamically where inspect.getsource() would fail + namespace = {} + exec( + "def dynamic_func(x, y): return InspectorOutput(critiques='', content_edited='', action=InspectorAction.CONTINUE)", + namespace, + ) + func = namespace["dynamic_func"] + + # Remove any potential source code attributes + if hasattr(func, "_source_code"): + delattr(func, "_source_code") + + source = get_policy_source(func) + assert source is None + + +class TestInspectorSerialization: + """Test Inspector serialization and deserialization""" + + def test_model_dump_with_callable_policy(self): + """Test that Inspector.model_dump properly serializes callable policies""" + + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + return InspectorOutput(critiques="Test critique", content_edited="", action=InspectorAction.ABORT) + + inspector = Inspector( + name="test_inspector", + model_id="test_model_id", + policy=process_response, + ) + + data = inspector.model_dump() + assert data["policy_type"] == "callable" + assert isinstance(data["policy"], str) + assert "def process_response" in data["policy"] + + def test_model_dump_with_enum_policy(self): + """Test that Inspector.model_dump properly serializes enum policies""" + inspector = Inspector( + name="test_inspector", + model_id="test_model_id", + policy=InspectorPolicy.WARN, + ) + + data = inspector.model_dump() + assert data["policy_type"] == "enum" + assert data["policy"] == "warn" + + def test_model_validate_with_callable_policy(self): + """Test that Inspector.model_validate properly deserializes callable policies""" + inspector_data = { + "name": "test_inspector", + "model_id": "test_model_id", + "policy": """def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + return InspectorOutput(critiques="Test critique", content_edited="", action=InspectorAction.ABORT)""", + "policy_type": "callable", + } + + inspector = Inspector.model_validate(inspector_data) + assert callable(inspector.policy) + assert inspector.policy.__name__ == "process_response" + result = inspector.policy(ModelResponse(status=ResponseStatus.SUCCESS, data="test"), "input") + assert result.action == InspectorAction.ABORT + + def test_model_validate_with_enum_policy(self): + """Test that Inspector.model_validate properly deserializes enum policies""" + inspector_data = { + "name": "test_inspector", + "model_id": "test_model_id", + "policy": "warn", + "policy_type": "enum", + } + + inspector = Inspector.model_validate(inspector_data) + assert inspector.policy == InspectorPolicy.WARN + + def test_model_validate_fallback(self): + """Test that Inspector.model_validate falls back to default policy on error""" + inspector_data = { + "name": "test_inspector", + "model_id": "test_model_id", + "policy": "invalid code string", + "policy_type": "callable", + } + + inspector = Inspector.model_validate(inspector_data) + assert inspector.policy == InspectorPolicy.ADAPTIVE # Default fallback + + def test_roundtrip_serialization_preserves_source_code(self): + """Test that Inspector round-trip serialization preserves source code""" + + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + if "error" in model_response.error_message.lower(): + return InspectorOutput(critiques="Error detected", content_edited="", action=InspectorAction.ABORT) + elif "warning" in model_response.data.lower(): + return InspectorOutput(critiques="Warning detected", content_edited="", action=InspectorAction.RERUN) + return InspectorOutput(critiques="No issues", content_edited="", action=InspectorAction.CONTINUE) + + # Create inspector with callable policy + inspector = Inspector( + name="test_inspector", + model_id="test_model_id", + policy=process_response, + ) + + # Serialize to dict + inspector_dict = inspector.model_dump() + assert inspector_dict["policy_type"] == "callable" + assert isinstance(inspector_dict["policy"], str) + + # Deserialize from dict + inspector_copy = Inspector.model_validate(inspector_dict) + assert callable(inspector_copy.policy) + assert inspector_copy.policy.__name__ == "process_response" + + # Verify the deserialized function has source code and works correctly + assert hasattr(inspector_copy.policy, "_source_code") + assert "def process_response" in inspector_copy.policy._source_code + assert ( + inspector_copy.policy( + ModelResponse(status=ResponseStatus.FAILED, error_message="This is an error message"), "input" + ).action + == InspectorAction.ABORT + ) + assert ( + inspector_copy.policy( + ModelResponse(status=ResponseStatus.SUCCESS, data="This is a warning message"), "input" + ).action + == InspectorAction.RERUN + ) + assert ( + inspector_copy.policy(ModelResponse(status=ResponseStatus.SUCCESS, data="This is a normal message"), "input").action + == InspectorAction.CONTINUE + ) + + +class TestInspectorFactory: + """Test InspectorFactory functionality""" + + def test_create_from_model(self): + """Test creating inspector from model using factory""" + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + **MOCK_MODEL_RESPONSE, + "status": AssetStatus.ONBOARDED.value, + "function": {"id": Function.GUARDRAILS.value}, + } + + with patch("aixplain.factories.team_agent_factory.inspector_factory._request_with_retry", return_value=mock_response): + inspector = InspectorFactory.create_from_model( name=INSPECTOR_CONFIG["name"], model=INSPECTOR_CONFIG["model_id"], model_config=INSPECTOR_CONFIG["model_config"], policy=INSPECTOR_CONFIG["policy"], ) + assert inspector.name == INSPECTOR_CONFIG["name"] + assert inspector.model_id == INSPECTOR_CONFIG["model_id"] + assert inspector.model_params == INSPECTOR_CONFIG["model_config"] + assert inspector.policy == INSPECTOR_CONFIG["policy"] + + def test_create_from_model_with_callable_policy(self): + """Test creating inspector from model using factory with callable policy""" -def test_inspector_factory_create_from_model_invalid_function(): - """Test creating inspector from model with invalid function""" - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.json.return_value = { - **MOCK_MODEL_RESPONSE, - "status": AssetStatus.ONBOARDED.value, - "function": {"id": Function.TRANSLATION.value}, - } + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + return InspectorOutput(critiques="Test critique", content_edited="", action=InspectorAction.CONTINUE) - with patch("aixplain.factories.team_agent_factory.inspector_factory._request_with_retry", return_value=mock_response): - with pytest.raises(ValueError, match="models are supported"): - InspectorFactory.create_from_model( + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + **MOCK_MODEL_RESPONSE, + "status": AssetStatus.ONBOARDED.value, + "function": {"id": Function.GUARDRAILS.value}, + } + + with patch("aixplain.factories.team_agent_factory.inspector_factory._request_with_retry", return_value=mock_response): + inspector = InspectorFactory.create_from_model( name=INSPECTOR_CONFIG["name"], model=INSPECTOR_CONFIG["model_id"], model_config=INSPECTOR_CONFIG["model_config"], - policy=INSPECTOR_CONFIG["policy"], + policy=process_response, ) + assert inspector.name == INSPECTOR_CONFIG["name"] + assert inspector.model_id == INSPECTOR_CONFIG["model_id"] + assert inspector.model_params == INSPECTOR_CONFIG["model_config"] + assert inspector.policy == process_response + assert callable(inspector.policy) + + def test_create_from_model_invalid_status(self): + """Test creating inspector from model with invalid status""" + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + **MOCK_MODEL_RESPONSE, + "status": AssetStatus.DRAFT.value, + "function": {"id": Function.GUARDRAILS.value}, + } + + with patch("aixplain.factories.team_agent_factory.inspector_factory._request_with_retry", return_value=mock_response): + with pytest.raises(ValueError, match="is not onboarded"): + InspectorFactory.create_from_model( + name=INSPECTOR_CONFIG["name"], + model=INSPECTOR_CONFIG["model_id"], + model_config=INSPECTOR_CONFIG["model_config"], + policy=INSPECTOR_CONFIG["policy"], + ) + + def test_create_from_model_invalid_function(self): + """Test creating inspector from model with invalid function""" + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + **MOCK_MODEL_RESPONSE, + "status": AssetStatus.ONBOARDED.value, + "function": {"id": Function.TRANSLATION.value}, + } + + with patch("aixplain.factories.team_agent_factory.inspector_factory._request_with_retry", return_value=mock_response): + with pytest.raises(ValueError, match="models are supported"): + InspectorFactory.create_from_model( + name=INSPECTOR_CONFIG["name"], + model=INSPECTOR_CONFIG["model_id"], + model_config=INSPECTOR_CONFIG["model_config"], + policy=INSPECTOR_CONFIG["policy"], + ) + + def test_create_auto(self): + """Test creating auto-configured inspector using factory""" + inspector = InspectorFactory.create_auto( + auto=InspectorAuto.CORRECTNESS, name="custom_name", policy=InspectorPolicy.ABORT + ) + + assert inspector.name == "custom_name" + assert inspector.auto == InspectorAuto.CORRECTNESS + assert inspector.policy == InspectorPolicy.ABORT + assert inspector.model_id == AUTO_DEFAULT_MODEL_ID + assert inspector.model_params is None + + def test_create_auto_with_callable_policy(self): + """Test creating auto-configured inspector using factory with callable policy""" -def test_inspector_factory_create_auto(): - """Test creating auto-configured inspector using factory""" - inspector = InspectorFactory.create_auto(auto=InspectorAuto.CORRECTNESS, name="custom_name", policy=InspectorPolicy.ABORT) + def process_response(model_response: ModelResponse, input_content: str) -> InspectorOutput: + return InspectorOutput(critiques="Test critique", content_edited="", action=InspectorAction.ABORT) - assert inspector.name == "custom_name" - assert inspector.auto == InspectorAuto.CORRECTNESS - assert inspector.policy == InspectorPolicy.ABORT - assert inspector.model_id == AUTO_DEFAULT_MODEL_ID - assert inspector.model_params is None + inspector = InspectorFactory.create_auto(auto=InspectorAuto.CORRECTNESS, name="custom_name", policy=process_response) + assert inspector.name == "custom_name" + assert inspector.auto == InspectorAuto.CORRECTNESS + assert inspector.policy == process_response + assert callable(inspector.policy) + assert inspector.model_id == AUTO_DEFAULT_MODEL_ID + assert inspector.model_params is None -def test_inspector_factory_create_auto_default_name(): - """Test creating auto-configured inspector with default name""" - inspector = InspectorFactory.create_auto(auto=InspectorAuto.CORRECTNESS) + def test_create_auto_default_name(self): + """Test creating auto-configured inspector with default name""" + inspector = InspectorFactory.create_auto(auto=InspectorAuto.CORRECTNESS) - assert inspector.name == "inspector_correctness" - assert inspector.auto == InspectorAuto.CORRECTNESS - assert inspector.policy == InspectorPolicy.ADAPTIVE # default policy + assert inspector.name == "inspector_correctness" + assert inspector.auto == InspectorAuto.CORRECTNESS + assert inspector.policy == InspectorPolicy.ADAPTIVE # default policy From 5e010df2f7ba369878ea21654c17d58f0d20c3e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20G=C3=BCnd=C3=BCz?= Date: Tue, 9 Sep 2025 21:37:20 +0300 Subject: [PATCH 2/5] Upgrade the version to 0.2.25 (#667) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c1af1a1a..c625b666 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ namespaces = true [project] name = "aiXplain" -version = "0.2.35rc1" +version = "0.2.35" description = "aiXplain SDK adds AI functions to software." readme = "README.md" requires-python = ">=3.9, <4" From c33ebbbb47a875b24b619b62698d0367b3d3c9aa Mon Sep 17 00:00:00 2001 From: Abdelrahman El-Sheikh <139810675+elsheikhams99@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:55:29 +0300 Subject: [PATCH 3/5] Add missing evolver docstrings / ruff pre-commit config (#671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add missing evolver docstrings / ruff pre-commit config * Create ruff.toml * Update pyproject.toml --------- Co-authored-by: Ahmet Gündüz --- .pre-commit-config.yaml | 7 ++ aixplain/enums/evolve_type.py | 13 ++++ .../team_agent/evolver_response_data.py | 71 +++++++++++++++++++ ruff.toml | 27 +++++++ 4 files changed, 118 insertions(+) create mode 100644 ruff.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4ad3e5bc..c7ad1c08 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,3 +31,10 @@ repos: - id: flake8 args: # arguments to configure flake8 - --ignore=E402,E501,E203,W503 + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.12 + hooks: + - id: ruff + args: [--fix] + - id: ruff-format diff --git a/aixplain/enums/evolve_type.py b/aixplain/enums/evolve_type.py index 555fdb53..b60289e2 100644 --- a/aixplain/enums/evolve_type.py +++ b/aixplain/enums/evolve_type.py @@ -2,5 +2,18 @@ class EvolveType(str, Enum): + """Enumeration of evolution types for team agents. + + This enum defines the available evolution strategies that can be applied + to team agents during the evolution process. Each type represents a + different approach to improving agent performance. + + Attributes: + TEAM_TUNING (str): Evolution strategy focused on tuning team-level + configurations and interactions between agents. + INSTRUCTION_TUNING (str): Evolution strategy focused on refining + individual agent instructions and prompts. + + """ TEAM_TUNING = "team_tuning" INSTRUCTION_TUNING = "instruction_tuning" diff --git a/aixplain/modules/team_agent/evolver_response_data.py b/aixplain/modules/team_agent/evolver_response_data.py index 06479e4e..ed197c2a 100644 --- a/aixplain/modules/team_agent/evolver_response_data.py +++ b/aixplain/modules/team_agent/evolver_response_data.py @@ -5,6 +5,22 @@ class EvolverResponseData: + """Container for team agent evolution response data. + + This class encapsulates all the data returned from a team agent evolution + process, including the evolved agent, code, evaluation reports, and + historical archive information. + + Attributes: + evolved_agent (TeamAgent): The evolved team agent instance. + current_code (str): The current YAML code representation of the agent. + evaluation_report (str): Report containing evaluation results. + comparison_report (str): Report comparing different agent versions. + criteria (str): Criteria used for evolution evaluation. + archive (List[str]): Historical archive of previous versions. + current_output (str): Current output from the agent. + + """ def __init__( self, evolved_agent: "TeamAgent", @@ -15,6 +31,19 @@ def __init__( archive: List[Text], current_output: Text = "", ) -> None: + """Initialize the EvolverResponseData instance. + + Args: + evolved_agent (TeamAgent): The evolved team agent instance. + current_code (str): The current YAML code representation. + evaluation_report (str): Report containing evaluation results. + comparison_report (str): Report comparing different versions. + criteria (str): Criteria used for evolution evaluation. + archive (List[str]): Historical archive of previous versions. + current_output (str, optional): Current output from the agent. + Defaults to empty string. + + """ self.evolved_agent = evolved_agent self.current_code = current_code self.evaluation_report = evaluation_report @@ -25,6 +54,17 @@ def __init__( @classmethod def from_dict(cls, data: Dict[str, Any], llm_id: Text, api_key: Text) -> "EvolverResponseData": + """Create an EvolverResponseData instance from a dictionary. + + Args: + data (Dict[str, Any]): Dictionary containing the response data. + llm_id (str): The LLM identifier for building the team agent. + api_key (str): API key for accessing the LLM service. + + Returns: + EvolverResponseData: A new instance created from the dictionary data. + + """ from aixplain.factories.team_agent_factory.utils import build_team_agent_from_yaml yaml_code = data.get("current_code", "") @@ -40,6 +80,12 @@ def from_dict(cls, data: Dict[str, Any], llm_id: Text, api_key: Text) -> "Evolve ) def to_dict(self) -> Dict[str, Any]: + """Convert the EvolverResponseData instance to a dictionary. + + Returns: + Dict[str, Any]: Dictionary representation of the instance data. + + """ return { "evolved_agent": self.evolved_agent, "current_code": self.current_code, @@ -51,15 +97,40 @@ def to_dict(self) -> Dict[str, Any]: } def __getitem__(self, key: str) -> Any: + """Get an attribute value using dictionary-style access. + + Args: + key (str): The attribute name to retrieve. + + Returns: + Any: The value of the requested attribute, or None if not found. + + """ return getattr(self, key, None) def __setitem__(self, key: str, value: Any) -> None: + """Set an attribute value using dictionary-style access. + + Args: + key (str): The attribute name to set. + value (Any): The value to assign to the attribute. + + Raises: + KeyError: If the key is not a valid attribute of the class. + + """ if hasattr(self, key): setattr(self, key, value) else: raise KeyError(f"{key} is not a valid attribute of {self.__class__.__name__}") def __repr__(self) -> str: + """Return a string representation of the EvolverResponseData instance. + + Returns: + str: A string representation showing key attributes of the instance. + + """ return ( f"{self.__class__.__name__}(" f"evolved_agent='{self.evolved_agent}', " diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..4a6fd632 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,27 @@ +line-length = 120 +indent-width = 4 +exclude = [] + +[format] +# Like Black, use double quotes for strings. +quote-style = "double" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" + +[lint] +select = ["D"] +ignore = [] +extend-safe-fixes = [] + +[lint.isort] +known-first-party = ["src"] + +[lint.pydocstyle] +convention = "google" From 460ec3323cee46fadedd7e6c78d378915dc7f74a Mon Sep 17 00:00:00 2001 From: Ayberk Demir <35486168+ayberkjs@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:13:15 +0300 Subject: [PATCH 4/5] Updated api reference docs (#672) --- .../python/aixplain/enums/evolve_type.md | 26 +++ .../aixplain/factories/agent_factory/init.md | 51 ++---- .../aixplain/factories/model_factory/utils.md | 4 +- .../team_agent_factory/inspector_factory.md | 40 ++--- .../factories/team_agent_factory/utils.md | 23 ++- .../aixplain/modules/agent/agent_response.md | 15 +- .../modules/agent/agent_response_data.md | 8 +- .../aixplain/modules/agent/agent_task.md | 28 ++-- .../aixplain/modules/agent/evolve_param.md | 155 ++++++++++++++++++ .../python/aixplain/modules/agent/init.md | 108 +++++++++--- .../aixplain/modules/model/index_model.md | 100 ++++++++--- .../python/aixplain/modules/model/utils.md | 10 +- .../team_agent/evolver_response_data.md | 146 +++++++++++++++++ .../aixplain/modules/team_agent/init.md | 112 ++++++++++--- .../aixplain/modules/team_agent/inspector.md | 111 ++++++++++++- .../python/aixplain/utils/evolve_utils.md | 25 +++ docs/api-reference/python/api_sidebar.js | 4 + 17 files changed, 798 insertions(+), 168 deletions(-) create mode 100644 docs/api-reference/python/aixplain/enums/evolve_type.md create mode 100644 docs/api-reference/python/aixplain/modules/agent/evolve_param.md create mode 100644 docs/api-reference/python/aixplain/modules/team_agent/evolver_response_data.md create mode 100644 docs/api-reference/python/aixplain/utils/evolve_utils.md diff --git a/docs/api-reference/python/aixplain/enums/evolve_type.md b/docs/api-reference/python/aixplain/enums/evolve_type.md new file mode 100644 index 00000000..556219c4 --- /dev/null +++ b/docs/api-reference/python/aixplain/enums/evolve_type.md @@ -0,0 +1,26 @@ +--- +sidebar_label: evolve_type +title: aixplain.enums.evolve_type +--- + +### EvolveType Objects + +```python +class EvolveType(str, Enum) +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/enums/evolve_type.py#L4) + +Enumeration of evolution types for team agents. + +This enum defines the available evolution strategies that can be applied +to team agents during the evolution process. Each type represents a +different approach to improving agent performance. + +**Attributes**: + +- `TEAM_TUNING` _str_ - Evolution strategy focused on tuning team-level + configurations and interactions between agents. +- `INSTRUCTION_TUNING` _str_ - Evolution strategy focused on refining + individual agent instructions and prompts. + diff --git a/docs/api-reference/python/aixplain/factories/agent_factory/init.md b/docs/api-reference/python/aixplain/factories/agent_factory/init.md index c13e186d..8eabbaa8 100644 --- a/docs/api-reference/python/aixplain/factories/agent_factory/init.md +++ b/docs/api-reference/python/aixplain/factories/agent_factory/init.md @@ -52,7 +52,8 @@ def create( api_key: Text = config.TEAM_API_KEY, supplier: Union[Dict, Text, Supplier, int] = "aiXplain", version: Optional[Text] = None, - tasks: List[AgentTask] = [], + tasks: List[WorkflowTask] = None, + workflow_tasks: List[WorkflowTask] = [], output_format: Optional[OutputFormat] = None, expected_output: Optional[Union[BaseModel, Text, dict]] = None) -> Agent @@ -72,7 +73,7 @@ Create a new agent in the platform. **Arguments**: - `name` _Text_ - name of the agent -- `description` _Text_ - description of the agent role. +- `description` _Text_ - description of the agent instructions. - `instructions` _Text_ - instructions of the agent. - `llm` _Optional[Union[LLM, Text]], optional_ - LLM instance to use as an object or as an ID. - `llm_id` _Optional[Text], optional_ - ID of LLM to use if no LLM instance provided. Defaults to None. @@ -80,7 +81,7 @@ Create a new agent in the platform. - `api_key` _Text, optional_ - team/user API key. Defaults to config.TEAM_API_KEY. - `supplier` _Union[Dict, Text, Supplier, int], optional_ - owner of the agent. Defaults to "aiXplain". - `version` _Optional[Text], optional_ - version of the agent. Defaults to None. -- `tasks` _List[AgentTask], optional_ - list of tasks for the agent. Defaults to []. +- `workflow_tasks` _List[WorkflowTask], optional_ - list of tasks for the agent. Defaults to []. - `description`0 _OutputFormat, optional_ - default output format for agent responses. Defaults to OutputFormat.TEXT. - `description`1 _Union[BaseModel, Text, dict], optional_ - expected output. Defaults to None. @@ -95,7 +96,7 @@ Create a new agent in the platform. def create_from_dict(cls, dict: Dict) -> Agent ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L191) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L202) Create an agent instance from a dictionary representation. @@ -113,34 +114,6 @@ Create an agent instance from a dictionary representation. - `Exception` - If agent validation fails or required properties are missing. -#### create\_task - -```python -@classmethod -def create_task(cls, - name: Text, - description: Text, - expected_output: Text, - dependencies: Optional[List[Text]] = None) -> AgentTask -``` - -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L209) - -Create a new task for an agent. - -**Arguments**: - -- `name` _Text_ - Name of the task. -- `description` _Text_ - Description of what the task should accomplish. -- `expected_output` _Text_ - Description of the expected output format. -- `dependencies` _Optional[List[Text]], optional_ - List of task names that must - complete before this task can start. Defaults to None. - - -**Returns**: - -- `AgentTask` - Created task object. - #### create\_model\_tool ```python @@ -154,7 +127,7 @@ def create_model_tool(cls, name: Optional[Text] = None) -> ModelTool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L236) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L245) Create a new model tool for use with an agent. @@ -187,7 +160,7 @@ def create_pipeline_tool(cls, name: Optional[Text] = None) -> PipelineTool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L284) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L293) Create a new pipeline tool for use with an agent. @@ -209,7 +182,7 @@ Create a new pipeline tool for use with an agent. def create_python_interpreter_tool(cls) -> PythonInterpreterTool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L303) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L312) Create a new Python interpreter tool for use with an agent. @@ -230,7 +203,7 @@ def create_custom_python_code_tool( description: Text = "") -> CustomPythonCodeTool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L314) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L323) Create a new custom Python code tool for use with an agent. @@ -259,7 +232,7 @@ def create_sql_tool(cls, enable_commit: bool = False) -> SQLTool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L330) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L339) Create a new SQL tool @@ -303,7 +276,7 @@ Create a new SQL tool def list(cls) -> Dict ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L463) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L472) List all agents available in the platform. @@ -327,7 +300,7 @@ List all agents available in the platform. def get(cls, agent_id: Text, api_key: Optional[Text] = None) -> Agent ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L513) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/agent_factory/__init__.py#L522) Retrieve an agent by its ID. diff --git a/docs/api-reference/python/aixplain/factories/model_factory/utils.md b/docs/api-reference/python/aixplain/factories/model_factory/utils.md index 80562490..df724a2c 100644 --- a/docs/api-reference/python/aixplain/factories/model_factory/utils.md +++ b/docs/api-reference/python/aixplain/factories/model_factory/utils.md @@ -58,7 +58,7 @@ def get_assets_from_page(query, api_key: Optional[str] = None) -> List[Model] ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/model_factory/utils.py#L145) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/model_factory/utils.py#L149) Retrieve a paginated list of models with specified filters. @@ -107,7 +107,7 @@ def get_model_from_ids(model_ids: List[str], api_key: Optional[str] = None) -> List[Model] ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/model_factory/utils.py#L258) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/model_factory/utils.py#L262) Retrieve multiple models by their IDs. diff --git a/docs/api-reference/python/aixplain/factories/team_agent_factory/inspector_factory.md b/docs/api-reference/python/aixplain/factories/team_agent_factory/inspector_factory.md index 7b14c9ef..40ddf76f 100644 --- a/docs/api-reference/python/aixplain/factories/team_agent_factory/inspector_factory.md +++ b/docs/api-reference/python/aixplain/factories/team_agent_factory/inspector_factory.md @@ -46,11 +46,12 @@ monitor team agent operations, providing feedback and enforcing policies. ```python @classmethod def create_from_model( - cls, - name: Text, - model: Union[Text, Model], - model_config: Optional[Dict] = None, - policy: InspectorPolicy = InspectorPolicy.ADAPTIVE) -> Inspector + cls, + name: Text, + model: Union[Text, Model], + model_config: Optional[Dict] = None, + policy: Union[InspectorPolicy, Callable] = InspectorPolicy.ADAPTIVE +) -> Inspector ``` [[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/team_agent_factory/inspector_factory.py#L48) @@ -68,11 +69,10 @@ onboarded to the platform. The model must be of a supported function type to use for the inspector. - `model_config` _Optional[Dict], optional_ - Configuration parameters for the inspector model (e.g., prompts, thresholds). Defaults to None. -- `policy` _InspectorPolicy, optional_ - Action to take upon negative feedback: - - WARN: Log warning but continue execution - - ABORT: Stop execution on negative feedback - - ADAPTIVE: Dynamically decide based on context - Defaults to InspectorPolicy.ADAPTIVE. +- `policy` - Action to take upon negative feedback (WARN/ABORT/ADAPTIVE) + or a callable function. If callable, must have name "process_response", + arguments "model_response" and "input_content" (both strings), and + return InspectorAction. Defaults to ADAPTIVE. **Returns**: @@ -93,13 +93,14 @@ onboarded to the platform. The model must be of a supported function type ```python @classmethod def create_auto( - cls, - auto: InspectorAuto, - name: Optional[Text] = None, - policy: InspectorPolicy = InspectorPolicy.ADAPTIVE) -> Inspector + cls, + auto: InspectorAuto, + name: Optional[Text] = None, + policy: Union[InspectorPolicy, Callable] = InspectorPolicy.ADAPTIVE +) -> Inspector ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/team_agent_factory/inspector_factory.py#L125) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/team_agent_factory/inspector_factory.py#L124) Create a new inspector agent using automatic configuration. @@ -112,11 +113,10 @@ a specific model. - `auto` _InspectorAuto_ - Pre-configured automatic inspector instance. - `name` _Optional[Text], optional_ - Name for the inspector. If not provided, uses the name from the auto configuration. Defaults to None. -- `policy` _InspectorPolicy, optional_ - Action to take upon negative feedback: - - WARN: Log warning but continue execution - - ABORT: Stop execution on negative feedback - - ADAPTIVE: Dynamically decide based on context - Defaults to InspectorPolicy.ADAPTIVE. +- `policy` - Action to take upon negative feedback (WARN/ABORT/ADAPTIVE) + or a callable function. If callable, must have name "process_response", + arguments "model_response" and "input_content" (both strings), and + return InspectorAction. Defaults to ADAPTIVE. **Returns**: diff --git a/docs/api-reference/python/aixplain/factories/team_agent_factory/utils.md b/docs/api-reference/python/aixplain/factories/team_agent_factory/utils.md index 5bbfd73c..1696b4ee 100644 --- a/docs/api-reference/python/aixplain/factories/team_agent_factory/utils.md +++ b/docs/api-reference/python/aixplain/factories/team_agent_factory/utils.md @@ -11,7 +11,7 @@ def build_team_agent(payload: Dict, api_key: Text = config.TEAM_API_KEY) -> TeamAgent ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/team_agent_factory/utils.py#L20) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/team_agent_factory/utils.py#L23) Build a TeamAgent instance from configuration payload. @@ -25,7 +25,7 @@ handling the setup of agents, LLMs, inspectors, and task dependencies. - name: Team agent name - agents: List of agent configurations - description: Optional description - - role: Optional instructions + - instructions: Optional instructions - teamId: Optional supplier information - version: Optional version - cost: Optional cost information @@ -52,3 +52,22 @@ handling the setup of agents, LLMs, inspectors, and task dependencies. - `Exception` - If a task dependency referenced in an agent's configuration cannot be found. +#### is\_yaml\_formatted + +```python +def is_yaml_formatted(text) +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/factories/team_agent_factory/utils.py#L212) + +Check if a string is valid YAML format with additional validation. + +**Arguments**: + +- `text` _str_ - The string to check + + +**Returns**: + +- `bool` - True if valid YAML, False otherwise + diff --git a/docs/api-reference/python/aixplain/modules/agent/agent_response.md b/docs/api-reference/python/aixplain/modules/agent/agent_response.md index 08a03828..cede8c81 100644 --- a/docs/api-reference/python/aixplain/modules/agent/agent_response.md +++ b/docs/api-reference/python/aixplain/modules/agent/agent_response.md @@ -9,7 +9,7 @@ title: aixplain.modules.agent.agent_response class AgentResponse(ModelResponse) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L7) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L10) A response object for agent execution results. @@ -33,7 +33,8 @@ access to response data and serialization capabilities. ```python def __init__(status: ResponseStatus = ResponseStatus.FAILED, - data: Optional[AgentResponseData] = None, + data: Optional[Union[AgentResponseData, + "EvolverResponseData"]] = None, details: Optional[Union[Dict, List]] = {}, completed: bool = False, error_message: Text = "", @@ -44,7 +45,7 @@ def __init__(status: ResponseStatus = ResponseStatus.FAILED, **kwargs) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L25) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L28) Initialize a new AgentResponse instance. @@ -76,7 +77,7 @@ Initialize a new AgentResponse instance. def __getitem__(key: Text) -> Any ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L76) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L79) Get a response attribute using dictionary-style access. @@ -99,7 +100,7 @@ serialization when accessing the 'data' key. def __setitem__(key: Text, value: Any) -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L93) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L96) Set a response attribute using dictionary-style access. @@ -118,7 +119,7 @@ deserialization when setting the 'data' key. def to_dict() -> Dict[Text, Any] ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L111) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L114) Convert the response to a dictionary representation. @@ -136,7 +137,7 @@ serialization in the output dictionary. def __repr__() -> str ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L125) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response.py#L128) Return a string representation of the response. diff --git a/docs/api-reference/python/aixplain/modules/agent/agent_response_data.md b/docs/api-reference/python/aixplain/modules/agent/agent_response_data.md index 11ecdade..2cec35a6 100644 --- a/docs/api-reference/python/aixplain/modules/agent/agent_response_data.md +++ b/docs/api-reference/python/aixplain/modules/agent/agent_response_data.md @@ -108,7 +108,7 @@ Convert the response data to a dictionary representation. def __getitem__(key: str) -> Any ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L98) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L101) Get an attribute value using dictionary-style access. @@ -127,7 +127,7 @@ Get an attribute value using dictionary-style access. def __setitem__(key: str, value: Any) -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L109) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L112) Set an attribute value using dictionary-style access. @@ -147,7 +147,7 @@ Set an attribute value using dictionary-style access. def __repr__() -> str ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L124) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L127) Return a string representation of the response data. @@ -161,7 +161,7 @@ Return a string representation of the response data. def __contains__(key: Text) -> bool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L140) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_response_data.py#L143) Check if an attribute exists using 'in' operator. diff --git a/docs/api-reference/python/aixplain/modules/agent/agent_task.md b/docs/api-reference/python/aixplain/modules/agent/agent_task.md index ff52f8a0..f5de2bfd 100644 --- a/docs/api-reference/python/aixplain/modules/agent/agent_task.md +++ b/docs/api-reference/python/aixplain/modules/agent/agent_task.md @@ -3,10 +3,10 @@ sidebar_label: agent_task title: aixplain.modules.agent.agent_task --- -### AgentTask Objects +### WorkflowTask Objects ```python -class AgentTask() +class WorkflowTask() ``` [[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_task.py#L4) @@ -21,7 +21,7 @@ description, expected output, and any dependencies on other tasks. - `name` _Text_ - The unique identifier/name of the task. - `description` _Text_ - Detailed description of what the task should accomplish. - `expected_output` _Text_ - Description of the expected output format or content. -- `dependencies` _Optional[List[Union[Text, AgentTask]]]_ - List of tasks or task +- `dependencies` _Optional[List[Union[Text, WorkflowTask]]]_ - List of tasks or task names that must be completed before this task. Defaults to None. #### \_\_init\_\_ @@ -30,19 +30,19 @@ description, expected output, and any dependencies on other tasks. def __init__(name: Text, description: Text, expected_output: Text, - dependencies: Optional[List[Union[Text, "AgentTask"]]] = None) + dependencies: Optional[List[Union[Text, "WorkflowTask"]]] = []) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_task.py#L17) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_task.py#L18) -Initialize a new AgentTask instance. +Initialize a new WorkflowTask instance. **Arguments**: - `name` _Text_ - The unique identifier/name of the task. - `description` _Text_ - Detailed description of what the task should accomplish. - `expected_output` _Text_ - Description of the expected output format or content. -- `dependencies` _Optional[List[Union[Text, AgentTask]]], optional_ - List of +- `dependencies` _Optional[List[Union[Text, WorkflowTask]]], optional_ - List of tasks or task names that must be completed before this task. Defaults to None. @@ -52,11 +52,11 @@ Initialize a new AgentTask instance. def to_dict() -> dict ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_task.py#L39) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_task.py#L40) Convert the task to a dictionary representation. -This method serializes the task data, converting any AgentTask dependencies +This method serializes the task data, converting any WorkflowTask dependencies to their name strings. **Returns**: @@ -71,19 +71,19 @@ to their name strings. ```python @classmethod -def from_dict(cls, data: dict) -> "AgentTask" +def from_dict(cls, data: dict) -> "WorkflowTask" ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_task.py#L66) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/agent_task.py#L67) -Create an AgentTask instance from a dictionary representation. +Create an WorkflowTask instance from a dictionary representation. **Arguments**: -- `data` - Dictionary containing AgentTask parameters +- `data` - Dictionary containing WorkflowTask parameters **Returns**: - AgentTask instance + WorkflowTask instance diff --git a/docs/api-reference/python/aixplain/modules/agent/evolve_param.md b/docs/api-reference/python/aixplain/modules/agent/evolve_param.md new file mode 100644 index 00000000..f80150a5 --- /dev/null +++ b/docs/api-reference/python/aixplain/modules/agent/evolve_param.md @@ -0,0 +1,155 @@ +--- +sidebar_label: evolve_param +title: aixplain.modules.agent.evolve_param +--- + +#### \_\_author\_\_ + +Copyright 2024 The aiXplain SDK authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: aiXplain Team +Date: December 2024 +Description: + EvolveParam Base Model Class for Agent and TeamAgent evolve functionality + +### EvolveParam Objects + +```python +@dataclass +class EvolveParam() +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/evolve_param.py#L29) + +Base model for evolve parameters used in Agent and TeamAgent evolution. + +**Attributes**: + +- `to_evolve` _bool_ - Whether to enable evolution. Defaults to False. +- `evolve_type` _Optional[EvolveType]_ - Type of evolve. +- `max_successful_generations` _int_ - Maximum number of successful generations. +- `max_failed_generation_retries` _int_ - Maximum number of failed generation retries. +- `max_iterations` _int_ - Maximum number of iterations. +- `max_non_improving_generations` _Optional[int]_ - Maximum number of non-improving generations. +- `llm` _Optional[Dict[str, Any]]_ - LLM configuration with all parameters. +- `additional_params` _Optional[Dict[str, Any]]_ - Additional parameters. + +#### \_\_post\_init\_\_ + +```python +def __post_init__() +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/evolve_param.py#L52) + +Validate parameters after initialization. + +#### validate + +```python +def validate() -> None +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/evolve_param.py#L56) + +Validate evolve parameters. + +**Raises**: + +- `ValueError` - If any parameter is invalid. + +#### from\_dict + +```python +@classmethod +def from_dict(cls, data: Union[Dict[str, Any], None]) -> "EvolveParam" +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/evolve_param.py#L107) + +Create EvolveParam instance from dictionary. + +**Arguments**: + +- `data` _Union[Dict[str, Any], None]_ - Dictionary containing evolve parameters. + + +**Returns**: + +- `EvolveParam` - Instance with parameters set from dictionary. + + +**Raises**: + +- `ValueError` - If data format is invalid. + +#### to\_dict + +```python +def to_dict() -> Dict[str, Any] +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/evolve_param.py#L160) + +Convert EvolveParam instance to dictionary for API calls. + +**Returns**: + + Dict[str, Any]: Dictionary representation with API-compatible keys. + +#### merge + +```python +def merge(other: Union[Dict[str, Any], "EvolveParam"]) -> "EvolveParam" +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/evolve_param.py#L188) + +Merge this EvolveParam with another set of parameters. + +**Arguments**: + +- `other` _Union[Dict[str, Any], EvolveParam]_ - Other parameters to merge. + + +**Returns**: + +- `EvolveParam` - New instance with merged parameters. + +#### validate\_evolve\_param + +```python +def validate_evolve_param( + evolve_param: Union[Dict[str, Any], EvolveParam, None]) -> EvolveParam +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/evolve_param.py#L242) + +Utility function to validate and convert evolve parameters. + +**Arguments**: + +- `evolve_param` _Union[Dict[str, Any], EvolveParam, None]_ - Input evolve parameters. + + +**Returns**: + +- `EvolveParam` - Validated EvolveParam instance. + + +**Raises**: + +- `ValueError` - If parameters are invalid. + diff --git a/docs/api-reference/python/aixplain/modules/agent/init.md b/docs/api-reference/python/aixplain/modules/agent/init.md index e8de644a..ff43c8fa 100644 --- a/docs/api-reference/python/aixplain/modules/agent/init.md +++ b/docs/api-reference/python/aixplain/modules/agent/init.md @@ -30,7 +30,7 @@ Description: class Agent(Model, DeployableMixin[Tool]) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L48) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L51) An advanced AI system that performs tasks using specialized tools from the aiXplain marketplace. @@ -77,12 +77,13 @@ def __init__(id: Text, cost: Optional[Dict] = None, status: AssetStatus = AssetStatus.DRAFT, tasks: List[AgentTask] = [], + workflow_tasks: List[WorkflowTask] = [], output_format: OutputFormat = OutputFormat.TEXT, expected_output: Optional[Union[BaseModel, Text, dict]] = None, **additional_info) -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L80) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L83) Initialize a new Agent instance. @@ -119,7 +120,7 @@ Initialize a new Agent instance. def validate(raise_exception: bool = False) -> bool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L194) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L207) Validate the Agent's configuration and mark its validity status. @@ -161,7 +162,7 @@ def run( ) -> AgentResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L265) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L278) Runs an agent call. @@ -189,21 +190,22 @@ Runs an agent call. ```python def run_async( - data: Optional[Union[Dict, Text]] = None, - query: Optional[Text] = None, - session_id: Optional[Text] = None, - history: Optional[List[Dict]] = None, - name: Text = "model_process", - parameters: Dict = {}, - content: Optional[Union[Dict[Text, Text], List[Text]]] = None, - max_tokens: int = 2048, - max_iterations: int = 5, - output_format: Optional[OutputFormat] = None, - expected_output: Optional[Union[BaseModel, Text, dict]] = None -) -> AgentResponse + data: Optional[Union[Dict, Text]] = None, + query: Optional[Text] = None, + session_id: Optional[Text] = None, + history: Optional[List[Dict]] = None, + name: Text = "model_process", + parameters: Dict = {}, + content: Optional[Union[Dict[Text, Text], List[Text]]] = None, + max_tokens: int = 2048, + max_iterations: int = 5, + output_format: Optional[OutputFormat] = None, + expected_output: Optional[Union[BaseModel, Text, dict]] = None, + evolve: Union[Dict[str, Any], EvolveParam, + None] = None) -> AgentResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L365) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L378) Runs asynchronously an agent call. @@ -220,10 +222,12 @@ Runs asynchronously an agent call. - `max_iterations` _int, optional_ - maximum number of iterations between the agent and the tools. Defaults to 10. - `output_format` _OutputFormat, optional_ - response format. If not provided, uses the format set during initialization. - `query`0 _Union[BaseModel, Text, dict], optional_ - expected output. Defaults to None. +- `output_format` _ResponseFormat, optional_ - response format. Defaults to TEXT. +- `query`2 _Union[Dict[str, Any], EvolveParam, None], optional_ - evolve the agent configuration. Can be a dictionary, EvolveParam instance, or None. **Returns**: -- `query`1 - polling URL in response +- `query`3 - polling URL in response #### from\_dict @@ -232,7 +236,7 @@ Runs asynchronously an agent call. def from_dict(cls, data: Dict) -> "Agent" ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L527) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L545) Create an Agent instance from a dictionary representation. @@ -251,7 +255,7 @@ Create an Agent instance from a dictionary representation. def delete() -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L602) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L620) Delete this Agent from the aiXplain platform. @@ -272,7 +276,7 @@ Agent is being used by any team agents. def update() -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L665) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L683) Update the Agent's configuration on the aiXplain platform. @@ -296,7 +300,7 @@ in favor of the save() method. def save() -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L712) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L730) Save the Agent's current configuration to the aiXplain platform. @@ -313,7 +317,7 @@ It is the preferred method for updating an Agent's settings. def __repr__() -> str ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L723) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L741) Return a string representation of the Agent. @@ -321,3 +325,61 @@ Return a string representation of the Agent. - `str` - A string in the format "Agent: <name> (id=<id>)". +#### evolve\_async + +```python +def evolve_async(evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None) -> AgentResponse +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L749) + +Asynchronously evolve the Agent and return a polling URL in the AgentResponse. + +**Arguments**: + +- `evolve_type` _Union[EvolveType, str]_ - Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. +- `max_successful_generations` _int_ - Maximum number of successful generations to evolve. Defaults to 3. +- `max_failed_generation_retries` _int_ - Maximum retry attempts for failed generations. Defaults to 3. +- `max_iterations` _int_ - Maximum number of iterations. Defaults to 50. +- `max_non_improving_generations` _Optional[int]_ - Stop condition parameter for non-improving generations. Defaults to 2, can be None. +- `llm` _Optional[Union[Text, LLM]]_ - LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + +**Returns**: + +- `AgentResponse` - Response containing polling URL and status. + +#### evolve + +```python +def evolve(evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None) -> AgentResponse +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/agent/__init__.py#L788) + +Synchronously evolve the Agent and poll for the result. + +**Arguments**: + +- `evolve_type` _Union[EvolveType, str]_ - Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. +- `max_successful_generations` _int_ - Maximum number of successful generations to evolve. Defaults to 3. +- `max_failed_generation_retries` _int_ - Maximum retry attempts for failed generations. Defaults to 3. +- `max_iterations` _int_ - Maximum number of iterations. Defaults to 50. +- `max_non_improving_generations` _Optional[int]_ - Stop condition parameter for non-improving generations. Defaults to 2, can be None. +- `llm` _Optional[Union[Text, LLM]]_ - LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + +**Returns**: + +- `AgentResponse` - Final response from the evolution process. + diff --git a/docs/api-reference/python/aixplain/modules/model/index_model.md b/docs/api-reference/python/aixplain/modules/model/index_model.md index 15b2f421..bf8cb910 100644 --- a/docs/api-reference/python/aixplain/modules/model/index_model.md +++ b/docs/api-reference/python/aixplain/modules/model/index_model.md @@ -9,7 +9,7 @@ title: aixplain.modules.model.index_model class IndexFilterOperator(Enum) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L16) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L17) Enumeration of operators available for filtering index records. @@ -33,7 +33,7 @@ filters for searching and retrieving records from an index. class IndexFilter() ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L42) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L43) A class representing a filter for querying index records. @@ -53,7 +53,7 @@ def __init__(field: str, value: str, operator: Union[IndexFilterOperator, str]) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L58) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L59) Initialize a new IndexFilter instance. @@ -69,7 +69,7 @@ Initialize a new IndexFilter instance. def to_dict() ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L70) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L71) Convert the filter to a dictionary representation. @@ -84,7 +84,7 @@ Convert the filter to a dictionary representation. class Splitter() ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L84) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L85) A class for configuring how documents should be split during indexing. @@ -108,7 +108,7 @@ def __init__(split: bool = False, split_overlap: int = 0) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L98) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L99) Initialize a new Splitter instance. @@ -127,7 +127,7 @@ Initialize a new Splitter instance. class IndexModel(Model) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L121) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L122) #### \_\_init\_\_ @@ -146,7 +146,7 @@ def __init__(id: Text, **additional_info) -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L122) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L123) Initialize a new IndexModel instance. @@ -176,7 +176,7 @@ Initialize a new IndexModel instance. def to_dict() -> Dict ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L185) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L184) Convert the IndexModel instance to a dictionary representation. @@ -196,7 +196,7 @@ def search(query: str, filters: List[IndexFilter] = []) -> ModelResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L201) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L200) Search for documents in the index @@ -220,17 +220,17 @@ Search for documents in the index #### upsert ```python -def upsert(documents: List[Record], +def upsert(documents: Union[List[Record], str], splitter: Optional[Splitter] = None) -> ModelResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L234) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L233) Upsert documents into the index **Arguments**: -- `documents` _List[Record]_ - List of documents to be upserted +- `documents` _Union[List[Record], str]_ - List of documents to be upserted or a file path - `splitter` _Splitter, optional_ - Splitter to be applied. Defaults to None. @@ -243,15 +243,17 @@ Upsert documents into the index index_model.upsert([Record(value="Hello, world!", value_type="text", uri="", id="1", attributes=\{})]) index_model.upsert([Record(value="Hello, world!", value_type="text", uri="", id="1", attributes=\{})], splitter=Splitter(split=True, split_by=SplittingOptions.WORD, split_length=1, split_overlap=0)) + index_model.upsert("my_file.pdf") + index_model.upsert("my_file.pdf", splitter=Splitter(split=True, split_by=SplittingOptions.WORD, split_length=400, split_overlap=50)) Splitter in the above example is optional and can be used to split the documents into smaller chunks. #### count ```python -def count() -> float +def count() -> int ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L275) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L278) Get the total number of documents in the index. @@ -276,7 +278,7 @@ Get the total number of documents in the index. def get_record(record_id: Text) -> ModelResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L294) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L297) Get a document from the index. @@ -305,7 +307,7 @@ Get a document from the index. def delete_record(record_id: Text) -> ModelResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L316) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L319) Delete a document from the index. @@ -328,13 +330,73 @@ Delete a document from the index. >>> index_model.delete_record("123") +#### prepare\_record\_from\_file + +```python +def prepare_record_from_file(file_path: str, file_id: str = None) -> Record +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L341) + +Prepare a record from a file. + +**Arguments**: + +- `file_path` _str_ - The path to the file to be processed. +- `file_id` _str, optional_ - The ID to assign to the record. If not provided, a unique ID is generated. + + +**Returns**: + +- `Record` - A Record object containing the file's content and metadata. + + +**Raises**: + +- `Exception` - If the file cannot be parsed. + + +**Example**: + + >>> record = index_model.prepare_record_from_file("/path/to/file.txt") + +#### parse\_file + +```python +@staticmethod +def parse_file(file_path: str) -> ModelResponse +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L364) + +Parse a file using the Docling model. + +**Arguments**: + +- `file_path` _str_ - The path to the file to be parsed. + + +**Returns**: + +- `ModelResponse` - The response containing the parsed file content. + + +**Raises**: + +- `Exception` - If the file does not exist or cannot be parsed. + + +**Example**: + + >>> response = IndexModel.parse_file("/path/to/file.pdf") + #### retrieve\_records\_with\_filter ```python def retrieve_records_with_filter(filter: IndexFilter) -> ModelResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L338) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L398) Retrieve records from the index that match the given filter. @@ -365,7 +427,7 @@ Retrieve records from the index that match the given filter. def delete_records_by_date(date: float) -> ModelResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L362) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/index_model.py#L422) Delete records from the index that match the given date. diff --git a/docs/api-reference/python/aixplain/modules/model/utils.md b/docs/api-reference/python/aixplain/modules/model/utils.md index ff005850..c273b6f6 100644 --- a/docs/api-reference/python/aixplain/modules/model/utils.md +++ b/docs/api-reference/python/aixplain/modules/model/utils.md @@ -11,7 +11,7 @@ def build_payload(data: Union[Text, Dict], stream: Optional[bool] = None) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L10) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L81) Build a JSON payload for API requests. @@ -48,7 +48,7 @@ ensures proper JSON serialization. def call_run_endpoint(url: Text, api_key: Text, payload: Dict) -> Dict ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L63) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L134) Call a model execution endpoint and handle the response. @@ -84,7 +84,7 @@ various response scenarios, and provides appropriate error handling. def parse_code(code: Union[Text, Callable]) -> Tuple[Text, List, Text, Text] ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L127) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L198) Parse and process code for utility model creation. @@ -131,7 +131,7 @@ def parse_code_decorated( code: Union[Text, Callable]) -> Tuple[Text, List, Text, Text] ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L238) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L309) Parse and process code that may be decorated with @utility_tool. @@ -184,7 +184,7 @@ It supports various input formats and provides robust parameter extraction. def is_supported_image_type(value: str) -> bool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L462) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/model/utils.py#L523) Check if a file path or URL points to a supported image format. diff --git a/docs/api-reference/python/aixplain/modules/team_agent/evolver_response_data.md b/docs/api-reference/python/aixplain/modules/team_agent/evolver_response_data.md new file mode 100644 index 00000000..ab1bed53 --- /dev/null +++ b/docs/api-reference/python/aixplain/modules/team_agent/evolver_response_data.md @@ -0,0 +1,146 @@ +--- +sidebar_label: evolver_response_data +title: aixplain.modules.team_agent.evolver_response_data +--- + +### EvolverResponseData Objects + +```python +class EvolverResponseData() +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/evolver_response_data.py#L7) + +Container for team agent evolution response data. + +This class encapsulates all the data returned from a team agent evolution +process, including the evolved agent, code, evaluation reports, and +historical archive information. + +**Attributes**: + +- `evolved_agent` _TeamAgent_ - The evolved team agent instance. +- `current_code` _str_ - The current YAML code representation of the agent. +- `evaluation_report` _str_ - Report containing evaluation results. +- `comparison_report` _str_ - Report comparing different agent versions. +- `criteria` _str_ - Criteria used for evolution evaluation. +- `archive` _List[str]_ - Historical archive of previous versions. +- `current_output` _str_ - Current output from the agent. + +#### \_\_init\_\_ + +```python +def __init__(evolved_agent: "TeamAgent", + current_code: Text, + evaluation_report: Text, + comparison_report: Text, + criteria: Text, + archive: List[Text], + current_output: Text = "") -> None +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/evolver_response_data.py#L24) + +Initialize the EvolverResponseData instance. + +**Arguments**: + +- `evolved_agent` _TeamAgent_ - The evolved team agent instance. +- `current_code` _str_ - The current YAML code representation. +- `evaluation_report` _str_ - Report containing evaluation results. +- `comparison_report` _str_ - Report comparing different versions. +- `criteria` _str_ - Criteria used for evolution evaluation. +- `archive` _List[str]_ - Historical archive of previous versions. +- `current_output` _str, optional_ - Current output from the agent. + Defaults to empty string. + +#### from\_dict + +```python +@classmethod +def from_dict(cls, data: Dict[str, Any], llm_id: Text, + api_key: Text) -> "EvolverResponseData" +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/evolver_response_data.py#L56) + +Create an EvolverResponseData instance from a dictionary. + +**Arguments**: + +- `data` _Dict[str, Any]_ - Dictionary containing the response data. +- `llm_id` _str_ - The LLM identifier for building the team agent. +- `api_key` _str_ - API key for accessing the LLM service. + + +**Returns**: + +- `EvolverResponseData` - A new instance created from the dictionary data. + +#### to\_dict + +```python +def to_dict() -> Dict[str, Any] +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/evolver_response_data.py#L82) + +Convert the EvolverResponseData instance to a dictionary. + +**Returns**: + + Dict[str, Any]: Dictionary representation of the instance data. + +#### \_\_getitem\_\_ + +```python +def __getitem__(key: str) -> Any +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/evolver_response_data.py#L99) + +Get an attribute value using dictionary-style access. + +**Arguments**: + +- `key` _str_ - The attribute name to retrieve. + + +**Returns**: + +- `Any` - The value of the requested attribute, or None if not found. + +#### \_\_setitem\_\_ + +```python +def __setitem__(key: str, value: Any) -> None +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/evolver_response_data.py#L111) + +Set an attribute value using dictionary-style access. + +**Arguments**: + +- `key` _str_ - The attribute name to set. +- `value` _Any_ - The value to assign to the attribute. + + +**Raises**: + +- `KeyError` - If the key is not a valid attribute of the class. + +#### \_\_repr\_\_ + +```python +def __repr__() -> str +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/evolver_response_data.py#L127) + +Return a string representation of the EvolverResponseData instance. + +**Returns**: + +- `str` - A string representation showing key attributes of the instance. + diff --git a/docs/api-reference/python/aixplain/modules/team_agent/init.md b/docs/api-reference/python/aixplain/modules/team_agent/init.md index 41a568a0..2a3ba120 100644 --- a/docs/api-reference/python/aixplain/modules/team_agent/init.md +++ b/docs/api-reference/python/aixplain/modules/team_agent/init.md @@ -30,7 +30,7 @@ Description: class InspectorTarget(str, Enum) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L52) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L55) Target stages for inspector validation in the team agent pipeline. @@ -49,7 +49,7 @@ validate and ensure quality of the team agent's operation. def __str__() ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L68) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L71) Return the string value of the enum member. @@ -63,7 +63,7 @@ Return the string value of the enum member. class TeamAgent(Model, DeployableMixin[Agent]) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L77) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L80) Advanced AI system capable of using multiple agents to perform a variety of tasks. @@ -102,7 +102,7 @@ def run( ) -> AgentResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L183) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L187) Runs a team agent call. @@ -130,21 +130,22 @@ Runs a team agent call. ```python def run_async( - data: Optional[Union[Dict, Text]] = None, - query: Optional[Text] = None, - session_id: Optional[Text] = None, - history: Optional[List[Dict]] = None, - name: Text = "model_process", - parameters: Dict = {}, - content: Optional[Union[Dict[Text, Text], List[Text]]] = None, - max_tokens: int = 2048, - max_iterations: int = 30, - output_format: Optional[OutputFormat] = None, - expected_output: Optional[Union[BaseModel, Text, dict]] = None -) -> AgentResponse + data: Optional[Union[Dict, Text]] = None, + query: Optional[Text] = None, + session_id: Optional[Text] = None, + history: Optional[List[Dict]] = None, + name: Text = "model_process", + parameters: Dict = {}, + content: Optional[Union[Dict[Text, Text], List[Text]]] = None, + max_tokens: int = 2048, + max_iterations: int = 30, + output_format: Optional[OutputFormat] = None, + expected_output: Optional[Union[BaseModel, Text, dict]] = None, + evolve: Union[Dict[str, Any], EvolveParam, + None] = None) -> AgentResponse ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L273) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L277) Runs asynchronously a Team Agent call. @@ -161,10 +162,11 @@ Runs asynchronously a Team Agent call. - `max_iterations` _int, optional_ - maximum number of iterations between the agents. Defaults to 30. - `output_format` _OutputFormat, optional_ - response format. If not provided, uses the format set during initialization. - `query`0 _Union[BaseModel, Text, dict], optional_ - expected output. Defaults to None. +- `query`1 _Union[Dict[str, Any], EvolveParam, None], optional_ - evolve the team agent configuration. Can be a dictionary, EvolveParam instance, or None. **Returns**: -- `query`1 - polling URL in response +- `query`2 - polling URL in response #### delete @@ -172,7 +174,7 @@ Runs asynchronously a Team Agent call. def delete() -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L402) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L472) Delete Corpus service @@ -182,7 +184,7 @@ Delete Corpus service def to_dict() -> Dict ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L461) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L531) Convert the TeamAgent instance to a dictionary representation. @@ -206,7 +208,7 @@ or transmission. - supplier (str): The supplier code - version (str): The version number - status (str): The current status - - role (str): The team agent's instructions + - instructions (str): The team agent's instructions #### from\_dict @@ -215,7 +217,7 @@ or transmission. def from_dict(cls, data: Dict) -> "TeamAgent" ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L509) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L579) Create a TeamAgent instance from a dictionary representation. @@ -234,7 +236,7 @@ Create a TeamAgent instance from a dictionary representation. def validate(raise_exception: bool = False) -> bool ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L630) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L704) Validate the TeamAgent configuration. @@ -271,7 +273,7 @@ including name format, LLM compatibility, and agent validity. def update() -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L666) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L740) Update the TeamAgent in the backend. @@ -300,7 +302,7 @@ backend system. It is deprecated in favor of the save() method. def save() -> None ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L718) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L792) Save the Agent. @@ -310,7 +312,7 @@ Save the Agent. def __repr__() ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L722) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L796) Return a string representation of the TeamAgent. @@ -318,3 +320,61 @@ Return a string representation of the TeamAgent. - `str` - A string in the format "TeamAgent: <name> (id=<id>)". +#### evolve\_async + +```python +def evolve_async(evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None) -> AgentResponse +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L804) + +Asynchronously evolve the Team Agent and return a polling URL in the AgentResponse. + +**Arguments**: + +- `evolve_type` _Union[EvolveType, str]_ - Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. +- `max_successful_generations` _int_ - Maximum number of successful generations to evolve. Defaults to 3. +- `max_failed_generation_retries` _int_ - Maximum retry attempts for failed generations. Defaults to 3. +- `max_iterations` _int_ - Maximum number of iterations. Defaults to 50. +- `max_non_improving_generations` _Optional[int]_ - Stop condition parameter for non-improving generations. Defaults to 2, can be None. +- `llm` _Optional[Union[Text, LLM]]_ - LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + +**Returns**: + +- `AgentResponse` - Response containing polling URL and status. + +#### evolve + +```python +def evolve(evolve_type: Union[EvolveType, str] = EvolveType.TEAM_TUNING, + max_successful_generations: int = 3, + max_failed_generation_retries: int = 3, + max_iterations: int = 50, + max_non_improving_generations: Optional[int] = 2, + llm: Optional[Union[Text, LLM]] = None) -> AgentResponse +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/__init__.py#L844) + +Synchronously evolve the Team Agent and poll for the result. + +**Arguments**: + +- `evolve_type` _Union[EvolveType, str]_ - Type of evolution (TEAM_TUNING or INSTRUCTION_TUNING). Defaults to TEAM_TUNING. +- `max_successful_generations` _int_ - Maximum number of successful generations to evolve. Defaults to 3. +- `max_failed_generation_retries` _int_ - Maximum retry attempts for failed generations. Defaults to 3. +- `max_iterations` _int_ - Maximum number of iterations. Defaults to 50. +- `max_non_improving_generations` _Optional[int]_ - Stop condition parameter for non-improving generations. Defaults to 2, can be None. +- `llm` _Optional[Union[Text, LLM]]_ - LLM to use for evolution. Can be an LLM ID string or LLM object. Defaults to None. + + +**Returns**: + +- `AgentResponse` - Final response from the evolution process. + diff --git a/docs/api-reference/python/aixplain/modules/team_agent/inspector.md b/docs/api-reference/python/aixplain/modules/team_agent/inspector.md index f158f243..b83c8b37 100644 --- a/docs/api-reference/python/aixplain/modules/team_agent/inspector.md +++ b/docs/api-reference/python/aixplain/modules/team_agent/inspector.md @@ -4,6 +4,7 @@ title: aixplain.modules.team_agent.inspector --- Pre-defined agent for inspecting the data flow within a team agent. +WARNING: This feature is currently in private beta. WARNING: This feature is currently in private beta. @@ -29,13 +30,33 @@ team = TeamAgent( GPT-4.1 Nano +### InspectorAction Objects + +```python +class InspectorAction(str, Enum) +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L39) + +Inspector's decision on the next action. + +### InspectorOutput Objects + +```python +class InspectorOutput(BaseModel) +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L49) + +Inspector's output. + ### InspectorAuto Objects ```python class InspectorAuto(str, Enum) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L35) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L59) A list of keywords for inspectors configured automatically in the backend. @@ -45,7 +66,7 @@ A list of keywords for inspectors configured automatically in the backend. def get_name() -> Text ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L40) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L64) Get the standardized name for this inspector type. @@ -62,7 +83,7 @@ the enum value with "inspector_". class InspectorPolicy(str, Enum) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L52) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L76) Which action to take if the inspector gives negative feedback. @@ -78,13 +99,66 @@ stop execution adjust execution according to feedback +#### validate\_policy\_callable + +```python +def validate_policy_callable(policy_func: Callable) -> bool +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L84) + +Validate that the policy callable meets the required constraints. + +#### callable\_to\_code\_string + +```python +def callable_to_code_string(policy_func: Callable) -> str +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L106) + +Convert a callable policy function to a code string for serialization. + +#### code\_string\_to\_callable + +```python +def code_string_to_callable(code_string: str) -> Callable +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L124) + +Convert a code string back to a callable function for deserialization. + +#### get\_policy\_source + +```python +def get_policy_source(func: Callable) -> Optional[str] +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L259) + +Get the source code of a policy function. + +This function tries to retrieve the source code of a policy function. +It first checks if the function has a stored _source_code attribute (for functions +created via code_string_to_callable), then falls back to inspect.getsource(). + +**Arguments**: + +- `func` - The function to get source code for + + +**Returns**: + + The source code string if available, None otherwise + ### Inspector Objects ```python class Inspector(ModelWithParams) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L60) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L280) Pre-defined agent for inspecting the data flow within a team agent. @@ -95,7 +169,9 @@ The model should be onboarded before using it as an inspector. - `name` - The name of the inspector. - `model_id` - The ID of the model to wrap. - `model_params` - The configuration for the model. -- `policy` - The policy for the inspector. Default is ADAPTIVE. +- `policy` - The policy for the inspector. Can be InspectorPolicy enum or a callable function. + If callable, must have name "process_response", arguments "model_response" and "input_content" (both strings), + and return InspectorAction. Default is ADAPTIVE. #### \_\_init\_\_ @@ -103,7 +179,7 @@ The model should be onboarded before using it as an inspector. def __init__(*args, **kwargs) ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L77) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L299) Initialize an Inspector instance. @@ -134,7 +210,7 @@ auto model ID. def validate_name(cls, v: Text) -> Text ``` -[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L102) +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L324) Validate the inspector name field. @@ -154,3 +230,24 @@ This validator ensures that the inspector's name is not empty. - `ValueError` - If the name is an empty string. +#### model\_dump + +```python +def model_dump(by_alias: bool = False, **kwargs) -> Dict +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L353) + +Override model_dump to handle callable policy serialization. + +#### model\_validate + +```python +@classmethod +def model_validate(cls, data: Union[Dict, "Inspector"]) -> "Inspector" +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/modules/team_agent/inspector.py#L368) + +Override model_validate to handle callable policy deserialization. + diff --git a/docs/api-reference/python/aixplain/utils/evolve_utils.md b/docs/api-reference/python/aixplain/utils/evolve_utils.md new file mode 100644 index 00000000..e9254a70 --- /dev/null +++ b/docs/api-reference/python/aixplain/utils/evolve_utils.md @@ -0,0 +1,25 @@ +--- +sidebar_label: evolve_utils +title: aixplain.utils.evolve_utils +--- + +#### create\_llm\_dict + +```python +def create_llm_dict( + llm: Optional[Union[Text, LLM]]) -> Optional[Dict[str, Any]] +``` + +[[view_source]](https://github.com/aixplain/aiXplain/blob/main/aixplain/utils/evolve_utils.py#L5) + +Create a dictionary representation of an LLM for evolution parameters. + +**Arguments**: + +- `llm` - Either an LLM ID string or an LLM object instance. + + +**Returns**: + + Dictionary with LLM information if llm is provided, None otherwise. + diff --git a/docs/api-reference/python/api_sidebar.js b/docs/api-reference/python/api_sidebar.js index 476b437f..a601c569 100644 --- a/docs/api-reference/python/api_sidebar.js +++ b/docs/api-reference/python/api_sidebar.js @@ -28,6 +28,7 @@ "api-reference/python/aixplain/enums/database_source", "api-reference/python/aixplain/enums/embedding_model", "api-reference/python/aixplain/enums/error_handler", + "api-reference/python/aixplain/enums/evolve_type", "api-reference/python/aixplain/enums/file_type", "api-reference/python/aixplain/enums/function", "api-reference/python/aixplain/enums/function_type", @@ -160,6 +161,7 @@ "api-reference/python/aixplain/modules/agent/agent_response", "api-reference/python/aixplain/modules/agent/agent_response_data", "api-reference/python/aixplain/modules/agent/agent_task", + "api-reference/python/aixplain/modules/agent/evolve_param", "api-reference/python/aixplain/modules/agent/model_with_params", "api-reference/python/aixplain/modules/agent/output_format", "api-reference/python/aixplain/modules/agent/utils" @@ -222,6 +224,7 @@ { "items": [ "api-reference/python/aixplain/modules/team_agent/init", + "api-reference/python/aixplain/modules/team_agent/evolver_response_data", "api-reference/python/aixplain/modules/team_agent/inspector" ], "label": "aixplain.modules.team_agent", @@ -269,6 +272,7 @@ "api-reference/python/aixplain/utils/cache_utils", "api-reference/python/aixplain/utils/config", "api-reference/python/aixplain/utils/convert_datatype_utils", + "api-reference/python/aixplain/utils/evolve_utils", "api-reference/python/aixplain/utils/file_utils", "api-reference/python/aixplain/utils/llm_utils", "api-reference/python/aixplain/utils/request_utils", From 480066de8437079168e317e04f6b0a6568c40dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20G=C3=BCnd=C3=BCz?= Date: Thu, 11 Sep 2025 23:54:56 +0300 Subject: [PATCH 5/5] HOTFIX--MCP-deploy-method-missing (#680) * added deploy method to connection tool * BUG-620: fix mcp deploy error --- .pre-commit-config.yaml | 35 +--- aixplain/exceptions/__init__.py | 12 +- aixplain/exceptions/types.py | 79 ++++++++ aixplain/modules/agent/__init__.py | 53 ++++-- aixplain/modules/agent/tool/__init__.py | 19 +- .../agent/tool/custom_python_code_tool.py | 22 +-- aixplain/modules/agent/tool/model_tool.py | 58 +++--- aixplain/modules/agent/tool/pipeline_tool.py | 17 +- .../agent/tool/python_interpreter_tool.py | 16 +- aixplain/modules/agent/tool/sql_tool.py | 30 +-- aixplain/modules/mixins.py | 42 ++-- aixplain/modules/model/connection.py | 41 +++- .../functional/agent/agent_mcp_deploy_test.py | 180 ++++++++++++++++++ 13 files changed, 457 insertions(+), 147 deletions(-) create mode 100644 tests/functional/agent/agent_mcp_deploy_test.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c7ad1c08..2a567d6f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,22 +1,4 @@ repos: - - repo: local - hooks: - - id: pytest-check - name: pytest-check - entry: coverage run --source=. -m pytest tests/unit - language: python - pass_filenames: false - types: [python] - always_run: true - - - repo: https://github.com/psf/black - rev: 25.1.0 - hooks: - - id: black - language_version: python3 - args: # arguments to configure black - - --line-length=128 - - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 # Use the latest version hooks: @@ -25,16 +7,19 @@ repos: - id: check-merge-conflict - id: check-added-large-files - - repo: https://github.com/pycqa/flake8 - rev: 7.2.0 - hooks: - - id: flake8 - args: # arguments to configure flake8 - - --ignore=E402,E501,E203,W503 - - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.12.12 hooks: - id: ruff args: [--fix] - id: ruff-format + + - repo: local + hooks: + - id: pytest-check + name: pytest-check + entry: coverage run --source=. -m pytest tests/unit + language: python + pass_filenames: false + types: [python] + always_run: true diff --git a/aixplain/exceptions/__init__.py b/aixplain/exceptions/__init__.py index 5d645c62..658778a8 100644 --- a/aixplain/exceptions/__init__.py +++ b/aixplain/exceptions/__init__.py @@ -1,5 +1,4 @@ -""" -Error message registry for aiXplain SDK. +"""Error message registry for aiXplain SDK. This module maintains a centralized registry of error messages used throughout the aiXplain ecosystem. It allows developers to look up existing error messages and reuse them instead of creating new ones. @@ -9,6 +8,7 @@ AixplainBaseException, AuthenticationError, ValidationError, + AlreadyDeployedError, ResourceError, BillingError, SupplierError, @@ -19,12 +19,11 @@ def get_error_from_status_code(status_code: int, error_details: str = None) -> AixplainBaseException: - """ - Map HTTP status codes to appropriate exception types. + """Map HTTP status codes to appropriate exception types. Args: status_code (int): The HTTP status code to map. - default_message (str, optional): The default message to use if no specific message is available. + error_details (str, optional): Additional error details to include in the message. Returns: AixplainBaseException: An exception of the appropriate type. @@ -112,5 +111,6 @@ def get_error_from_status_code(status_code: int, error_details: str = None) -> A # Catch-all for other client/server errors category = "Client" if 400 <= status_code < 500 else "Server" return InternalError( - message=f"Unspecified {category} Error (Status {status_code}) {error_details}".strip(), status_code=status_code + message=f"Unspecified {category} Error (Status {status_code}) {error_details}".strip(), + status_code=status_code, ) diff --git a/aixplain/exceptions/types.py b/aixplain/exceptions/types.py index 5162662f..e8df5fe5 100644 --- a/aixplain/exceptions/types.py +++ b/aixplain/exceptions/types.py @@ -1,3 +1,5 @@ +"""Exception types and error handling for the aiXplain SDK.""" + from enum import Enum from typing import Optional, Dict, Any @@ -121,6 +123,17 @@ def __init__( retry_recommended: bool = False, error_code: Optional[ErrorCode] = None, ): + """Initialize the base exception with structured error information. + + Args: + message: Error message describing the issue. + category: Category of the error (default: UNKNOWN). + severity: Severity level of the error (default: ERROR). + status_code: HTTP status code if applicable. + details: Additional error context and details. + retry_recommended: Whether retrying the operation might succeed. + error_code: Standardized error code for the exception. + """ self.message = message self.category = category self.severity = severity @@ -163,6 +176,12 @@ class AuthenticationError(AixplainBaseException): """Raised when authentication fails.""" def __init__(self, message: str, **kwargs): + """Initialize authentication error. + + Args: + message: Error message describing the authentication issue. + **kwargs: Additional keyword arguments passed to parent class. + """ super().__init__( message=message, category=ErrorCategory.AUTHENTICATION, @@ -177,6 +196,12 @@ class ValidationError(AixplainBaseException): """Raised when input validation fails.""" def __init__(self, message: str, **kwargs): + """Initialize validation error. + + Args: + message: Error message describing the validation issue. + **kwargs: Additional keyword arguments passed to parent class. + """ super().__init__( message=message, category=ErrorCategory.VALIDATION, @@ -187,10 +212,34 @@ def __init__(self, message: str, **kwargs): ) +class AlreadyDeployedError(AixplainBaseException): + """Raised when attempting to deploy an asset that is already deployed.""" + + def __init__(self, message: str, **kwargs): + """Initialize already deployed error. + + Args: + message: Error message describing the deployment state conflict. + **kwargs: Additional keyword arguments passed to parent class. + """ + super().__init__( + message=message, + retry_recommended=kwargs.pop("retry_recommended", False), + error_code=ErrorCode.AX_VAL_ERROR, + **kwargs, + ) + + class ResourceError(AixplainBaseException): """Raised when a resource is unavailable.""" def __init__(self, message: str, **kwargs): + """Initialize resource error. + + Args: + message: Error message describing the resource issue. + **kwargs: Additional keyword arguments passed to parent class. + """ super().__init__( message=message, category=ErrorCategory.RESOURCE, @@ -205,6 +254,12 @@ class BillingError(AixplainBaseException): """Raised when there are billing issues.""" def __init__(self, message: str, **kwargs): + """Initialize billing error. + + Args: + message: Error message describing the billing issue. + **kwargs: Additional keyword arguments passed to parent class. + """ super().__init__( message=message, category=ErrorCategory.BILLING, @@ -219,6 +274,12 @@ class SupplierError(AixplainBaseException): """Raised when there are issues with external suppliers.""" def __init__(self, message: str, **kwargs): + """Initialize supplier error. + + Args: + message: Error message describing the supplier issue. + **kwargs: Additional keyword arguments passed to parent class. + """ super().__init__( message=message, category=ErrorCategory.SUPPLIER, @@ -233,6 +294,12 @@ class NetworkError(AixplainBaseException): """Raised when there are network connectivity issues.""" def __init__(self, message: str, **kwargs): + """Initialize network error. + + Args: + message: Error message describing the network issue. + **kwargs: Additional keyword arguments passed to parent class. + """ super().__init__( message=message, category=ErrorCategory.NETWORK, @@ -247,6 +314,12 @@ class ServiceError(AixplainBaseException): """Raised when a service is unavailable.""" def __init__(self, message: str, **kwargs): + """Initialize service error. + + Args: + message: Error message describing the service issue. + **kwargs: Additional keyword arguments passed to parent class. + """ super().__init__( message=message, category=ErrorCategory.SERVICE, @@ -261,6 +334,12 @@ class InternalError(AixplainBaseException): """Raised when there is an internal system error.""" def __init__(self, message: str, **kwargs): + """Initialize internal error. + + Args: + message: Error message describing the internal issue. + **kwargs: Additional keyword arguments passed to parent class. + """ # Server errors (5xx) should generally be retryable status_code = kwargs.get("status_code") retry_recommended = kwargs.pop("retry_recommended", False) diff --git a/aixplain/modules/agent/__init__.py b/aixplain/modules/agent/__init__.py index 23a39c9a..1b1f64f3 100644 --- a/aixplain/modules/agent/__init__.py +++ b/aixplain/modules/agent/__init__.py @@ -1,6 +1,8 @@ -__author__ = "aiXplain" +"""Agent module for aiXplain SDK. + +This module provides the Agent class and related functionality for creating and managing +AI agents that can execute tasks using various tools and models. -""" Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +22,8 @@ Description: Agentification Class """ + +__author__ = "aiXplain" import json import logging import re @@ -33,7 +37,7 @@ from aixplain.modules.model import Model from aixplain.modules.agent.agent_task import WorkflowTask, AgentTask from aixplain.modules.agent.output_format import OutputFormat -from aixplain.modules.agent.tool import Tool +from aixplain.modules.agent.tool import Tool, DeployableTool from aixplain.modules.agent.agent_response import AgentResponse from aixplain.modules.agent.agent_response_data import AgentResponseData from aixplain.modules.agent.utils import process_variables, validate_history @@ -48,7 +52,7 @@ import warnings -class Agent(Model, DeployableMixin[Tool]): +class Agent(Model, DeployableMixin[Union[Tool, DeployableTool]]): """An advanced AI system that performs tasks using specialized tools from the aiXplain marketplace. This class represents an AI agent that can understand natural language instructions, @@ -124,6 +128,8 @@ def __init__( Defaults to AssetStatus.DRAFT. tasks (List[AgentTask], optional): List of tasks the Agent can perform. Defaults to empty list. + workflow_tasks (List[WorkflowTask], optional): List of workflow tasks + the Agent can execute. Defaults to empty list. output_format (OutputFormat, optional): default output format for agent responses. Defaults to OutputFormat.TEXT. expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None. **additional_info: Additional configuration parameters. @@ -144,7 +150,8 @@ def __init__( self.status = status if tasks: warnings.warn( - "The 'tasks' parameter is deprecated and will be removed in a future version. " "Use 'workflow_tasks' instead.", + "The 'tasks' parameter is deprecated and will be removed in a future version. " + "Use 'workflow_tasks' instead.", DeprecationWarning, stacklevel=2, ) @@ -171,9 +178,9 @@ def _validate(self) -> None: from aixplain.utils.llm_utils import get_llm_instance # validate name - assert ( - re.match(r"^[a-zA-Z0-9 \-\(\)]*$", self.name) is not None - ), "Agent Creation Error: Agent name contains invalid characters. Only alphanumeric characters, spaces, hyphens, and brackets are allowed." + assert re.match(r"^[a-zA-Z0-9 \-\(\)]*$", self.name) is not None, ( + "Agent Creation Error: Agent name contains invalid characters. Only alphanumeric characters, spaces, hyphens, and brackets are allowed." + ) llm = get_llm_instance(self.llm_id, api_key=self.api_key) @@ -233,6 +240,14 @@ def validate(self, raise_exception: bool = False) -> bool: return self.is_valid def generate_session_id(self, history: list = None) -> str: + """Generate a unique session ID for agent conversations. + + Args: + history (list, optional): Previous conversation history. Defaults to None. + + Returns: + str: A unique session identifier based on timestamp and random components. + """ if history: validate_history(history) timestamp = datetime.now().strftime("%Y%m%d%H%M%S") @@ -307,6 +322,7 @@ def run( max_iterations (int, optional): maximum number of iterations between the agent and the tools. Defaults to 10. output_format (OutputFormat, optional): response format. If not provided, uses the format set during initialization. expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None. + Returns: Dict: parsed output from model """ @@ -406,10 +422,10 @@ def run_async( expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None. output_format (ResponseFormat, optional): response format. Defaults to TEXT. evolve (Union[Dict[str, Any], EvolveParam, None], optional): evolve the agent configuration. Can be a dictionary, EvolveParam instance, or None. + Returns: dict: polling URL in response """ - if session_id is not None and history is not None: raise ValueError("Provide either `session_id` or `history`, not both.") @@ -434,7 +450,9 @@ def run_async( assert data is not None or query is not None, "Either 'data' or 'query' must be provided." if data is not None: if isinstance(data, dict): - assert "query" in data and data["query"] is not None, "When providing a dictionary, 'query' must be provided." + assert "query" in data and data["query"] is not None, ( + "When providing a dictionary, 'query' must be provided." + ) query = data.get("query") if session_id is None: session_id = data.get("session_id") @@ -447,7 +465,9 @@ def run_async( # process content inputs if content is not None: - assert FileFactory.check_storage_type(query) == StorageType.TEXT, "When providing 'content', query must be text." + assert FileFactory.check_storage_type(query) == StorageType.TEXT, ( + "When providing 'content', query must be text." + ) if isinstance(content, list): assert len(content) <= 3, "The maximum number of content inputs is 3." @@ -511,6 +531,11 @@ def run_async( ) def to_dict(self) -> Dict: + """Convert the Agent instance to a dictionary representation. + + Returns: + Dict: Dictionary containing the agent's configuration and metadata. + """ from aixplain.factories.agent_factory.utils import build_tool_payload return { @@ -674,9 +699,9 @@ def delete(self) -> None: "referencing it." ) else: - message = f"Agent Deletion Error (HTTP {r.status_code}): " f"{error_message}." + message = f"Agent Deletion Error (HTTP {r.status_code}): {error_message}." except ValueError: - message = f"Agent Deletion Error (HTTP {r.status_code}): " "There was an error in deleting the agent." + message = f"Agent Deletion Error (HTTP {r.status_code}): There was an error in deleting the agent." logging.error(message) raise Exception(message) @@ -701,7 +726,7 @@ def update(self) -> None: stack = inspect.stack() if len(stack) > 2 and stack[1].function != "save": warnings.warn( - "update() is deprecated and will be removed in a future version. " "Please use save() instead.", + "update() is deprecated and will be removed in a future version. Please use save() instead.", DeprecationWarning, stacklevel=2, ) diff --git a/aixplain/modules/agent/tool/__init__.py b/aixplain/modules/agent/tool/__init__.py index b83c9704..76bbd802 100644 --- a/aixplain/modules/agent/tool/__init__.py +++ b/aixplain/modules/agent/tool/__init__.py @@ -1,6 +1,8 @@ -__author__ = "aiXplain" +"""Agent tool module for aiXplain SDK. + +This module provides tool classes and functionality for agents to interact with +various services, models, and data sources. -""" Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +22,8 @@ Description: Agentification Class """ + +__author__ = "aiXplain" from abc import ABC from typing import Optional, Text from aixplain.utils import config @@ -83,13 +87,10 @@ def validate(self): """ raise NotImplementedError - def deploy(self) -> None: - """Deploys the tool to make it available for use. - This method should handle any necessary setup or deployment steps - required to make the tool operational. +class DeployableTool(Tool): + """Tool that can be deployed.""" - Raises: - NotImplementedError: This is an abstract method that must be implemented by subclasses. - """ + def deploy(self) -> None: + """Deploy the tool.""" raise NotImplementedError diff --git a/aixplain/modules/agent/tool/custom_python_code_tool.py b/aixplain/modules/agent/tool/custom_python_code_tool.py index 0a027c04..1fa32541 100644 --- a/aixplain/modules/agent/tool/custom_python_code_tool.py +++ b/aixplain/modules/agent/tool/custom_python_code_tool.py @@ -1,6 +1,8 @@ -__author__ = "aiXplain" +"""Custom Python code tool for aiXplain SDK agents. + +This module provides a tool that allows agents to execute custom Python code +in a controlled environment. -""" Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +23,8 @@ Agentification Class """ +__author__ = "aiXplain" + from typing import Text, Union, Callable, Optional from aixplain.modules.agent.tool import Tool import logging @@ -110,9 +114,9 @@ def validate(self): if name and name.strip() != "": self.name = name - assert ( - self.description and self.description.strip() != "" - ), "Custom Python Code Tool Error: Tool description is required" + assert self.description and self.description.strip() != "", ( + "Custom Python Code Tool Error: Tool description is required" + ) assert self.code and self.code.strip() != "", "Custom Python Code Tool Error: Code is required" assert self.name and self.name.strip() != "", "Custom Python Code Tool Error: Name is required" assert self.status in [ @@ -127,11 +131,3 @@ def __repr__(self) -> Text: Text: A string in the format "CustomPythonCodeTool(name=)". """ return f"CustomPythonCodeTool(name={self.name})" - - def deploy(self): - """Deploy the custom Python code tool. - - This is a placeholder method as custom Python code tools are automatically - deployed when created. - """ - pass diff --git a/aixplain/modules/agent/tool/model_tool.py b/aixplain/modules/agent/tool/model_tool.py index da455188..5ac0c8a5 100644 --- a/aixplain/modules/agent/tool/model_tool.py +++ b/aixplain/modules/agent/tool/model_tool.py @@ -1,6 +1,8 @@ -__author__ = "aiXplain" +"""Model tool for aiXplain SDK agents. + +This module provides a tool that allows agents to interact with AI models +and execute model-based tasks. -""" Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +22,9 @@ Description: Agentification Class """ + +__author__ = "aiXplain" + from typing import Optional, Union, Text, Dict, List from aixplain.enums import AssetStatus, Function, Supplier @@ -162,8 +167,8 @@ def to_dict(self) -> Dict: } def validate(self) -> None: - """ - Validates the tool. + """Validates the tool. + Notes: - Checks if the tool has a function or model. - If the function is a string, it converts it to a Function enum. @@ -174,16 +179,16 @@ def validate(self) -> None: """ from aixplain.enums import FunctionInputOutput - assert ( - self.function is not None or self.model is not None - ), "Agent Creation Error: Either function or model must be provided when instantiating a tool." + assert self.function is not None or self.model is not None, ( + "Agent Creation Error: Either function or model must be provided when instantiating a tool." + ) if self.function is not None: if isinstance(self.function, str): self.function = Function(self.function) - assert ( - self.function is None or self.function is not Function.UTILITIES or self.model is not None - ), "Agent Creation Error: Utility function must be used with an associated model." + assert self.function is None or self.function is not Function.UTILITIES or self.model is not None, ( + "Agent Creation Error: Utility function must be used with an associated model." + ) try: if isinstance(self.supplier, dict): @@ -196,7 +201,9 @@ def validate(self) -> None: try: self.model = self._get_model() except Exception: - raise Exception(f"Model Tool Unavailable. Make sure Model '{self.model}' exists or you have access to it.") + raise Exception( + f"Model Tool Unavailable. Make sure Model '{self.model}' exists or you have access to it." + ) self.function = self.model.function if isinstance(self.model.supplier, Supplier): self.supplier = self.model.supplier @@ -213,7 +220,6 @@ def validate(self) -> None: self.parameters = self.validate_parameters(self.parameters) self.name = self.name if self.name else set_tool_name(self.function, self.supplier, self.model) - def get_parameters(self) -> Dict: """Get the tool's parameters, either from explicit settings or the model object. @@ -224,9 +230,9 @@ def get_parameters(self) -> Dict: # If parameters were not explicitly provided, get them from the model if ( self.parameters is None - and self.model_object is not None # noqa: W503 - and hasattr(self.model_object, "model_params") # noqa: W503 - and self.model_object.model_params is not None # noqa: W503 + and self.model_object is not None + and hasattr(self.model_object, "model_params") + and self.model_object.model_params is not None ): return self.model_object.model_params.to_list() return self.parameters @@ -265,11 +271,11 @@ def validate_parameters(self, received_parameters: Optional[List[Dict]] = None) # Get default parameters if none provided if ( self.model_object is not None - and hasattr(self.model_object, "model_params") # noqa: W503 - and self.model_object.model_params is not None # noqa: W503 + and hasattr(self.model_object, "model_params") + and self.model_object.model_params is not None ): return self.model_object.model_params.to_list() - + elif self.function is not None: function_params = self.function.get_parameters() if function_params is not None: @@ -280,8 +286,8 @@ def validate_parameters(self, received_parameters: Optional[List[Dict]] = None) expected_params = None if ( self.model_object is not None - and hasattr(self.model_object, "model_params") # noqa: W503 - and self.model_object.model_params is not None # noqa: W503 + and hasattr(self.model_object, "model_params") + and self.model_object.model_params is not None ): expected_params = self.model_object.model_params elif self.function is not None: @@ -300,7 +306,9 @@ def validate_parameters(self, received_parameters: Optional[List[Dict]] = None) invalid_params = received_param_names - expected_param_names if invalid_params: - raise ValueError(f"Invalid parameters provided: {invalid_params}. Expected parameters are: {expected_param_names}") + raise ValueError( + f"Invalid parameters provided: {invalid_params}. Expected parameters are: {expected_param_names}" + ) return received_parameters @@ -314,11 +322,3 @@ def __repr__(self) -> Text: supplier_str = self.supplier.value if self.supplier is not None else None model_str = self.model.id if self.model is not None else None return f"ModelTool(name={self.name}, function={self.function}, supplier={supplier_str}, model={model_str})" - - def deploy(self): - """Deploy the model tool. - - This is a placeholder method as model tools are managed through the aiXplain platform - and don't require explicit deployment. - """ - pass diff --git a/aixplain/modules/agent/tool/pipeline_tool.py b/aixplain/modules/agent/tool/pipeline_tool.py index 4ed2bd8e..ab847275 100644 --- a/aixplain/modules/agent/tool/pipeline_tool.py +++ b/aixplain/modules/agent/tool/pipeline_tool.py @@ -1,6 +1,8 @@ -__author__ = "aiXplain" +"""Pipeline tool for aiXplain SDK agents. + +This module provides a tool that allows agents to execute AI pipelines +and chain multiple AI operations together. -""" Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +22,9 @@ Description: Agentification Class """ + +__author__ = "aiXplain" + from typing import Text, Union, Optional from aixplain.modules.agent.tool import Tool @@ -123,11 +128,3 @@ def validate(self): if self.name.strip() == "": self.name = pipeline_obj.name self.status = pipeline_obj.status - - def deploy(self): - """Deploy the pipeline tool. - - This is a placeholder method as pipeline tools are managed through the aiXplain platform - and don't require explicit deployment. - """ - pass diff --git a/aixplain/modules/agent/tool/python_interpreter_tool.py b/aixplain/modules/agent/tool/python_interpreter_tool.py index 7be02bed..181bdf72 100644 --- a/aixplain/modules/agent/tool/python_interpreter_tool.py +++ b/aixplain/modules/agent/tool/python_interpreter_tool.py @@ -1,6 +1,8 @@ -__author__ = "aiXplain" +"""Python interpreter tool for aiXplain SDK agents. + +This module provides a tool that allows agents to execute Python code +using an interpreter in a controlled environment. -""" Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +23,8 @@ Agentification Class """ +__author__ = "aiXplain" + from aixplain.modules.agent.tool import Tool from aixplain.enums import AssetStatus @@ -83,11 +87,3 @@ def __repr__(self) -> Text: Text: A string in the format "PythonInterpreterTool()". """ return "PythonInterpreterTool()" - - def deploy(self): - """Deploy the Python interpreter tool. - - This is a placeholder method as the Python interpreter tool is automatically - available and doesn't require explicit deployment. - """ - pass diff --git a/aixplain/modules/agent/tool/sql_tool.py b/aixplain/modules/agent/tool/sql_tool.py index 331f4539..e124cf76 100644 --- a/aixplain/modules/agent/tool/sql_tool.py +++ b/aixplain/modules/agent/tool/sql_tool.py @@ -1,6 +1,8 @@ -__author__ = "aiXplain" +"""SQL tool for aiXplain SDK agents. + +This module provides a tool that allows agents to execute SQL queries +against databases and CSV files. -""" Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +22,9 @@ Description: Agentification Class """ + +__author__ = "aiXplain" + import os import warnings import validators @@ -28,23 +33,23 @@ from typing import Text, Optional, Dict, List, Union import sqlite3 from aixplain.enums import AssetStatus -from aixplain.modules.agent.tool import Tool +from aixplain.modules.agent.tool import DeployableTool class SQLToolError(Exception): - """Base exception for SQL Tool errors""" + """Base exception for SQL Tool errors.""" pass class CSVError(SQLToolError): - """Exception for CSV-related errors""" + """Exception for CSV-related errors.""" pass class DatabaseError(SQLToolError): - """Exception for database-related errors""" + """Exception for database-related errors.""" pass @@ -221,7 +226,9 @@ def create_database_from_csv(csv_path: str, database_path: str, table_name: str # Clean column names and track changes original_columns = df.columns.tolist() cleaned_columns = [clean_column_name(col) for col in original_columns] - changed_columns = [(orig, cleaned) for orig, cleaned in zip(original_columns, cleaned_columns) if orig != cleaned] + changed_columns = [ + (orig, cleaned) for orig, cleaned in zip(original_columns, cleaned_columns) if orig != cleaned + ] if changed_columns: changes = ", ".join([f"'{orig}' to '{cleaned}'" for orig, cleaned in changed_columns]) @@ -333,7 +340,7 @@ def get_table_names_from_schema(schema: str) -> List[str]: return table_names -class SQLTool(Tool): +class SQLTool(DeployableTool): """A tool for executing SQL commands in an SQLite database. This tool provides an interface for interacting with SQLite databases, including @@ -381,7 +388,6 @@ def __init__( Raises: SQLToolError: If required parameters are missing or invalid. """ - super().__init__(name=name, description=description, **additional_info) self.database = database @@ -440,9 +446,9 @@ def validate(self): # Handle database validation if not ( str(self.database).startswith("s3://") - or str(self.database).startswith("http://") # noqa: W503 - or str(self.database).startswith("https://") # noqa: W503 - or validators.url(self.database) # noqa: W503 + or str(self.database).startswith("http://") + or str(self.database).startswith("https://") + or validators.url(self.database) ): if not os.path.exists(self.database): raise SQLToolError(f"Database '{self.database}' does not exist") diff --git a/aixplain/modules/mixins.py b/aixplain/modules/mixins.py index 9e522022..20aa2983 100644 --- a/aixplain/modules/mixins.py +++ b/aixplain/modules/mixins.py @@ -1,4 +1,5 @@ -""" +"""Mixins for common functionality across different asset types. + Copyright 2024 The aiXplain SDK authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,9 +19,11 @@ Description: Mixins for common functionality across different asset types """ + from abc import ABC from typing import TypeVar, Generic from aixplain.enums import AssetStatus +from aixplain.exceptions import AlreadyDeployedError T = TypeVar("T") @@ -46,11 +49,12 @@ def _validate_deployment_readiness(self) -> None: items (Optional[List[T]], optional): List of items to validate (e.g. tools for Agent, agents for TeamAgent) Raises: + AlreadyDeployedError: If the asset is already deployed ValueError: If the asset is not ready to be deployed """ asset_type = self.__class__.__name__ if self.status == AssetStatus.ONBOARDED: - raise ValueError(f"{asset_type} is already deployed.") + raise AlreadyDeployedError(f"{asset_type} is already deployed.") if self.status != AssetStatus.DRAFT: raise ValueError(f"{asset_type} must be in DRAFT status to be deployed.") @@ -62,24 +66,36 @@ def deploy(self) -> None: Classes that need special deployment handling should override this method. Raises: + AlreadyDeployedError: If the asset is already deployed ValueError: If the asset is not ready to be deployed """ self._validate_deployment_readiness() previous_status = self.status try: + # Deploy tools if present if hasattr(self, "tools"): - [tool.deploy() for tool in self.tools] + for tool in self.tools: + if hasattr(tool, "deploy"): + try: + tool.deploy() + except AlreadyDeployedError: + # Skip tools that are already deployed + pass + except Exception as e: + raise Exception(f"Error deploying tool {tool.name}: {e}") from e + + # Deploy agents if present (for TeamAgent) if hasattr(self, "agents"): - undeployed_agents = [agent for agent in self.agents if agent.status != AssetStatus.ONBOARDED] - if undeployed_agents: - names = ", ".join(str(agent) for agent in undeployed_agents) - if names: - raise ValueError( - f"Agents not deployed: {names}. " - "Deploy them with `.deploy()` before running this command." - ) - - + for agent in self.agents: + if hasattr(agent, "deploy"): + try: + agent.deploy() + except AlreadyDeployedError: + # Skip agents that are already deployed + pass + except Exception as e: + raise Exception(f"Error deploying agent {agent.name}: {e}") from e + self.status = AssetStatus.ONBOARDED self.update() except Exception as e: diff --git a/aixplain/modules/model/connection.py b/aixplain/modules/model/connection.py index 94369f1f..148ff5f7 100644 --- a/aixplain/modules/model/connection.py +++ b/aixplain/modules/model/connection.py @@ -1,3 +1,23 @@ +"""Copyright 2025 The aiXplain SDK authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: Ahmet Gündüz +Date: September 10th 2025 +Description: + Connection Tool Class. +""" + from aixplain.enums import Function, Supplier, FunctionType, ResponseStatus from aixplain.modules.model import Model from aixplain.utils import config @@ -52,6 +72,15 @@ def __repr__(self): class ConnectionTool(Model): + """A class representing a connection tool. + + This class defines the structure of a connection tool with its actions and action scope. + + Attributes: + actions (List[ConnectAction]): A list of available actions for this connection. + action_scope (Optional[List[ConnectAction]]): The scope of actions for this connection. + """ + actions: List[ConnectAction] action_scope: Optional[List[ConnectAction]] = None @@ -84,9 +113,9 @@ def __init__( function_type (FunctionType, optional): Type of the Connection. Defaults to FunctionType.CONNECTION. **additional_info: Any additional Connection info to be saved """ - assert ( - function_type == FunctionType.CONNECTION or function_type == FunctionType.MCP_CONNECTION - ), "Connection only supports connection function" + assert function_type == FunctionType.CONNECTION or function_type == FunctionType.MCP_CONNECTION, ( + "Connection only supports connection function" + ) super().__init__( id=id, name=name, @@ -188,9 +217,9 @@ def get_parameters(self) -> List[Dict]: Raises: AssertionError: If the action scope is not set or is empty. """ - assert ( - self.action_scope is not None and len(self.action_scope) > 0 - ), f"Please set the scope of actions for the connection '{self.id}'." + assert self.action_scope is not None and len(self.action_scope) > 0, ( + f"Please set the scope of actions for the connection '{self.id}'." + ) response = [ { "code": action.code, diff --git a/tests/functional/agent/agent_mcp_deploy_test.py b/tests/functional/agent/agent_mcp_deploy_test.py new file mode 100644 index 00000000..74c3bcf3 --- /dev/null +++ b/tests/functional/agent/agent_mcp_deploy_test.py @@ -0,0 +1,180 @@ +"""Tests for agent deployment functionality with MCP (Model Control Protocol) tools. + +This test verifies that agents can be created, deployed, and used with MCP tools, +including proper status management and cleanup. +""" + +import pytest +import logging +from uuid import uuid4 +from aixplain.factories import ToolFactory, AgentFactory +from aixplain.modules.model.integration import AuthenticationSchema +from aixplain.enums import AssetStatus +from aixplain.exceptions import AlreadyDeployedError +from tests.test_deletion_utils import safe_delete_all_agents_and_team_agents + + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +@pytest.fixture(scope="function") +def cleanup_agents(): + """Fixture to clean up agents before and after tests.""" + # Clean up before test + safe_delete_all_agents_and_team_agents() + + yield True + + # Clean up after test + safe_delete_all_agents_and_team_agents() + + +@pytest.fixture +def mcp_tool(): + """Create an MCP tool for testing.""" + tool = ToolFactory.create( + integration="686eb9cd26480723d0634d3e", # Remote MCP ID + name=f"Test Remote MCP {uuid4()}", + authentication_schema=AuthenticationSchema.API_KEY, + data={"url": "https://remote.mcpservers.org/fetch/mcp"}, + ) + + # Set allowed actions (using ... as in original script) + tool.allowed_actions = [...] + + # Filter actions to only include "fetch" action + tool.action_scope = [action for action in tool.actions if action.code == "fetch"] + + return tool + + +@pytest.fixture +def test_agent(cleanup_agents, mcp_tool): + """Create a test agent with MCP tool.""" + agent = AgentFactory.create( + name=f"Test Agent {uuid4()}", + description="This agent is used to scrape websites", + instructions="You are a helpful assistant that can scrape any given website", + tools=[mcp_tool], + llm="669a63646eb56306647e1091", + ) + return agent + + +def test_agent_creation_with_mcp_tool(test_agent, mcp_tool): + """Test that an agent can be created with an MCP tool.""" + assert test_agent is not None + assert test_agent.name.startswith("Test Agent") + assert test_agent.description == "This agent is used to scrape websites" + assert len(test_agent.tools) == 1 + assert test_agent.tools[0] == mcp_tool + assert test_agent.status == AssetStatus.DRAFT + + +def test_agent_run_before_deployment(test_agent): + """Test that an agent can run before being deployed.""" + response = test_agent.run("Give me information about the aixplain website") + + assert response is not None + assert hasattr(response, "data") + assert hasattr(response.data, "output") + + +def test_agent_deployment(test_agent): + """Test that an agent can be deployed successfully.""" + # Verify initial status is DRAFT + assert test_agent.status == AssetStatus.DRAFT + + # Deploy the agent + test_agent.deploy() + + # Verify status is now ONBOARDED + assert test_agent.status == AssetStatus.ONBOARDED + + +def test_agent_retrieval_after_deployment(test_agent): + """Test that a deployed agent can be retrieved and maintains its status.""" + # Deploy the agent first + test_agent.deploy() + agent_id = test_agent.id + + # Retrieve the agent by ID + retrieved_agent = AgentFactory.get(agent_id) + + assert retrieved_agent is not None + assert retrieved_agent.id == agent_id + assert retrieved_agent.status == AssetStatus.ONBOARDED + + +def test_deployed_agent_cannot_be_deployed_again(test_agent): + """Test that attempting to deploy an already deployed agent raises an error.""" + # Deploy the agent first + test_agent.deploy() + assert test_agent.status == AssetStatus.ONBOARDED + + # Attempt to deploy again should raise AlreadyDeployedError + with pytest.raises(AlreadyDeployedError, match="is already deployed"): + test_agent.deploy() + + +def test_deployed_agent_can_run(test_agent): + """Test that a deployed agent can still run queries.""" + # Deploy the agent first + test_agent.deploy() + + # Run a query on the deployed agent + response = test_agent.run("Give me information about the aixplain website") + + assert response is not None + assert hasattr(response, "data") + assert hasattr(response.data, "output") + + +def test_agent_lifecycle_end_to_end(cleanup_agents, mcp_tool): + """Test the complete agent lifecycle: create, run, deploy, retrieve, run, delete.""" + # Create agent + agent = AgentFactory.create( + name=f"Test Agent Lifecycle {uuid4()}", + description="This agent is used for lifecycle testing", + instructions="You are a helpful assistant that can scrape any given website", + tools=[mcp_tool], + llm="669a63646eb56306647e1091", + ) + + # Test initial state + assert agent.status == AssetStatus.DRAFT + + # Test run before deployment + response = agent.run("Give me information about the aixplain website") + assert response is not None + + # Deploy agent + agent.deploy() + assert agent.status == AssetStatus.ONBOARDED + + # Retrieve agent by ID + agent_id = agent.id + retrieved_agent = AgentFactory.get(agent_id) + assert retrieved_agent.status == AssetStatus.ONBOARDED + + # Test run after deployment + response = retrieved_agent.run("Give me information about the aixplain website") + assert response is not None + + # Clean up + retrieved_agent.delete() + + +def test_mcp_tool_properties(mcp_tool): + """Test that the MCP tool has the expected properties.""" + assert mcp_tool is not None + assert mcp_tool.name.startswith("MCP Server") + assert hasattr(mcp_tool, "actions") + assert hasattr(mcp_tool, "action_scope") + assert len(mcp_tool.action_scope) >= 0 # Should have filtered actions + + # Verify that action_scope only contains "fetch" actions + for action in mcp_tool.action_scope: + assert action.code == "fetch"