ibm-watsonx-gov 1.3.3__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. ibm_watsonx_gov/__init__.py +8 -0
  2. ibm_watsonx_gov/agent_catalog/__init__.py +8 -0
  3. ibm_watsonx_gov/agent_catalog/clients/__init__.py +14 -0
  4. ibm_watsonx_gov/agent_catalog/clients/ai_agent_client.py +333 -0
  5. ibm_watsonx_gov/agent_catalog/core/__init__.py +8 -0
  6. ibm_watsonx_gov/agent_catalog/core/agent_loader.py +202 -0
  7. ibm_watsonx_gov/agent_catalog/core/agents.py +134 -0
  8. ibm_watsonx_gov/agent_catalog/entities/__init__.py +8 -0
  9. ibm_watsonx_gov/agent_catalog/entities/ai_agent.py +599 -0
  10. ibm_watsonx_gov/agent_catalog/utils/__init__.py +8 -0
  11. ibm_watsonx_gov/agent_catalog/utils/constants.py +36 -0
  12. ibm_watsonx_gov/agent_catalog/utils/notebook_utils.py +70 -0
  13. ibm_watsonx_gov/ai_experiments/__init__.py +8 -0
  14. ibm_watsonx_gov/ai_experiments/ai_experiments_client.py +980 -0
  15. ibm_watsonx_gov/ai_experiments/utils/__init__.py +8 -0
  16. ibm_watsonx_gov/ai_experiments/utils/ai_experiment_utils.py +139 -0
  17. ibm_watsonx_gov/clients/__init__.py +0 -0
  18. ibm_watsonx_gov/clients/api_client.py +99 -0
  19. ibm_watsonx_gov/clients/segment_client.py +46 -0
  20. ibm_watsonx_gov/clients/usage_client.cp313-win_amd64.pyd +0 -0
  21. ibm_watsonx_gov/clients/wx_ai_client.py +87 -0
  22. ibm_watsonx_gov/config/__init__.py +14 -0
  23. ibm_watsonx_gov/config/agentic_ai_configuration.py +225 -0
  24. ibm_watsonx_gov/config/gen_ai_configuration.py +129 -0
  25. ibm_watsonx_gov/config/model_risk_configuration.py +173 -0
  26. ibm_watsonx_gov/config/predictive_ai_configuration.py +20 -0
  27. ibm_watsonx_gov/entities/__init__.py +8 -0
  28. ibm_watsonx_gov/entities/agentic_app.py +209 -0
  29. ibm_watsonx_gov/entities/agentic_evaluation_result.py +185 -0
  30. ibm_watsonx_gov/entities/ai_evaluation.py +290 -0
  31. ibm_watsonx_gov/entities/ai_experiment.py +419 -0
  32. ibm_watsonx_gov/entities/base_classes.py +134 -0
  33. ibm_watsonx_gov/entities/container.py +54 -0
  34. ibm_watsonx_gov/entities/credentials.py +633 -0
  35. ibm_watsonx_gov/entities/criteria.py +508 -0
  36. ibm_watsonx_gov/entities/enums.py +274 -0
  37. ibm_watsonx_gov/entities/evaluation_result.py +444 -0
  38. ibm_watsonx_gov/entities/foundation_model.py +490 -0
  39. ibm_watsonx_gov/entities/llm_judge.py +44 -0
  40. ibm_watsonx_gov/entities/locale.py +17 -0
  41. ibm_watsonx_gov/entities/mapping.py +49 -0
  42. ibm_watsonx_gov/entities/metric.py +211 -0
  43. ibm_watsonx_gov/entities/metric_threshold.py +36 -0
  44. ibm_watsonx_gov/entities/model_provider.py +329 -0
  45. ibm_watsonx_gov/entities/model_risk_result.py +43 -0
  46. ibm_watsonx_gov/entities/monitor.py +71 -0
  47. ibm_watsonx_gov/entities/prompt_setup.py +40 -0
  48. ibm_watsonx_gov/entities/state.py +22 -0
  49. ibm_watsonx_gov/entities/utils.py +99 -0
  50. ibm_watsonx_gov/evaluators/__init__.py +26 -0
  51. ibm_watsonx_gov/evaluators/agentic_evaluator.py +2725 -0
  52. ibm_watsonx_gov/evaluators/agentic_traces_evaluator.py +115 -0
  53. ibm_watsonx_gov/evaluators/base_evaluator.py +22 -0
  54. ibm_watsonx_gov/evaluators/impl/__init__.py +0 -0
  55. ibm_watsonx_gov/evaluators/impl/evaluate_metrics_impl.cp313-win_amd64.pyd +0 -0
  56. ibm_watsonx_gov/evaluators/impl/evaluate_model_risk_impl.cp313-win_amd64.pyd +0 -0
  57. ibm_watsonx_gov/evaluators/metrics_evaluator.py +187 -0
  58. ibm_watsonx_gov/evaluators/model_risk_evaluator.py +89 -0
  59. ibm_watsonx_gov/evaluators/traces_evaluator.py +93 -0
  60. ibm_watsonx_gov/metric_groups/answer_quality/answer_quality_decorator.py +66 -0
  61. ibm_watsonx_gov/metric_groups/content_safety/content_safety_decorator.py +76 -0
  62. ibm_watsonx_gov/metric_groups/readability/readability_decorator.py +59 -0
  63. ibm_watsonx_gov/metric_groups/retrieval_quality/retrieval_quality_decorator.py +63 -0
  64. ibm_watsonx_gov/metric_groups/usage/usage_decorator.py +58 -0
  65. ibm_watsonx_gov/metrics/__init__.py +74 -0
  66. ibm_watsonx_gov/metrics/answer_relevance/__init__.py +8 -0
  67. ibm_watsonx_gov/metrics/answer_relevance/answer_relevance_decorator.py +63 -0
  68. ibm_watsonx_gov/metrics/answer_relevance/answer_relevance_metric.py +260 -0
  69. ibm_watsonx_gov/metrics/answer_similarity/__init__.py +0 -0
  70. ibm_watsonx_gov/metrics/answer_similarity/answer_similarity_decorator.py +66 -0
  71. ibm_watsonx_gov/metrics/answer_similarity/answer_similarity_metric.py +219 -0
  72. ibm_watsonx_gov/metrics/average_precision/__init__.py +0 -0
  73. ibm_watsonx_gov/metrics/average_precision/average_precision_decorator.py +62 -0
  74. ibm_watsonx_gov/metrics/average_precision/average_precision_metric.py +174 -0
  75. ibm_watsonx_gov/metrics/base_metric_decorator.py +193 -0
  76. ibm_watsonx_gov/metrics/context_relevance/__init__.py +8 -0
  77. ibm_watsonx_gov/metrics/context_relevance/context_relevance_decorator.py +60 -0
  78. ibm_watsonx_gov/metrics/context_relevance/context_relevance_metric.py +414 -0
  79. ibm_watsonx_gov/metrics/cost/__init__.py +8 -0
  80. ibm_watsonx_gov/metrics/cost/cost_decorator.py +58 -0
  81. ibm_watsonx_gov/metrics/cost/cost_metric.py +155 -0
  82. ibm_watsonx_gov/metrics/duration/__init__.py +8 -0
  83. ibm_watsonx_gov/metrics/duration/duration_decorator.py +59 -0
  84. ibm_watsonx_gov/metrics/duration/duration_metric.py +111 -0
  85. ibm_watsonx_gov/metrics/evasiveness/__init__.py +8 -0
  86. ibm_watsonx_gov/metrics/evasiveness/evasiveness_decorator.py +61 -0
  87. ibm_watsonx_gov/metrics/evasiveness/evasiveness_metric.py +103 -0
  88. ibm_watsonx_gov/metrics/faithfulness/__init__.py +8 -0
  89. ibm_watsonx_gov/metrics/faithfulness/faithfulness_decorator.py +65 -0
  90. ibm_watsonx_gov/metrics/faithfulness/faithfulness_metric.py +254 -0
  91. ibm_watsonx_gov/metrics/hap/__init__.py +16 -0
  92. ibm_watsonx_gov/metrics/hap/hap_decorator.py +58 -0
  93. ibm_watsonx_gov/metrics/hap/hap_metric.py +98 -0
  94. ibm_watsonx_gov/metrics/hap/input_hap_metric.py +104 -0
  95. ibm_watsonx_gov/metrics/hap/output_hap_metric.py +110 -0
  96. ibm_watsonx_gov/metrics/harm/__init__.py +8 -0
  97. ibm_watsonx_gov/metrics/harm/harm_decorator.py +60 -0
  98. ibm_watsonx_gov/metrics/harm/harm_metric.py +103 -0
  99. ibm_watsonx_gov/metrics/harm_engagement/__init__.py +8 -0
  100. ibm_watsonx_gov/metrics/harm_engagement/harm_engagement_decorator.py +61 -0
  101. ibm_watsonx_gov/metrics/harm_engagement/harm_engagement_metric.py +103 -0
  102. ibm_watsonx_gov/metrics/hit_rate/__init__.py +0 -0
  103. ibm_watsonx_gov/metrics/hit_rate/hit_rate_decorator.py +59 -0
  104. ibm_watsonx_gov/metrics/hit_rate/hit_rate_metric.py +167 -0
  105. ibm_watsonx_gov/metrics/input_token_count/__init__.py +8 -0
  106. ibm_watsonx_gov/metrics/input_token_count/input_token_count_decorator.py +58 -0
  107. ibm_watsonx_gov/metrics/input_token_count/input_token_count_metric.py +112 -0
  108. ibm_watsonx_gov/metrics/jailbreak/__init__.py +8 -0
  109. ibm_watsonx_gov/metrics/jailbreak/jailbreak_decorator.py +60 -0
  110. ibm_watsonx_gov/metrics/jailbreak/jailbreak_metric.py +103 -0
  111. ibm_watsonx_gov/metrics/keyword_detection/keyword_detection_decorator.py +58 -0
  112. ibm_watsonx_gov/metrics/keyword_detection/keyword_detection_metric.py +111 -0
  113. ibm_watsonx_gov/metrics/llm_validation/__init__.py +8 -0
  114. ibm_watsonx_gov/metrics/llm_validation/evaluation_criteria.py +84 -0
  115. ibm_watsonx_gov/metrics/llm_validation/llm_validation_constants.py +24 -0
  116. ibm_watsonx_gov/metrics/llm_validation/llm_validation_decorator.py +54 -0
  117. ibm_watsonx_gov/metrics/llm_validation/llm_validation_impl.py +525 -0
  118. ibm_watsonx_gov/metrics/llm_validation/llm_validation_metric.py +258 -0
  119. ibm_watsonx_gov/metrics/llm_validation/llm_validation_prompts.py +106 -0
  120. ibm_watsonx_gov/metrics/llmaj/__init__.py +0 -0
  121. ibm_watsonx_gov/metrics/llmaj/llmaj_metric.py +298 -0
  122. ibm_watsonx_gov/metrics/ndcg/__init__.py +0 -0
  123. ibm_watsonx_gov/metrics/ndcg/ndcg_decorator.py +61 -0
  124. ibm_watsonx_gov/metrics/ndcg/ndcg_metric.py +166 -0
  125. ibm_watsonx_gov/metrics/output_token_count/__init__.py +8 -0
  126. ibm_watsonx_gov/metrics/output_token_count/output_token_count_decorator.py +58 -0
  127. ibm_watsonx_gov/metrics/output_token_count/output_token_count_metric.py +112 -0
  128. ibm_watsonx_gov/metrics/pii/__init__.py +16 -0
  129. ibm_watsonx_gov/metrics/pii/input_pii_metric.py +102 -0
  130. ibm_watsonx_gov/metrics/pii/output_pii_metric.py +107 -0
  131. ibm_watsonx_gov/metrics/pii/pii_decorator.py +59 -0
  132. ibm_watsonx_gov/metrics/pii/pii_metric.py +96 -0
  133. ibm_watsonx_gov/metrics/profanity/__init__.py +8 -0
  134. ibm_watsonx_gov/metrics/profanity/profanity_decorator.py +60 -0
  135. ibm_watsonx_gov/metrics/profanity/profanity_metric.py +103 -0
  136. ibm_watsonx_gov/metrics/prompt_safety_risk/__init__.py +8 -0
  137. ibm_watsonx_gov/metrics/prompt_safety_risk/prompt_safety_risk_decorator.py +57 -0
  138. ibm_watsonx_gov/metrics/prompt_safety_risk/prompt_safety_risk_metric.py +128 -0
  139. ibm_watsonx_gov/metrics/reciprocal_rank/__init__.py +0 -0
  140. ibm_watsonx_gov/metrics/reciprocal_rank/reciprocal_rank_decorator.py +62 -0
  141. ibm_watsonx_gov/metrics/reciprocal_rank/reciprocal_rank_metric.py +162 -0
  142. ibm_watsonx_gov/metrics/regex_detection/regex_detection_decorator.py +58 -0
  143. ibm_watsonx_gov/metrics/regex_detection/regex_detection_metric.py +106 -0
  144. ibm_watsonx_gov/metrics/retrieval_precision/__init__.py +0 -0
  145. ibm_watsonx_gov/metrics/retrieval_precision/retrieval_precision_decorator.py +62 -0
  146. ibm_watsonx_gov/metrics/retrieval_precision/retrieval_precision_metric.py +170 -0
  147. ibm_watsonx_gov/metrics/sexual_content/__init__.py +8 -0
  148. ibm_watsonx_gov/metrics/sexual_content/sexual_content_decorator.py +61 -0
  149. ibm_watsonx_gov/metrics/sexual_content/sexual_content_metric.py +103 -0
  150. ibm_watsonx_gov/metrics/social_bias/__init__.py +8 -0
  151. ibm_watsonx_gov/metrics/social_bias/social_bias_decorator.py +62 -0
  152. ibm_watsonx_gov/metrics/social_bias/social_bias_metric.py +103 -0
  153. ibm_watsonx_gov/metrics/status/__init__.py +0 -0
  154. ibm_watsonx_gov/metrics/status/status_metric.py +113 -0
  155. ibm_watsonx_gov/metrics/text_grade_level/__init__.py +8 -0
  156. ibm_watsonx_gov/metrics/text_grade_level/text_grade_level_decorator.py +59 -0
  157. ibm_watsonx_gov/metrics/text_grade_level/text_grade_level_metric.py +127 -0
  158. ibm_watsonx_gov/metrics/text_reading_ease/__init__.py +8 -0
  159. ibm_watsonx_gov/metrics/text_reading_ease/text_reading_ease_decorator.py +59 -0
  160. ibm_watsonx_gov/metrics/text_reading_ease/text_reading_ease_metric.py +123 -0
  161. ibm_watsonx_gov/metrics/tool_call_accuracy/__init__.py +0 -0
  162. ibm_watsonx_gov/metrics/tool_call_accuracy/tool_call_accuracy_decorator.py +67 -0
  163. ibm_watsonx_gov/metrics/tool_call_accuracy/tool_call_accuracy_metric.py +162 -0
  164. ibm_watsonx_gov/metrics/tool_call_parameter_accuracy/__init__.py +0 -0
  165. ibm_watsonx_gov/metrics/tool_call_parameter_accuracy/tool_call_parameter_accuracy_decorator.py +68 -0
  166. ibm_watsonx_gov/metrics/tool_call_parameter_accuracy/tool_call_parameter_accuracy_metric.py +151 -0
  167. ibm_watsonx_gov/metrics/tool_call_relevance/__init__.py +0 -0
  168. ibm_watsonx_gov/metrics/tool_call_relevance/tool_call_relevance_decorator.py +71 -0
  169. ibm_watsonx_gov/metrics/tool_call_relevance/tool_call_relevance_metric.py +166 -0
  170. ibm_watsonx_gov/metrics/tool_call_syntactic_accuracy/__init__.py +0 -0
  171. ibm_watsonx_gov/metrics/tool_call_syntactic_accuracy/tool_call_syntactic_accuracy_decorator.py +66 -0
  172. ibm_watsonx_gov/metrics/tool_call_syntactic_accuracy/tool_call_syntactic_accuracy_metric.py +121 -0
  173. ibm_watsonx_gov/metrics/topic_relevance/__init__.py +8 -0
  174. ibm_watsonx_gov/metrics/topic_relevance/topic_relevance_decorator.py +57 -0
  175. ibm_watsonx_gov/metrics/topic_relevance/topic_relevance_metric.py +106 -0
  176. ibm_watsonx_gov/metrics/unethical_behavior/__init__.py +8 -0
  177. ibm_watsonx_gov/metrics/unethical_behavior/unethical_behavior_decorator.py +61 -0
  178. ibm_watsonx_gov/metrics/unethical_behavior/unethical_behavior_metric.py +103 -0
  179. ibm_watsonx_gov/metrics/unsuccessful_requests/__init__.py +0 -0
  180. ibm_watsonx_gov/metrics/unsuccessful_requests/unsuccessful_requests_decorator.py +66 -0
  181. ibm_watsonx_gov/metrics/unsuccessful_requests/unsuccessful_requests_metric.py +128 -0
  182. ibm_watsonx_gov/metrics/user_id/__init__.py +0 -0
  183. ibm_watsonx_gov/metrics/user_id/user_id_metric.py +111 -0
  184. ibm_watsonx_gov/metrics/utils.py +440 -0
  185. ibm_watsonx_gov/metrics/violence/__init__.py +8 -0
  186. ibm_watsonx_gov/metrics/violence/violence_decorator.py +60 -0
  187. ibm_watsonx_gov/metrics/violence/violence_metric.py +103 -0
  188. ibm_watsonx_gov/prompt_evaluator/__init__.py +9 -0
  189. ibm_watsonx_gov/prompt_evaluator/impl/__init__.py +8 -0
  190. ibm_watsonx_gov/prompt_evaluator/impl/prompt_evaluator_impl.py +554 -0
  191. ibm_watsonx_gov/prompt_evaluator/impl/pta_lifecycle_evaluator.py +2332 -0
  192. ibm_watsonx_gov/prompt_evaluator/prompt_evaluator.py +262 -0
  193. ibm_watsonx_gov/providers/__init__.py +8 -0
  194. ibm_watsonx_gov/providers/detectors_provider.cp313-win_amd64.pyd +0 -0
  195. ibm_watsonx_gov/providers/detectors_provider.py +415 -0
  196. ibm_watsonx_gov/providers/eval_assist_provider.cp313-win_amd64.pyd +0 -0
  197. ibm_watsonx_gov/providers/eval_assist_provider.py +266 -0
  198. ibm_watsonx_gov/providers/inference_engines/__init__.py +0 -0
  199. ibm_watsonx_gov/providers/inference_engines/custom_inference_engine.py +165 -0
  200. ibm_watsonx_gov/providers/inference_engines/portkey_inference_engine.py +57 -0
  201. ibm_watsonx_gov/providers/llmevalkit/__init__.py +0 -0
  202. ibm_watsonx_gov/providers/llmevalkit/ciso_agent/main.py +516 -0
  203. ibm_watsonx_gov/providers/llmevalkit/ciso_agent/preprocess_log.py +111 -0
  204. ibm_watsonx_gov/providers/llmevalkit/ciso_agent/utils.py +186 -0
  205. ibm_watsonx_gov/providers/llmevalkit/function_calling/README.md +411 -0
  206. ibm_watsonx_gov/providers/llmevalkit/function_calling/__init__.py +27 -0
  207. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/README.md +306 -0
  208. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/__init__.py +89 -0
  209. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/comparators/__init__.py +30 -0
  210. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/comparators/base.py +411 -0
  211. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/comparators/code_agent.py +1254 -0
  212. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/comparators/exact_match.py +134 -0
  213. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/comparators/fuzzy_string.py +104 -0
  214. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/comparators/hybrid.py +516 -0
  215. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/comparators/llm_judge.py +1882 -0
  216. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/pipeline.py +387 -0
  217. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/types.py +178 -0
  218. ibm_watsonx_gov/providers/llmevalkit/function_calling/comparison/utils.py +298 -0
  219. ibm_watsonx_gov/providers/llmevalkit/function_calling/consts.py +33 -0
  220. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/__init__.py +31 -0
  221. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/base.py +26 -0
  222. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_call/__init__.py +4 -0
  223. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_call/general.py +46 -0
  224. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_call/general_metrics.json +783 -0
  225. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_call/general_metrics_runtime.json +580 -0
  226. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_selection/__init__.py +6 -0
  227. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_selection/function_selection.py +28 -0
  228. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_selection/function_selection_metrics.json +599 -0
  229. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/function_selection/function_selection_metrics_runtime.json +477 -0
  230. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/loader.py +259 -0
  231. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/parameter/__init__.py +7 -0
  232. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/parameter/parameter.py +52 -0
  233. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/parameter/parameter_metrics.json +613 -0
  234. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/parameter/parameter_metrics_runtime.json +489 -0
  235. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/trajectory/__init__.py +7 -0
  236. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/trajectory/trajectory.py +43 -0
  237. ibm_watsonx_gov/providers/llmevalkit/function_calling/metrics/trajectory/trajectory_metrics.json +161 -0
  238. ibm_watsonx_gov/providers/llmevalkit/function_calling/pipeline/__init__.py +0 -0
  239. ibm_watsonx_gov/providers/llmevalkit/function_calling/pipeline/adapters.py +102 -0
  240. ibm_watsonx_gov/providers/llmevalkit/function_calling/pipeline/pipeline.py +355 -0
  241. ibm_watsonx_gov/providers/llmevalkit/function_calling/pipeline/semantic_checker.py +816 -0
  242. ibm_watsonx_gov/providers/llmevalkit/function_calling/pipeline/static_checker.py +297 -0
  243. ibm_watsonx_gov/providers/llmevalkit/function_calling/pipeline/transformation_prompts.py +509 -0
  244. ibm_watsonx_gov/providers/llmevalkit/function_calling/pipeline/types.py +596 -0
  245. ibm_watsonx_gov/providers/llmevalkit/llm/README.md +375 -0
  246. ibm_watsonx_gov/providers/llmevalkit/llm/__init__.py +137 -0
  247. ibm_watsonx_gov/providers/llmevalkit/llm/base.py +426 -0
  248. ibm_watsonx_gov/providers/llmevalkit/llm/output_parser.py +364 -0
  249. ibm_watsonx_gov/providers/llmevalkit/llm/providers/__init__.py +0 -0
  250. ibm_watsonx_gov/providers/llmevalkit/llm/providers/consts.py +7 -0
  251. ibm_watsonx_gov/providers/llmevalkit/llm/providers/ibm_watsonx_ai/__init__.py +0 -0
  252. ibm_watsonx_gov/providers/llmevalkit/llm/providers/ibm_watsonx_ai/ibm_watsonx_ai.py +656 -0
  253. ibm_watsonx_gov/providers/llmevalkit/llm/providers/litellm/__init__.py +0 -0
  254. ibm_watsonx_gov/providers/llmevalkit/llm/providers/litellm/litellm.py +509 -0
  255. ibm_watsonx_gov/providers/llmevalkit/llm/providers/litellm/rits.py +224 -0
  256. ibm_watsonx_gov/providers/llmevalkit/llm/providers/litellm/watsonx.py +60 -0
  257. ibm_watsonx_gov/providers/llmevalkit/llm/providers/mock_llm_client.py +75 -0
  258. ibm_watsonx_gov/providers/llmevalkit/llm/providers/openai/__init__.py +0 -0
  259. ibm_watsonx_gov/providers/llmevalkit/llm/providers/openai/openai.py +639 -0
  260. ibm_watsonx_gov/providers/llmevalkit/llm/providers/wxo_ai_gateway/__init__.py +0 -0
  261. ibm_watsonx_gov/providers/llmevalkit/llm/providers/wxo_ai_gateway/wxo_ai_gateway.py +134 -0
  262. ibm_watsonx_gov/providers/llmevalkit/llm/providers/wxo_ai_gateway/wxo_ai_gateway_inference.py +214 -0
  263. ibm_watsonx_gov/providers/llmevalkit/llm/types.py +136 -0
  264. ibm_watsonx_gov/providers/llmevalkit/metrics/__init__.py +4 -0
  265. ibm_watsonx_gov/providers/llmevalkit/metrics/field.py +255 -0
  266. ibm_watsonx_gov/providers/llmevalkit/metrics/metric.py +332 -0
  267. ibm_watsonx_gov/providers/llmevalkit/metrics/metrics_runner.py +188 -0
  268. ibm_watsonx_gov/providers/llmevalkit/metrics/prompt.py +403 -0
  269. ibm_watsonx_gov/providers/llmevalkit/metrics/utils.py +46 -0
  270. ibm_watsonx_gov/providers/llmevalkit/prompt/__init__.py +0 -0
  271. ibm_watsonx_gov/providers/llmevalkit/prompt/runner.py +144 -0
  272. ibm_watsonx_gov/providers/tool_call_metric_provider.py +455 -0
  273. ibm_watsonx_gov/providers/unitxt_provider.cp313-win_amd64.pyd +0 -0
  274. ibm_watsonx_gov/tools/__init__.py +10 -0
  275. ibm_watsonx_gov/tools/clients/__init__.py +11 -0
  276. ibm_watsonx_gov/tools/clients/ai_tool_client.py +405 -0
  277. ibm_watsonx_gov/tools/clients/detector_client.py +82 -0
  278. ibm_watsonx_gov/tools/core/__init__.py +8 -0
  279. ibm_watsonx_gov/tools/core/tool_loader.py +237 -0
  280. ibm_watsonx_gov/tools/entities/__init__.py +8 -0
  281. ibm_watsonx_gov/tools/entities/ai_tools.py +435 -0
  282. ibm_watsonx_gov/tools/onboarding/create/answer_relevance_detector.json +57 -0
  283. ibm_watsonx_gov/tools/onboarding/create/chromadb_retrieval_tool.json +63 -0
  284. ibm_watsonx_gov/tools/onboarding/create/context_relevance_detector.json +57 -0
  285. ibm_watsonx_gov/tools/onboarding/create/duduckgo_search_tool.json +53 -0
  286. ibm_watsonx_gov/tools/onboarding/create/google_search_tool.json +62 -0
  287. ibm_watsonx_gov/tools/onboarding/create/hap_detector.json +70 -0
  288. ibm_watsonx_gov/tools/onboarding/create/jailbreak_detector.json +70 -0
  289. ibm_watsonx_gov/tools/onboarding/create/pii_detector.json +36 -0
  290. ibm_watsonx_gov/tools/onboarding/create/prompt_safety_risk_detector.json +69 -0
  291. ibm_watsonx_gov/tools/onboarding/create/topic_relevance_detector.json +57 -0
  292. ibm_watsonx_gov/tools/onboarding/create/weather_tool.json +39 -0
  293. ibm_watsonx_gov/tools/onboarding/create/webcrawler_tool.json +34 -0
  294. ibm_watsonx_gov/tools/onboarding/create/wikipedia_search_tool.json +53 -0
  295. ibm_watsonx_gov/tools/onboarding/delete/delete_tools.json +4 -0
  296. ibm_watsonx_gov/tools/onboarding/update/google_search_tool.json +38 -0
  297. ibm_watsonx_gov/tools/ootb/__init__.py +8 -0
  298. ibm_watsonx_gov/tools/ootb/detectors/__init__.py +8 -0
  299. ibm_watsonx_gov/tools/ootb/detectors/hap_detector_tool.py +109 -0
  300. ibm_watsonx_gov/tools/ootb/detectors/jailbreak_detector_tool.py +104 -0
  301. ibm_watsonx_gov/tools/ootb/detectors/pii_detector_tool.py +83 -0
  302. ibm_watsonx_gov/tools/ootb/detectors/prompt_safety_risk_detector_tool.py +111 -0
  303. ibm_watsonx_gov/tools/ootb/detectors/topic_relevance_detector_tool.py +101 -0
  304. ibm_watsonx_gov/tools/ootb/rag/__init__.py +8 -0
  305. ibm_watsonx_gov/tools/ootb/rag/answer_relevance_detector_tool.py +119 -0
  306. ibm_watsonx_gov/tools/ootb/rag/context_relevance_detector_tool.py +118 -0
  307. ibm_watsonx_gov/tools/ootb/search/__init__.py +8 -0
  308. ibm_watsonx_gov/tools/ootb/search/duckduckgo_search_tool.py +62 -0
  309. ibm_watsonx_gov/tools/ootb/search/google_search_tool.py +105 -0
  310. ibm_watsonx_gov/tools/ootb/search/weather_tool.py +95 -0
  311. ibm_watsonx_gov/tools/ootb/search/web_crawler_tool.py +69 -0
  312. ibm_watsonx_gov/tools/ootb/search/wikipedia_search_tool.py +63 -0
  313. ibm_watsonx_gov/tools/ootb/vectordb/__init__.py +8 -0
  314. ibm_watsonx_gov/tools/ootb/vectordb/chromadb_retriever_tool.py +111 -0
  315. ibm_watsonx_gov/tools/rest_api/__init__.py +10 -0
  316. ibm_watsonx_gov/tools/rest_api/restapi_tool.py +72 -0
  317. ibm_watsonx_gov/tools/schemas/__init__.py +10 -0
  318. ibm_watsonx_gov/tools/schemas/search_tool_schema.py +46 -0
  319. ibm_watsonx_gov/tools/schemas/vectordb_retrieval_schema.py +55 -0
  320. ibm_watsonx_gov/tools/utils/__init__.py +14 -0
  321. ibm_watsonx_gov/tools/utils/constants.py +69 -0
  322. ibm_watsonx_gov/tools/utils/display_utils.py +38 -0
  323. ibm_watsonx_gov/tools/utils/environment.py +108 -0
  324. ibm_watsonx_gov/tools/utils/package_utils.py +40 -0
  325. ibm_watsonx_gov/tools/utils/platform_url_mapping.cp313-win_amd64.pyd +0 -0
  326. ibm_watsonx_gov/tools/utils/python_utils.py +68 -0
  327. ibm_watsonx_gov/tools/utils/tool_utils.py +206 -0
  328. ibm_watsonx_gov/traces/__init__.py +8 -0
  329. ibm_watsonx_gov/traces/span_exporter.py +195 -0
  330. ibm_watsonx_gov/traces/span_node.py +251 -0
  331. ibm_watsonx_gov/traces/span_util.py +153 -0
  332. ibm_watsonx_gov/traces/trace_utils.py +1074 -0
  333. ibm_watsonx_gov/utils/__init__.py +8 -0
  334. ibm_watsonx_gov/utils/aggregation_util.py +346 -0
  335. ibm_watsonx_gov/utils/async_util.py +62 -0
  336. ibm_watsonx_gov/utils/authenticator.py +144 -0
  337. ibm_watsonx_gov/utils/constants.py +15 -0
  338. ibm_watsonx_gov/utils/errors.py +40 -0
  339. ibm_watsonx_gov/utils/gov_sdk_logger.py +39 -0
  340. ibm_watsonx_gov/utils/insights_generator.py +1285 -0
  341. ibm_watsonx_gov/utils/python_utils.py +425 -0
  342. ibm_watsonx_gov/utils/rest_util.py +73 -0
  343. ibm_watsonx_gov/utils/segment_batch_manager.py +162 -0
  344. ibm_watsonx_gov/utils/singleton_meta.py +25 -0
  345. ibm_watsonx_gov/utils/url_mapping.cp313-win_amd64.pyd +0 -0
  346. ibm_watsonx_gov/utils/validation_util.py +126 -0
  347. ibm_watsonx_gov/visualizations/__init__.py +13 -0
  348. ibm_watsonx_gov/visualizations/metric_descriptions.py +57 -0
  349. ibm_watsonx_gov/visualizations/model_insights.py +1304 -0
  350. ibm_watsonx_gov/visualizations/visualization_utils.py +75 -0
  351. ibm_watsonx_gov-1.3.3.dist-info/METADATA +93 -0
  352. ibm_watsonx_gov-1.3.3.dist-info/RECORD +353 -0
  353. ibm_watsonx_gov-1.3.3.dist-info/WHEEL +4 -0
@@ -0,0 +1,509 @@
1
+ try:
2
+ import litellm
3
+ except ImportError as e:
4
+ raise ImportError(
5
+ "litellm is not installed. Please install it with `pip install 'llmevalkit[litellm]'`."
6
+ ) from e
7
+
8
+ from typing import Any, Dict, List, Optional, Union, Type
9
+ from llmevalkit.llm.base import LLMClient, register_llm, Hook
10
+ from llmevalkit.llm.types import GenerationMode, LLMResponse, ParameterMapper
11
+ from pydantic import BaseModel
12
+ from llmevalkit.llm.output_parser import ValidatingLLMClient
13
+
14
+
15
+ @register_llm("litellm")
16
+ class LiteLLMClient(LLMClient):
17
+ """
18
+ Adapter for litellm.LiteLLM.
19
+
20
+ LiteLLM only supports chat-based interactions, so this client
21
+ restricts usage to:
22
+ - chat: completion with messages
23
+ - chat_async: acompletion with messages
24
+
25
+ Text-based modes (text, text_async) are not supported.
26
+ """
27
+
28
+ def __init__(
29
+ self, model_name: str, hooks: Optional[List[Hook]] = None, **lite_kwargs: Any
30
+ ) -> None:
31
+ self.model_path = model_name
32
+ self._lite_kwargs = lite_kwargs
33
+ super().__init__(client=None, hooks=hooks, **lite_kwargs)
34
+
35
+ @classmethod
36
+ def provider_class(cls) -> type:
37
+ return litellm
38
+
39
+ def _register_methods(self) -> None:
40
+ """Register LiteLLM methods - only chat and chat_async are supported"""
41
+ self.set_method_config(GenerationMode.CHAT.value, "completion", "messages")
42
+ self.set_method_config(
43
+ GenerationMode.CHAT_ASYNC.value, "acompletion", "messages"
44
+ )
45
+
46
+ def _setup_parameter_mapper(self) -> None:
47
+ """Setup parameter mapping for LiteLLM provider."""
48
+ self._parameter_mapper = ParameterMapper()
49
+
50
+ # LiteLLM uses the same parameters for both chat modes
51
+ # Based on litellm.main.py completion function parameters
52
+
53
+ # Direct mappings (same parameter names)
54
+ for param in [
55
+ "temperature",
56
+ "top_p",
57
+ "frequency_penalty",
58
+ "presence_penalty",
59
+ "seed",
60
+ "timeout",
61
+ "stream",
62
+ "logprobs",
63
+ "echo",
64
+ ]:
65
+ self._parameter_mapper.set_chat_mapping(param, param)
66
+
67
+ # Parameter name mappings
68
+ self._parameter_mapper.set_chat_mapping(
69
+ "max_tokens", "max_tokens"
70
+ ) # or max_completion_tokens
71
+ self._parameter_mapper.set_chat_mapping("stop_sequences", "stop")
72
+ self._parameter_mapper.set_chat_mapping("top_logprobs", "top_logprobs")
73
+
74
+ # Custom transforms for complex parameters
75
+ def transform_top_k(value, mode):
76
+ # LiteLLM doesn't have top_k directly, but some models support it via model_kwargs
77
+ return {"top_k": value}
78
+
79
+ def transform_repetition_penalty(value, mode):
80
+ # Map to frequency_penalty if not already set
81
+ return {"repetition_penalty": value}
82
+
83
+ def transform_decoding_method(value, mode):
84
+ # LiteLLM doesn't have direct decoding_method, map to temperature for approximation
85
+ if value == "greedy":
86
+ return {"temperature": 0.0}
87
+ elif value == "sample":
88
+ return {} # Use default temperature
89
+ else:
90
+ return {} # Unknown method, no transformation
91
+
92
+ self._parameter_mapper.set_custom_transform("top_k", transform_top_k)
93
+ self._parameter_mapper.set_custom_transform(
94
+ "repetition_penalty", transform_repetition_penalty
95
+ )
96
+ self._parameter_mapper.set_custom_transform(
97
+ "decoding_method", transform_decoding_method
98
+ )
99
+
100
+ # Custom transform for min_tokens (not supported by LiteLLM)
101
+ def transform_min_tokens(value, mode):
102
+ # LiteLLM doesn't support min_tokens, so we ignore it and emit a warning
103
+ import warnings
104
+
105
+ warnings.warn(
106
+ f"min_tokens parameter ({value}) is not supported by LiteLLM. Parameter will be ignored.",
107
+ UserWarning,
108
+ )
109
+ return {} # Return empty dict to ignore the parameter
110
+
111
+ self._parameter_mapper.set_custom_transform("min_tokens", transform_min_tokens)
112
+
113
+ def _parse_llm_response(self, raw: Any) -> Union[str, LLMResponse]:
114
+ """
115
+ Extract the assistant-generated text and tool calls from a LiteLLM response.
116
+
117
+ Returns:
118
+ LLMResponse object containing both content and tool calls if present,
119
+ or just the content string if no tool calls
120
+ """
121
+ choices = getattr(raw, "choices", None) or raw.get("choices", [])
122
+ if not choices:
123
+ raise ValueError("LiteLLM response missing 'choices'")
124
+ first = choices[0]
125
+
126
+ content = ""
127
+ tool_calls = []
128
+
129
+ # Extract content
130
+ delta = getattr(first, "delta", None)
131
+ if delta and hasattr(delta, "content") and delta.content:
132
+ content = delta.content
133
+
134
+ msg = getattr(first, "message", None)
135
+ if msg:
136
+ if hasattr(msg, "content") and msg.content:
137
+ content = msg.content
138
+
139
+ # Extract tool calls
140
+ if hasattr(msg, "tool_calls") and msg.tool_calls:
141
+ tool_calls = []
142
+ for tool_call in msg.tool_calls:
143
+ tool_call_dict = {
144
+ "id": getattr(tool_call, "id", None),
145
+ "type": getattr(tool_call, "type", "function"),
146
+ "function": {
147
+ "name": getattr(tool_call.function, "name", None),
148
+ "arguments": getattr(tool_call.function, "arguments", None),
149
+ },
150
+ }
151
+ tool_calls.append(tool_call_dict)
152
+
153
+ if hasattr(first, "text") and first.text:
154
+ content = first.text
155
+
156
+ # Fallback to dict lookup
157
+ if not content:
158
+ content = first.get("delta", {}).get("content", first.get("text", ""))
159
+
160
+ if not content and not tool_calls:
161
+ raise ValueError("No content or tool calls found in response")
162
+
163
+ # Return LLMResponse if tool calls exist, otherwise just content
164
+ if tool_calls:
165
+ return LLMResponse(content=content, tool_calls=tool_calls)
166
+ return content
167
+
168
+ def generate(
169
+ self, prompt: Union[str, List[Dict[str, Any]]], **kwargs: Any
170
+ ) -> Union[str, LLMResponse]:
171
+ """
172
+ Generate response from LiteLLM model using chat mode only.
173
+
174
+ Args:
175
+ prompt: Input prompt (string or list of message dicts)
176
+ **kwargs: Additional parameters for the model
177
+
178
+ Returns:
179
+ LLMResponse if tool calls are present, otherwise string content
180
+
181
+ Raises:
182
+ ValueError: If unsupported generation mode is requested
183
+ """
184
+ # Check if mode is specified and validate it
185
+ requested_mode = kwargs.get("mode")
186
+ if requested_mode is not None:
187
+ # Convert enum to string if needed
188
+ if hasattr(requested_mode, "value"):
189
+ mode_str = requested_mode.value
190
+ else:
191
+ mode_str = str(requested_mode)
192
+
193
+ # Only allow chat and chat_async modes
194
+ if mode_str not in ["chat", "chat_async"]:
195
+ raise ValueError(
196
+ f"LiteLLM clients only support chat modes (chat, chat_async). "
197
+ f"Requested mode '{mode_str}' is not supported."
198
+ )
199
+
200
+ model_str = self.model_path
201
+ mode = GenerationMode.CHAT.value
202
+
203
+ # Normalize prompt to chat format (list of message dicts)
204
+ if isinstance(prompt, str):
205
+ prompt = [{"role": "user", "content": prompt}]
206
+ elif not isinstance(prompt, list):
207
+ raise ValueError("Prompt must be a string or list of message dictionaries")
208
+
209
+ return super().generate(
210
+ **{
211
+ "prompt": prompt,
212
+ "model": model_str,
213
+ "mode": mode,
214
+ **self._lite_kwargs,
215
+ **kwargs,
216
+ }
217
+ )
218
+
219
+ async def generate_async(
220
+ self, prompt: Union[str, List[Dict[str, Any]]], **kwargs: Any
221
+ ) -> Union[str, LLMResponse]:
222
+ """
223
+ Generate response from LiteLLM model asynchronously using chat_async mode only.
224
+
225
+ Args:
226
+ prompt: Input prompt (string or list of message dicts)
227
+ **kwargs: Additional parameters for the model
228
+
229
+ Returns:
230
+ LLMResponse if tool calls are present, otherwise string content
231
+
232
+ Raises:
233
+ ValueError: If unsupported generation mode is requested
234
+ """
235
+ # Check if mode is specified and validate it
236
+ requested_mode = kwargs.get("mode")
237
+ if requested_mode is not None:
238
+ # Convert enum to string if needed
239
+ if hasattr(requested_mode, "value"):
240
+ mode_str = requested_mode.value
241
+ else:
242
+ mode_str = str(requested_mode)
243
+
244
+ # Only allow chat and chat_async modes
245
+ if mode_str not in ["chat", "chat_async"]:
246
+ raise ValueError(
247
+ f"LiteLLM clients only support chat modes (chat, chat_async). "
248
+ f"Requested mode '{mode_str}' is not supported."
249
+ )
250
+
251
+ model_str = self.model_path
252
+ mode = GenerationMode.CHAT_ASYNC.value
253
+
254
+ # Normalize prompt to chat format (list of message dicts)
255
+ if isinstance(prompt, str):
256
+ prompt = [{"role": "user", "content": prompt}]
257
+ elif not isinstance(prompt, list):
258
+ raise ValueError("Prompt must be a string or list of message dictionaries")
259
+
260
+ return await super().generate_async(
261
+ **{
262
+ "prompt": prompt,
263
+ "model": model_str,
264
+ "mode": mode,
265
+ **self._lite_kwargs,
266
+ **kwargs,
267
+ }
268
+ )
269
+
270
+
271
+ @register_llm("litellm.output_val")
272
+ class LiteLLMClientOutputVal(ValidatingLLMClient):
273
+ """
274
+ Validating adapter for litellm.LiteLLM.
275
+
276
+ Extends ValidatingLLMClient to enforce output structure (via JSON Schema,
277
+ Pydantic models, or simple Python types) on all generate calls,
278
+ with retries and batch support (sync & async).
279
+ """
280
+
281
+ def __init__(
282
+ self, model_name: str, hooks: Optional[List[Hook]] = None, **lite_kwargs: Any
283
+ ) -> None:
284
+ """
285
+ Initialize a LiteLLMClient.
286
+
287
+ Args:
288
+ model_name: Identifier or path for the LiteLLM model.
289
+ hooks: Optional observability hooks (callable(event, payload)).
290
+ lite_kwargs: Extra arguments passed when initializing the litellm client.
291
+ """
292
+ self.model_path = model_name
293
+ self._lite_kwargs = lite_kwargs
294
+ super().__init__(client=None, hooks=hooks, **lite_kwargs)
295
+
296
+ @classmethod
297
+ def provider_class(cls) -> Type:
298
+ """
299
+ Underlying SDK client for litellm.
300
+
301
+ Must be callable with no arguments (per LLMClient __init__ logic).
302
+ """
303
+ return litellm
304
+
305
+ def _register_methods(self) -> None:
306
+ """
307
+ Register how to call litellm methods - only chat modes are supported:
308
+
309
+ - 'chat' → litellm.completion
310
+ - 'chat_async' → litellm.acompletion
311
+ """
312
+ self.set_method_config(GenerationMode.CHAT.value, "completion", "messages")
313
+ self.set_method_config(
314
+ GenerationMode.CHAT_ASYNC.value, "acompletion", "messages"
315
+ )
316
+
317
+ def _setup_parameter_mapper(self) -> None:
318
+ """Setup parameter mapping for LiteLLM provider (same as regular LiteLLM)."""
319
+ self._parameter_mapper = ParameterMapper()
320
+
321
+ # LiteLLM uses the same parameters for both chat modes
322
+ for param in [
323
+ "temperature",
324
+ "top_p",
325
+ "frequency_penalty",
326
+ "presence_penalty",
327
+ "seed",
328
+ "timeout",
329
+ "stream",
330
+ "logprobs",
331
+ "echo",
332
+ ]:
333
+ self._parameter_mapper.set_chat_mapping(param, param)
334
+
335
+ self._parameter_mapper.set_chat_mapping("max_tokens", "max_tokens")
336
+ self._parameter_mapper.set_chat_mapping("stop_sequences", "stop")
337
+ self._parameter_mapper.set_chat_mapping("top_logprobs", "top_logprobs")
338
+
339
+ def transform_top_k(value, mode):
340
+ return {"top_k": value}
341
+
342
+ def transform_repetition_penalty(value, mode):
343
+ return {"repetition_penalty": value}
344
+
345
+ def transform_decoding_method(value, mode):
346
+ # LiteLLM doesn't have direct decoding_method, map to temperature for approximation
347
+ if value == "greedy":
348
+ return {"temperature": 0.0}
349
+ elif value == "sample":
350
+ return {} # Use default temperature
351
+ else:
352
+ return {} # Unknown method, no transformation
353
+
354
+ self._parameter_mapper.set_custom_transform("top_k", transform_top_k)
355
+ self._parameter_mapper.set_custom_transform(
356
+ "repetition_penalty", transform_repetition_penalty
357
+ )
358
+ self._parameter_mapper.set_custom_transform(
359
+ "decoding_method", transform_decoding_method
360
+ )
361
+
362
+ # Custom transform for min_tokens (not supported by LiteLLM)
363
+ def transform_min_tokens(value, mode):
364
+ # LiteLLM doesn't support min_tokens, so we ignore it and emit a warning
365
+ import warnings
366
+
367
+ warnings.warn(
368
+ f"min_tokens parameter ({value}) is not supported by LiteLLM. Parameter will be ignored.",
369
+ UserWarning,
370
+ )
371
+ return {} # Return empty dict to ignore the parameter
372
+
373
+ self._parameter_mapper.set_custom_transform("min_tokens", transform_min_tokens)
374
+
375
+ def _parse_llm_response(self, raw: Any) -> Union[str, LLMResponse]:
376
+ """
377
+ Extract the assistant-generated text and tool calls from a LiteLLM response.
378
+
379
+ Returns:
380
+ LLMResponse object containing both content and tool calls if present,
381
+ or just the content string if no tool calls
382
+ """
383
+ choices = getattr(raw, "choices", None) or raw.get("choices", [])
384
+ if not choices:
385
+ raise ValueError("LiteLLM response missing 'choices'")
386
+ first = choices[0]
387
+
388
+ content = ""
389
+ tool_calls = []
390
+
391
+ # Extract content
392
+ delta = getattr(first, "delta", None)
393
+ if delta and hasattr(delta, "content") and delta.content:
394
+ content = delta.content
395
+
396
+ msg = getattr(first, "message", None)
397
+ if msg:
398
+ if hasattr(msg, "content") and msg.content:
399
+ content = msg.content
400
+
401
+ # Extract tool calls
402
+ if hasattr(msg, "tool_calls") and msg.tool_calls:
403
+ tool_calls = []
404
+ for tool_call in msg.tool_calls:
405
+ tool_call_dict = {
406
+ "id": getattr(tool_call, "id", None),
407
+ "type": getattr(tool_call, "type", "function"),
408
+ "function": {
409
+ "name": getattr(tool_call.function, "name", None),
410
+ "arguments": getattr(tool_call.function, "arguments", None),
411
+ },
412
+ }
413
+ tool_calls.append(tool_call_dict)
414
+
415
+ if hasattr(first, "text") and first.text:
416
+ content = first.text
417
+
418
+ # Fallback to dict lookup
419
+ if not content:
420
+ content = first.get("delta", {}).get("content", first.get("text", ""))
421
+
422
+ if not content and not tool_calls:
423
+ raise ValueError("No content or tool calls found in response")
424
+
425
+ # Return LLMResponse if tool calls exist, otherwise just content
426
+ if tool_calls:
427
+ return LLMResponse(content=content, tool_calls=tool_calls)
428
+ return content
429
+
430
+ def generate(
431
+ self,
432
+ prompt: Union[str, List[Dict[str, Any]]],
433
+ *,
434
+ schema: Union[Dict[str, Any], Type[BaseModel], Type],
435
+ schema_field: Optional[str] = "response_format",
436
+ retries: int = 3,
437
+ **kwargs: Any,
438
+ ) -> Any:
439
+ """
440
+ Synchronous chat generation with validation + retries.
441
+
442
+ Args:
443
+ prompt: Either a string or a list of chat messages.
444
+ schema: JSON Schema dict, Pydantic model class, or built-in Python type.
445
+ retries: Maximum attempts (including the first).
446
+ **kwargs: Passed to the underlying litellm call (e.g. temperature).
447
+
448
+ Returns:
449
+ The parsed & validated Python object (or Pydantic instance).
450
+ """
451
+ model = self.model_path
452
+ mode = GenerationMode.CHAT.value
453
+
454
+ # Normalize prompt to chat-messages
455
+ if isinstance(prompt, str):
456
+ prompt = [{"role": "user", "content": prompt}]
457
+ elif not isinstance(prompt, list):
458
+ raise ValueError(
459
+ "LiteLLM only supports chat mode with string or list of message dictionaries"
460
+ )
461
+
462
+ # Delegate to ValidatingLLMClient.generate
463
+ return super().generate(
464
+ **{
465
+ "prompt": prompt,
466
+ "schema": schema,
467
+ "schema_field": schema_field,
468
+ "retries": retries,
469
+ "model": model,
470
+ "mode": mode,
471
+ **self._lite_kwargs,
472
+ **kwargs,
473
+ }
474
+ )
475
+
476
+ async def generate_async(
477
+ self,
478
+ prompt: Union[str, List[Dict[str, Any]]],
479
+ *,
480
+ schema: Union[Dict[str, Any], Type[BaseModel], Type],
481
+ schema_field: Optional[str] = "response_format",
482
+ retries: int = 3,
483
+ **kwargs: Any,
484
+ ) -> Any:
485
+ """
486
+ Asynchronous chat generation with validation + retries.
487
+ """
488
+ model = self.model_path
489
+ mode = GenerationMode.CHAT_ASYNC.value
490
+
491
+ if isinstance(prompt, str):
492
+ prompt = [{"role": "user", "content": prompt}]
493
+ elif not isinstance(prompt, list):
494
+ raise ValueError(
495
+ "LiteLLM only supports chat mode with string or list of message dictionaries"
496
+ )
497
+
498
+ return await super().generate_async(
499
+ **{
500
+ "prompt": prompt,
501
+ "schema": schema,
502
+ "schema_field": schema_field,
503
+ "retries": retries,
504
+ "model": model,
505
+ "mode": mode,
506
+ **self._lite_kwargs,
507
+ **kwargs,
508
+ }
509
+ )