scitex 2.0.0__py2.py3-none-any.whl → 2.1.0__py2.py3-none-any.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.
- scitex/__init__.py +53 -15
- scitex/__main__.py +72 -26
- scitex/__version__.py +1 -1
- scitex/_sh.py +145 -23
- scitex/ai/__init__.py +30 -16
- scitex/ai/_gen_ai/_Anthropic.py +5 -7
- scitex/ai/_gen_ai/_BaseGenAI.py +2 -2
- scitex/ai/_gen_ai/_DeepSeek.py +10 -2
- scitex/ai/_gen_ai/_Google.py +2 -2
- scitex/ai/_gen_ai/_Llama.py +2 -2
- scitex/ai/_gen_ai/_OpenAI.py +2 -2
- scitex/ai/_gen_ai/_PARAMS.py +51 -65
- scitex/ai/_gen_ai/_Perplexity.py +2 -2
- scitex/ai/_gen_ai/__init__.py +25 -14
- scitex/ai/_gen_ai/_format_output_func.py +4 -4
- scitex/ai/classification/{classifier_server.py → Classifier.py} +5 -5
- scitex/ai/classification/CrossValidationExperiment.py +374 -0
- scitex/ai/classification/__init__.py +43 -4
- scitex/ai/classification/reporters/_BaseClassificationReporter.py +281 -0
- scitex/ai/classification/reporters/_ClassificationReporter.py +773 -0
- scitex/ai/classification/reporters/_MultiClassificationReporter.py +406 -0
- scitex/ai/classification/reporters/_SingleClassificationReporter.py +1834 -0
- scitex/ai/classification/reporters/__init__.py +11 -0
- scitex/ai/classification/reporters/reporter_utils/_Plotter.py +1028 -0
- scitex/ai/classification/reporters/reporter_utils/__init__.py +80 -0
- scitex/ai/classification/reporters/reporter_utils/aggregation.py +457 -0
- scitex/ai/classification/reporters/reporter_utils/data_models.py +313 -0
- scitex/ai/classification/reporters/reporter_utils/reporting.py +1056 -0
- scitex/ai/classification/reporters/reporter_utils/storage.py +221 -0
- scitex/ai/classification/reporters/reporter_utils/validation.py +395 -0
- scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
- scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
- scitex/ai/classification/timeseries/_TimeSeriesMetadata.py +139 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
- scitex/ai/classification/timeseries/_TimeSeriesStrategy.py +84 -0
- scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
- scitex/ai/classification/timeseries/__init__.py +39 -0
- scitex/ai/classification/timeseries/_normalize_timestamp.py +436 -0
- scitex/ai/clustering/_umap.py +2 -2
- scitex/ai/feature_extraction/vit.py +1 -0
- scitex/ai/feature_selection/__init__.py +30 -0
- scitex/ai/feature_selection/feature_selection.py +364 -0
- scitex/ai/loss/multi_task_loss.py +1 -1
- scitex/ai/metrics/__init__.py +51 -4
- scitex/ai/metrics/_calc_bacc.py +61 -0
- scitex/ai/metrics/_calc_bacc_from_conf_mat.py +38 -0
- scitex/ai/metrics/_calc_clf_report.py +78 -0
- scitex/ai/metrics/_calc_conf_mat.py +93 -0
- scitex/ai/metrics/_calc_feature_importance.py +183 -0
- scitex/ai/metrics/_calc_mcc.py +61 -0
- scitex/ai/metrics/_calc_pre_rec_auc.py +116 -0
- scitex/ai/metrics/_calc_roc_auc.py +110 -0
- scitex/ai/metrics/_calc_seizure_prediction_metrics.py +490 -0
- scitex/ai/metrics/{silhoute_score_block.py → _calc_silhouette_score.py} +15 -8
- scitex/ai/metrics/_normalize_labels.py +83 -0
- scitex/ai/plt/__init__.py +47 -8
- scitex/ai/plt/{_conf_mat.py → _plot_conf_mat.py} +158 -87
- scitex/ai/plt/_plot_feature_importance.py +323 -0
- scitex/ai/plt/_plot_learning_curve.py +345 -0
- scitex/ai/plt/_plot_optuna_study.py +225 -0
- scitex/ai/plt/_plot_pre_rec_curve.py +290 -0
- scitex/ai/plt/_plot_roc_curve.py +255 -0
- scitex/ai/training/{learning_curve_logger.py → _LearningCurveLogger.py} +197 -213
- scitex/ai/training/__init__.py +2 -2
- scitex/ai/utils/grid_search.py +3 -3
- scitex/benchmark/__init__.py +52 -0
- scitex/benchmark/benchmark.py +400 -0
- scitex/benchmark/monitor.py +370 -0
- scitex/benchmark/profiler.py +297 -0
- scitex/browser/__init__.py +48 -0
- scitex/browser/automation/CookieHandler.py +216 -0
- scitex/browser/automation/__init__.py +7 -0
- scitex/browser/collaboration/__init__.py +55 -0
- scitex/browser/collaboration/auth_helpers.py +94 -0
- scitex/browser/collaboration/collaborative_agent.py +136 -0
- scitex/browser/collaboration/credential_manager.py +188 -0
- scitex/browser/collaboration/interactive_panel.py +400 -0
- scitex/browser/collaboration/persistent_browser.py +170 -0
- scitex/browser/collaboration/shared_session.py +383 -0
- scitex/browser/collaboration/standard_interactions.py +246 -0
- scitex/browser/collaboration/visual_feedback.py +181 -0
- scitex/browser/core/BrowserMixin.py +326 -0
- scitex/browser/core/ChromeProfileManager.py +446 -0
- scitex/browser/core/__init__.py +9 -0
- scitex/browser/debugging/__init__.py +18 -0
- scitex/browser/debugging/_browser_logger.py +657 -0
- scitex/browser/debugging/_highlight_element.py +143 -0
- scitex/browser/debugging/_show_grid.py +154 -0
- scitex/browser/interaction/__init__.py +24 -0
- scitex/browser/interaction/click_center.py +149 -0
- scitex/browser/interaction/click_with_fallbacks.py +206 -0
- scitex/browser/interaction/close_popups.py +498 -0
- scitex/browser/interaction/fill_with_fallbacks.py +209 -0
- scitex/browser/pdf/__init__.py +14 -0
- scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +200 -0
- scitex/browser/pdf/detect_chrome_pdf_viewer.py +198 -0
- scitex/browser/remote/CaptchaHandler.py +434 -0
- scitex/browser/remote/ZenRowsAPIClient.py +347 -0
- scitex/browser/remote/ZenRowsBrowserManager.py +570 -0
- scitex/browser/remote/__init__.py +11 -0
- scitex/browser/stealth/HumanBehavior.py +344 -0
- scitex/browser/stealth/StealthManager.py +1008 -0
- scitex/browser/stealth/__init__.py +9 -0
- scitex/browser/template.py +122 -0
- scitex/capture/__init__.py +110 -0
- scitex/capture/__main__.py +25 -0
- scitex/capture/capture.py +848 -0
- scitex/capture/cli.py +233 -0
- scitex/capture/gif.py +344 -0
- scitex/capture/mcp_server.py +961 -0
- scitex/capture/session.py +70 -0
- scitex/capture/utils.py +705 -0
- scitex/cli/__init__.py +17 -0
- scitex/cli/cloud.py +447 -0
- scitex/cli/main.py +42 -0
- scitex/cli/scholar.py +280 -0
- scitex/context/_suppress_output.py +5 -3
- scitex/db/__init__.py +30 -3
- scitex/db/__main__.py +75 -0
- scitex/db/_check_health.py +381 -0
- scitex/db/_delete_duplicates.py +25 -386
- scitex/db/_inspect.py +335 -114
- scitex/db/_inspect_optimized.py +301 -0
- scitex/db/{_PostgreSQL.py → _postgresql/_PostgreSQL.py} +3 -3
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BackupMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BatchMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BlobMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ConnectionMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_MaintenanceMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_QueryMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_SchemaMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TransactionMixin.py +1 -1
- scitex/db/_postgresql/__init__.py +6 -0
- scitex/db/_sqlite3/_SQLite3.py +210 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin.py +581 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin_v01-need-_hash-col.py +517 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_BatchMixin.py +1 -1
- scitex/db/_sqlite3/_SQLite3Mixins/_BlobMixin.py +281 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin.py +548 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin_v01-indentation-issues.py +583 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ConnectionMixin.py +29 -13
- scitex/db/_sqlite3/_SQLite3Mixins/_GitMixin.py +583 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ImportExportMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_IndexMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_MaintenanceMixin.py +2 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_QueryMixin.py +37 -10
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_RowMixin.py +46 -6
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TableMixin.py +56 -10
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TransactionMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/__init__.py +14 -2
- scitex/db/_sqlite3/__init__.py +7 -0
- scitex/db/_sqlite3/_delete_duplicates.py +274 -0
- scitex/decorators/__init__.py +2 -0
- scitex/decorators/_cache_disk.py +13 -5
- scitex/decorators/_cache_disk_async.py +49 -0
- scitex/decorators/_deprecated.py +175 -10
- scitex/decorators/_timeout.py +1 -1
- scitex/dev/_analyze_code_flow.py +2 -2
- scitex/dict/_DotDict.py +73 -15
- scitex/dict/_DotDict_v01-not-handling-recursive-instantiations.py +442 -0
- scitex/dict/_DotDict_v02-not-serializing-Path-object.py +446 -0
- scitex/dict/__init__.py +2 -0
- scitex/dict/_flatten.py +27 -0
- scitex/dsp/_crop.py +2 -2
- scitex/dsp/_demo_sig.py +2 -2
- scitex/dsp/_detect_ripples.py +2 -2
- scitex/dsp/_hilbert.py +2 -2
- scitex/dsp/_listen.py +6 -6
- scitex/dsp/_modulation_index.py +2 -2
- scitex/dsp/_pac.py +1 -1
- scitex/dsp/_psd.py +2 -2
- scitex/dsp/_resample.py +2 -1
- scitex/dsp/_time.py +3 -2
- scitex/dsp/_wavelet.py +3 -2
- scitex/dsp/add_noise.py +2 -2
- scitex/dsp/example.py +1 -0
- scitex/dsp/filt.py +10 -9
- scitex/dsp/template.py +3 -2
- scitex/dsp/utils/_differential_bandpass_filters.py +1 -1
- scitex/dsp/utils/pac.py +2 -2
- scitex/dt/_normalize_timestamp.py +432 -0
- scitex/errors.py +572 -0
- scitex/gen/_DimHandler.py +2 -2
- scitex/gen/__init__.py +37 -7
- scitex/gen/_deprecated_close.py +80 -0
- scitex/gen/_deprecated_start.py +26 -0
- scitex/gen/_detect_environment.py +152 -0
- scitex/gen/_detect_notebook_path.py +169 -0
- scitex/gen/_embed.py +6 -2
- scitex/gen/_get_notebook_path.py +257 -0
- scitex/gen/_less.py +1 -1
- scitex/gen/_list_packages.py +2 -2
- scitex/gen/_norm.py +44 -9
- scitex/gen/_norm_cache.py +269 -0
- scitex/gen/_src.py +3 -5
- scitex/gen/_title_case.py +3 -3
- scitex/io/__init__.py +28 -6
- scitex/io/_glob.py +13 -7
- scitex/io/_load.py +108 -21
- scitex/io/_load_cache.py +303 -0
- scitex/io/_load_configs.py +40 -15
- scitex/io/{_H5Explorer.py → _load_modules/_H5Explorer.py} +80 -17
- scitex/io/_load_modules/_ZarrExplorer.py +114 -0
- scitex/io/_load_modules/_bibtex.py +207 -0
- scitex/io/_load_modules/_hdf5.py +53 -178
- scitex/io/_load_modules/_json.py +5 -3
- scitex/io/_load_modules/_pdf.py +871 -16
- scitex/io/_load_modules/_sqlite3.py +15 -0
- scitex/io/_load_modules/_txt.py +41 -12
- scitex/io/_load_modules/_yaml.py +4 -3
- scitex/io/_load_modules/_zarr.py +126 -0
- scitex/io/_save.py +429 -171
- scitex/io/_save_modules/__init__.py +6 -0
- scitex/io/_save_modules/_bibtex.py +194 -0
- scitex/io/_save_modules/_csv.py +8 -4
- scitex/io/_save_modules/_excel.py +174 -15
- scitex/io/_save_modules/_hdf5.py +251 -226
- scitex/io/_save_modules/_image.py +1 -3
- scitex/io/_save_modules/_json.py +49 -4
- scitex/io/_save_modules/_listed_dfs_as_csv.py +1 -3
- scitex/io/_save_modules/_listed_scalars_as_csv.py +1 -3
- scitex/io/_save_modules/_tex.py +277 -0
- scitex/io/_save_modules/_yaml.py +42 -3
- scitex/io/_save_modules/_zarr.py +160 -0
- scitex/io/utils/__init__.py +20 -0
- scitex/io/utils/h5_to_zarr.py +616 -0
- scitex/linalg/_geometric_median.py +6 -2
- scitex/{gen/_tee.py → logging/_Tee.py} +43 -84
- scitex/logging/__init__.py +122 -0
- scitex/logging/_config.py +158 -0
- scitex/logging/_context.py +103 -0
- scitex/logging/_formatters.py +128 -0
- scitex/logging/_handlers.py +64 -0
- scitex/logging/_levels.py +35 -0
- scitex/logging/_logger.py +163 -0
- scitex/logging/_print_capture.py +95 -0
- scitex/ml/__init__.py +69 -0
- scitex/{ai/genai/anthropic.py → ml/_gen_ai/_Anthropic.py} +13 -19
- scitex/{ai/genai/base_genai.py → ml/_gen_ai/_BaseGenAI.py} +5 -5
- scitex/{ai/genai/deepseek.py → ml/_gen_ai/_DeepSeek.py} +11 -16
- scitex/{ai/genai/google.py → ml/_gen_ai/_Google.py} +7 -15
- scitex/{ai/genai/groq.py → ml/_gen_ai/_Groq.py} +1 -8
- scitex/{ai/genai/llama.py → ml/_gen_ai/_Llama.py} +3 -16
- scitex/{ai/genai/openai.py → ml/_gen_ai/_OpenAI.py} +3 -3
- scitex/{ai/genai/params.py → ml/_gen_ai/_PARAMS.py} +51 -65
- scitex/{ai/genai/perplexity.py → ml/_gen_ai/_Perplexity.py} +3 -14
- scitex/ml/_gen_ai/__init__.py +43 -0
- scitex/{ai/genai/calc_cost.py → ml/_gen_ai/_calc_cost.py} +1 -1
- scitex/{ai/genai/format_output_func.py → ml/_gen_ai/_format_output_func.py} +4 -4
- scitex/{ai/genai/genai_factory.py → ml/_gen_ai/_genai_factory.py} +8 -8
- scitex/ml/activation/__init__.py +8 -0
- scitex/ml/activation/_define.py +11 -0
- scitex/{ai/classifier_server.py → ml/classification/Classifier.py} +5 -5
- scitex/ml/classification/CrossValidationExperiment.py +374 -0
- scitex/ml/classification/__init__.py +46 -0
- scitex/ml/classification/reporters/_BaseClassificationReporter.py +281 -0
- scitex/ml/classification/reporters/_ClassificationReporter.py +773 -0
- scitex/ml/classification/reporters/_MultiClassificationReporter.py +406 -0
- scitex/ml/classification/reporters/_SingleClassificationReporter.py +1834 -0
- scitex/ml/classification/reporters/__init__.py +11 -0
- scitex/ml/classification/reporters/reporter_utils/_Plotter.py +1028 -0
- scitex/ml/classification/reporters/reporter_utils/__init__.py +80 -0
- scitex/ml/classification/reporters/reporter_utils/aggregation.py +457 -0
- scitex/ml/classification/reporters/reporter_utils/data_models.py +313 -0
- scitex/ml/classification/reporters/reporter_utils/reporting.py +1056 -0
- scitex/ml/classification/reporters/reporter_utils/storage.py +221 -0
- scitex/ml/classification/reporters/reporter_utils/validation.py +395 -0
- scitex/ml/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
- scitex/ml/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
- scitex/ml/classification/timeseries/_TimeSeriesMetadata.py +139 -0
- scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
- scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
- scitex/ml/classification/timeseries/_TimeSeriesStrategy.py +84 -0
- scitex/ml/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
- scitex/ml/classification/timeseries/__init__.py +39 -0
- scitex/ml/classification/timeseries/_normalize_timestamp.py +436 -0
- scitex/ml/clustering/__init__.py +11 -0
- scitex/ml/clustering/_pca.py +115 -0
- scitex/ml/clustering/_umap.py +376 -0
- scitex/ml/feature_extraction/__init__.py +56 -0
- scitex/ml/feature_extraction/vit.py +149 -0
- scitex/ml/feature_selection/__init__.py +30 -0
- scitex/ml/feature_selection/feature_selection.py +364 -0
- scitex/ml/loss/_L1L2Losses.py +34 -0
- scitex/ml/loss/__init__.py +12 -0
- scitex/ml/loss/multi_task_loss.py +47 -0
- scitex/ml/metrics/__init__.py +56 -0
- scitex/ml/metrics/_calc_bacc.py +61 -0
- scitex/ml/metrics/_calc_bacc_from_conf_mat.py +38 -0
- scitex/ml/metrics/_calc_clf_report.py +78 -0
- scitex/ml/metrics/_calc_conf_mat.py +93 -0
- scitex/ml/metrics/_calc_feature_importance.py +183 -0
- scitex/ml/metrics/_calc_mcc.py +61 -0
- scitex/ml/metrics/_calc_pre_rec_auc.py +116 -0
- scitex/ml/metrics/_calc_roc_auc.py +110 -0
- scitex/ml/metrics/_calc_seizure_prediction_metrics.py +490 -0
- scitex/ml/metrics/_calc_silhouette_score.py +503 -0
- scitex/ml/metrics/_normalize_labels.py +83 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/__init__.py +0 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/__init__.py +3 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger.py +207 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger2020.py +238 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger913A.py +215 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/rangerqh.py +184 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/setup.py +24 -0
- scitex/ml/optim/__init__.py +13 -0
- scitex/ml/optim/_get_set.py +31 -0
- scitex/ml/optim/_optimizers.py +71 -0
- scitex/ml/plt/__init__.py +60 -0
- scitex/ml/plt/_plot_conf_mat.py +663 -0
- scitex/ml/plt/_plot_feature_importance.py +323 -0
- scitex/ml/plt/_plot_learning_curve.py +345 -0
- scitex/ml/plt/_plot_optuna_study.py +225 -0
- scitex/ml/plt/_plot_pre_rec_curve.py +290 -0
- scitex/ml/plt/_plot_roc_curve.py +255 -0
- scitex/ml/sk/__init__.py +11 -0
- scitex/ml/sk/_clf.py +58 -0
- scitex/ml/sk/_to_sktime.py +100 -0
- scitex/ml/sklearn/__init__.py +26 -0
- scitex/ml/sklearn/clf.py +58 -0
- scitex/ml/sklearn/to_sktime.py +100 -0
- scitex/{ai/training/early_stopping.py → ml/training/_EarlyStopping.py} +1 -2
- scitex/{ai → ml/training}/_LearningCurveLogger.py +198 -242
- scitex/ml/training/__init__.py +7 -0
- scitex/ml/utils/__init__.py +22 -0
- scitex/ml/utils/_check_params.py +50 -0
- scitex/ml/utils/_default_dataset.py +46 -0
- scitex/ml/utils/_format_samples_for_sktime.py +26 -0
- scitex/ml/utils/_label_encoder.py +134 -0
- scitex/ml/utils/_merge_labels.py +22 -0
- scitex/ml/utils/_sliding_window_data_augmentation.py +11 -0
- scitex/ml/utils/_under_sample.py +51 -0
- scitex/ml/utils/_verify_n_gpus.py +16 -0
- scitex/ml/utils/grid_search.py +148 -0
- scitex/nn/_BNet.py +15 -9
- scitex/nn/_Filters.py +2 -2
- scitex/nn/_ModulationIndex.py +2 -2
- scitex/nn/_PAC.py +1 -1
- scitex/nn/_Spectrogram.py +12 -3
- scitex/nn/__init__.py +9 -10
- scitex/path/__init__.py +18 -0
- scitex/path/_clean.py +4 -0
- scitex/path/_find.py +9 -4
- scitex/path/_symlink.py +348 -0
- scitex/path/_version.py +4 -3
- scitex/pd/__init__.py +2 -0
- scitex/pd/_get_unique.py +99 -0
- scitex/plt/__init__.py +114 -5
- scitex/plt/_subplots/_AxesWrapper.py +1 -3
- scitex/plt/_subplots/_AxisWrapper.py +7 -3
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +47 -13
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +160 -2
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +26 -4
- scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +322 -0
- scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +1 -0
- scitex/plt/_subplots/_FigWrapper.py +62 -6
- scitex/plt/_subplots/_export_as_csv.py +43 -27
- scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +5 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py +81 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_bar.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_barh.py +20 -5
- scitex/plt/_subplots/_export_as_csv_formatters/_format_boxplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_contour.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_errorbar.py +35 -18
- scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill_between.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_hist.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +15 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_box.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_conf_mat.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_ecdf.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_fillv.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_heatmap.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_image.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_joyplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_line.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_ci.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_std.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_median_iqr.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_raster.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_rectangle.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter.py +35 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter_hist.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_shaded_line.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_violin.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_scatter.py +6 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_barplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_boxplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_heatmap.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_histplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_kdeplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_scatterplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_stripplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_swarmplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_violinplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_text.py +60 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violin.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violinplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters.py +56 -59
- scitex/plt/ax/_style/_hide_spines.py +1 -3
- scitex/plt/ax/_style/_rotate_labels.py +180 -76
- scitex/plt/ax/_style/_rotate_labels_v01.py +248 -0
- scitex/plt/ax/_style/_set_meta.py +11 -4
- scitex/plt/ax/_style/_set_supxyt.py +3 -3
- scitex/plt/ax/_style/_set_xyt.py +3 -3
- scitex/plt/ax/_style/_share_axes.py +2 -2
- scitex/plt/color/__init__.py +4 -4
- scitex/plt/color/{_get_colors_from_cmap.py → _get_colors_from_conf_matap.py} +7 -7
- scitex/plt/utils/_configure_mpl.py +99 -86
- scitex/plt/utils/_histogram_utils.py +1 -3
- scitex/plt/utils/_is_valid_axis.py +1 -3
- scitex/plt/utils/_scitex_config.py +1 -0
- scitex/repro/__init__.py +75 -0
- scitex/{reproduce → repro}/_gen_ID.py +1 -1
- scitex/{reproduce → repro}/_gen_timestamp.py +1 -1
- scitex/repro_rng/_RandomStateManager.py +590 -0
- scitex/repro_rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
- scitex/repro_rng/__init__.py +39 -0
- scitex/reproduce/__init__.py +25 -13
- scitex/reproduce/_hash_array.py +22 -0
- scitex/resource/_get_processor_usages.py +4 -4
- scitex/resource/_get_specs.py +2 -2
- scitex/resource/_log_processor_usages.py +2 -2
- scitex/rng/_RandomStateManager.py +590 -0
- scitex/rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
- scitex/rng/__init__.py +39 -0
- scitex/scholar/__init__.py +309 -19
- scitex/scholar/__main__.py +319 -0
- scitex/scholar/auth/ScholarAuthManager.py +308 -0
- scitex/scholar/auth/__init__.py +12 -0
- scitex/scholar/auth/core/AuthenticationGateway.py +473 -0
- scitex/scholar/auth/core/BrowserAuthenticator.py +386 -0
- scitex/scholar/auth/core/StrategyResolver.py +309 -0
- scitex/scholar/auth/core/__init__.py +16 -0
- scitex/scholar/auth/gateway/_OpenURLLinkFinder.py +120 -0
- scitex/scholar/auth/gateway/_OpenURLResolver.py +209 -0
- scitex/scholar/auth/gateway/__init__.py +38 -0
- scitex/scholar/auth/gateway/_resolve_functions.py +101 -0
- scitex/scholar/auth/providers/BaseAuthenticator.py +166 -0
- scitex/scholar/auth/providers/EZProxyAuthenticator.py +484 -0
- scitex/scholar/auth/providers/OpenAthensAuthenticator.py +619 -0
- scitex/scholar/auth/providers/ShibbolethAuthenticator.py +686 -0
- scitex/scholar/auth/providers/__init__.py +18 -0
- scitex/scholar/auth/session/AuthCacheManager.py +189 -0
- scitex/scholar/auth/session/SessionManager.py +159 -0
- scitex/scholar/auth/session/__init__.py +11 -0
- scitex/scholar/auth/sso/BaseSSOAutomator.py +373 -0
- scitex/scholar/auth/sso/OpenAthensSSOAutomator.py +378 -0
- scitex/scholar/auth/sso/SSOAutomator.py +180 -0
- scitex/scholar/auth/sso/UniversityOfMelbourneSSOAutomator.py +380 -0
- scitex/scholar/auth/sso/__init__.py +15 -0
- scitex/scholar/browser/ScholarBrowserManager.py +705 -0
- scitex/scholar/browser/__init__.py +38 -0
- scitex/scholar/browser/utils/__init__.py +13 -0
- scitex/scholar/browser/utils/click_and_wait.py +205 -0
- scitex/scholar/browser/utils/close_unwanted_pages.py +140 -0
- scitex/scholar/browser/utils/wait_redirects.py +732 -0
- scitex/scholar/config/PublisherRules.py +132 -0
- scitex/scholar/config/ScholarConfig.py +126 -0
- scitex/scholar/config/__init__.py +17 -0
- scitex/scholar/core/Paper.py +627 -0
- scitex/scholar/core/Papers.py +722 -0
- scitex/scholar/core/Scholar.py +1975 -0
- scitex/scholar/core/__init__.py +9 -0
- scitex/scholar/impact_factor/ImpactFactorEngine.py +204 -0
- scitex/scholar/impact_factor/__init__.py +20 -0
- scitex/scholar/impact_factor/estimation/ImpactFactorEstimationEngine.py +0 -0
- scitex/scholar/impact_factor/estimation/__init__.py +40 -0
- scitex/scholar/impact_factor/estimation/build_database.py +0 -0
- scitex/scholar/impact_factor/estimation/core/__init__.py +28 -0
- scitex/scholar/impact_factor/estimation/core/cache_manager.py +523 -0
- scitex/scholar/impact_factor/estimation/core/calculator.py +355 -0
- scitex/scholar/impact_factor/estimation/core/journal_matcher.py +428 -0
- scitex/scholar/integration/__init__.py +59 -0
- scitex/scholar/integration/base.py +502 -0
- scitex/scholar/integration/mendeley/__init__.py +22 -0
- scitex/scholar/integration/mendeley/exporter.py +166 -0
- scitex/scholar/integration/mendeley/importer.py +236 -0
- scitex/scholar/integration/mendeley/linker.py +79 -0
- scitex/scholar/integration/mendeley/mapper.py +212 -0
- scitex/scholar/integration/zotero/__init__.py +27 -0
- scitex/scholar/integration/zotero/__main__.py +264 -0
- scitex/scholar/integration/zotero/exporter.py +351 -0
- scitex/scholar/integration/zotero/importer.py +372 -0
- scitex/scholar/integration/zotero/linker.py +415 -0
- scitex/scholar/integration/zotero/mapper.py +286 -0
- scitex/scholar/metadata_engines/ScholarEngine.py +588 -0
- scitex/scholar/metadata_engines/__init__.py +21 -0
- scitex/scholar/metadata_engines/individual/ArXivEngine.py +397 -0
- scitex/scholar/metadata_engines/individual/CrossRefEngine.py +274 -0
- scitex/scholar/metadata_engines/individual/CrossRefLocalEngine.py +263 -0
- scitex/scholar/metadata_engines/individual/OpenAlexEngine.py +350 -0
- scitex/scholar/metadata_engines/individual/PubMedEngine.py +329 -0
- scitex/scholar/metadata_engines/individual/SemanticScholarEngine.py +438 -0
- scitex/scholar/metadata_engines/individual/URLDOIEngine.py +410 -0
- scitex/scholar/metadata_engines/individual/_BaseDOIEngine.py +487 -0
- scitex/scholar/metadata_engines/individual/__init__.py +7 -0
- scitex/scholar/metadata_engines/utils/_PubMedConverter.py +469 -0
- scitex/scholar/metadata_engines/utils/_URLDOIExtractor.py +283 -0
- scitex/scholar/metadata_engines/utils/__init__.py +30 -0
- scitex/scholar/metadata_engines/utils/_metadata2bibtex.py +103 -0
- scitex/scholar/metadata_engines/utils/_standardize_metadata.py +376 -0
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +579 -0
- scitex/scholar/pdf_download/__init__.py +5 -0
- scitex/scholar/pdf_download/strategies/__init__.py +38 -0
- scitex/scholar/pdf_download/strategies/chrome_pdf_viewer.py +376 -0
- scitex/scholar/pdf_download/strategies/direct_download.py +131 -0
- scitex/scholar/pdf_download/strategies/manual_download_fallback.py +167 -0
- scitex/scholar/pdf_download/strategies/manual_download_utils.py +996 -0
- scitex/scholar/pdf_download/strategies/response_body.py +207 -0
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +364 -0
- scitex/scholar/pipelines/ScholarPipelineParallel.py +478 -0
- scitex/scholar/pipelines/ScholarPipelineSingle.py +767 -0
- scitex/scholar/pipelines/__init__.py +49 -0
- scitex/scholar/storage/BibTeXHandler.py +1018 -0
- scitex/scholar/storage/PaperIO.py +468 -0
- scitex/scholar/storage/ScholarLibrary.py +182 -0
- scitex/scholar/storage/_DeduplicationManager.py +548 -0
- scitex/scholar/storage/_LibraryCacheManager.py +724 -0
- scitex/scholar/storage/_LibraryManager.py +1835 -0
- scitex/scholar/storage/__init__.py +28 -0
- scitex/scholar/url_finder/ScholarURLFinder.py +379 -0
- scitex/scholar/url_finder/__init__.py +7 -0
- scitex/scholar/url_finder/strategies/__init__.py +33 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_direct_links.py +261 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_dropdown.py +67 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_href.py +204 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_navigation.py +256 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_publisher_patterns.py +165 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_zotero_translators.py +163 -0
- scitex/scholar/url_finder/strategies/find_supplementary_urls_by_href.py +70 -0
- scitex/scholar/utils/__init__.py +22 -0
- scitex/scholar/utils/bibtex/__init__.py +9 -0
- scitex/scholar/utils/bibtex/_parse_bibtex.py +71 -0
- scitex/scholar/utils/cleanup/__init__.py +8 -0
- scitex/scholar/utils/cleanup/_cleanup_scholar_processes.py +96 -0
- scitex/scholar/utils/cleanup/cleanup_old_extractions.py +117 -0
- scitex/scholar/utils/text/_TextNormalizer.py +407 -0
- scitex/scholar/utils/text/__init__.py +9 -0
- scitex/scholar/zotero/__init__.py +38 -0
- scitex/session/__init__.py +51 -0
- scitex/session/_lifecycle.py +736 -0
- scitex/session/_manager.py +102 -0
- scitex/session/template.py +122 -0
- scitex/stats/__init__.py +30 -26
- scitex/stats/correct/__init__.py +21 -0
- scitex/stats/correct/_correct_bonferroni.py +551 -0
- scitex/stats/correct/_correct_fdr.py +634 -0
- scitex/stats/correct/_correct_holm.py +548 -0
- scitex/stats/correct/_correct_sidak.py +499 -0
- scitex/stats/descriptive/__init__.py +85 -0
- scitex/stats/descriptive/_circular.py +540 -0
- scitex/stats/descriptive/_describe.py +219 -0
- scitex/stats/descriptive/_nan.py +518 -0
- scitex/stats/descriptive/_real.py +189 -0
- scitex/stats/effect_sizes/__init__.py +41 -0
- scitex/stats/effect_sizes/_cliffs_delta.py +325 -0
- scitex/stats/effect_sizes/_cohens_d.py +342 -0
- scitex/stats/effect_sizes/_epsilon_squared.py +315 -0
- scitex/stats/effect_sizes/_eta_squared.py +302 -0
- scitex/stats/effect_sizes/_prob_superiority.py +296 -0
- scitex/stats/posthoc/__init__.py +19 -0
- scitex/stats/posthoc/_dunnett.py +463 -0
- scitex/stats/posthoc/_games_howell.py +383 -0
- scitex/stats/posthoc/_tukey_hsd.py +367 -0
- scitex/stats/power/__init__.py +19 -0
- scitex/stats/power/_power.py +433 -0
- scitex/stats/template.py +119 -0
- scitex/stats/utils/__init__.py +62 -0
- scitex/stats/utils/_effect_size.py +985 -0
- scitex/stats/utils/_formatters.py +270 -0
- scitex/stats/utils/_normalizers.py +927 -0
- scitex/stats/utils/_power.py +433 -0
- scitex/stats_v01/_EffectSizeCalculator.py +488 -0
- scitex/stats_v01/_StatisticalValidator.py +411 -0
- scitex/stats_v01/__init__.py +60 -0
- scitex/stats_v01/_additional_tests.py +415 -0
- scitex/{stats → stats_v01}/_p2stars.py +19 -5
- scitex/stats_v01/_two_sample_tests.py +141 -0
- scitex/stats_v01/desc/__init__.py +83 -0
- scitex/stats_v01/desc/_circular.py +540 -0
- scitex/stats_v01/desc/_describe.py +219 -0
- scitex/stats_v01/desc/_nan.py +518 -0
- scitex/{stats/desc/_nan.py → stats_v01/desc/_nan_v01-20250920_145731.py} +23 -12
- scitex/stats_v01/desc/_real.py +189 -0
- scitex/stats_v01/tests/__corr_test_optimized.py +221 -0
- scitex/stats_v01/tests/_corr_test_optimized.py +179 -0
- scitex/str/__init__.py +1 -3
- scitex/str/_clean_path.py +6 -2
- scitex/str/_latex_fallback.py +267 -160
- scitex/str/_parse.py +44 -36
- scitex/str/_printc.py +1 -3
- scitex/template/__init__.py +87 -0
- scitex/template/_create_project.py +267 -0
- scitex/template/create_pip_project.py +80 -0
- scitex/template/create_research.py +80 -0
- scitex/template/create_singularity.py +80 -0
- scitex/units.py +291 -0
- scitex/utils/_compress_hdf5.py +14 -3
- scitex/utils/_email.py +21 -2
- scitex/utils/_grid.py +6 -4
- scitex/utils/_notify.py +13 -10
- scitex/utils/_verify_scitex_format.py +589 -0
- scitex/utils/_verify_scitex_format_v01.py +370 -0
- scitex/utils/template.py +122 -0
- scitex/web/_search_pubmed.py +62 -16
- scitex-2.1.0.dist-info/LICENSE +21 -0
- scitex-2.1.0.dist-info/METADATA +677 -0
- scitex-2.1.0.dist-info/RECORD +919 -0
- {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/WHEEL +1 -1
- scitex-2.1.0.dist-info/entry_points.txt +3 -0
- scitex/ai/__Classifiers.py +0 -101
- scitex/ai/classification/classification_reporter.py +0 -1137
- scitex/ai/classification/classifiers.py +0 -101
- scitex/ai/classification_reporter.py +0 -1161
- scitex/ai/genai/__init__.py +0 -277
- scitex/ai/genai/anthropic_provider.py +0 -320
- scitex/ai/genai/anthropic_refactored.py +0 -109
- scitex/ai/genai/auth_manager.py +0 -200
- scitex/ai/genai/base_provider.py +0 -291
- scitex/ai/genai/chat_history.py +0 -307
- scitex/ai/genai/cost_tracker.py +0 -276
- scitex/ai/genai/deepseek_provider.py +0 -251
- scitex/ai/genai/google_provider.py +0 -228
- scitex/ai/genai/groq_provider.py +0 -248
- scitex/ai/genai/image_processor.py +0 -250
- scitex/ai/genai/llama_provider.py +0 -214
- scitex/ai/genai/mock_provider.py +0 -127
- scitex/ai/genai/model_registry.py +0 -304
- scitex/ai/genai/openai_provider.py +0 -293
- scitex/ai/genai/perplexity_provider.py +0 -205
- scitex/ai/genai/provider_base.py +0 -302
- scitex/ai/genai/provider_factory.py +0 -370
- scitex/ai/genai/response_handler.py +0 -235
- scitex/ai/layer/_Pass.py +0 -21
- scitex/ai/layer/__init__.py +0 -10
- scitex/ai/layer/_switch.py +0 -8
- scitex/ai/metrics/_bACC.py +0 -51
- scitex/ai/plt/_learning_curve.py +0 -194
- scitex/ai/plt/_optuna_study.py +0 -111
- scitex/ai/plt/aucs/__init__.py +0 -2
- scitex/ai/plt/aucs/example.py +0 -60
- scitex/ai/plt/aucs/pre_rec_auc.py +0 -223
- scitex/ai/plt/aucs/roc_auc.py +0 -246
- scitex/ai/sampling/undersample.py +0 -29
- scitex/db/_SQLite3.py +0 -2136
- scitex/db/_SQLite3Mixins/_BlobMixin.py +0 -229
- scitex/gen/_close.py +0 -222
- scitex/gen/_start.py +0 -451
- scitex/general/__init__.py +0 -5
- scitex/io/_load_modules/_db.py +0 -24
- scitex/life/__init__.py +0 -10
- scitex/life/_monitor_rain.py +0 -49
- scitex/reproduce/_fix_seeds.py +0 -45
- scitex/res/__init__.py +0 -5
- scitex/scholar/_local_search.py +0 -454
- scitex/scholar/_paper.py +0 -244
- scitex/scholar/_pdf_downloader.py +0 -325
- scitex/scholar/_search.py +0 -393
- scitex/scholar/_vector_search.py +0 -370
- scitex/scholar/_web_sources.py +0 -457
- scitex/stats/desc/__init__.py +0 -40
- scitex-2.0.0.dist-info/METADATA +0 -307
- scitex-2.0.0.dist-info/RECORD +0 -572
- scitex-2.0.0.dist-info/licenses/LICENSE +0 -7
- /scitex/ai/{act → activation}/__init__.py +0 -0
- /scitex/ai/{act → activation}/_define.py +0 -0
- /scitex/ai/{early_stopping.py → training/_EarlyStopping.py} +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ImportExportMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_IndexMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_RowMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TableMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/__init__.py +0 -0
- /scitex/{stats → stats_v01}/_calc_partial_corr.py +0 -0
- /scitex/{stats → stats_v01}/_corr_test_multi.py +0 -0
- /scitex/{stats → stats_v01}/_corr_test_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_describe_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_multiple_corrections.py +0 -0
- /scitex/{stats → stats_v01}/_nan_stats.py +0 -0
- /scitex/{stats → stats_v01}/_p2stars_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_statistical_tests.py +0 -0
- /scitex/{stats/desc/_describe.py → stats_v01/desc/_describe_v01-20250920_145731.py} +0 -0
- /scitex/{stats/desc/_real.py → stats_v01/desc/_real_v01-20250920_145731.py} +0 -0
- /scitex/{stats → stats_v01}/multiple/__init__.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_bonferroni_correction.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_fdr_correction.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_multicompair.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test_multi.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test_single.py +0 -0
- /scitex/{stats → stats_v01}/tests/__init__.py +0 -0
- /scitex/{stats → stats_v01}/tests/_brunner_munzel_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/_nocorrelation_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/_smirnov_grubbs.py +0 -0
- {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/top_level.txt +0 -0
scitex/ai/genai/__init__.py
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Time-stamp: "2024-11-25 12:00:00"
|
|
4
|
-
# Author: Yusuke Watanabe (ywatanabe@alumni.u-tokyo.ac.jp)
|
|
5
|
-
# scitex/src/scitex/ai/genai/__init__.py
|
|
6
|
-
|
|
7
|
-
"""
|
|
8
|
-
GenAI module for unified access to multiple AI providers.
|
|
9
|
-
|
|
10
|
-
This module provides a consistent interface for interacting with various
|
|
11
|
-
AI providers (OpenAI, Anthropic, Google, etc.) with built-in cost tracking,
|
|
12
|
-
chat history management, and error handling.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
from typing import List, Dict, Any, Optional, Union
|
|
16
|
-
import logging
|
|
17
|
-
|
|
18
|
-
from .provider_factory import Provider, create_provider, GenAI as GenAIFactory
|
|
19
|
-
from .auth_manager import AuthManager
|
|
20
|
-
from .chat_history import ChatHistory
|
|
21
|
-
from .cost_tracker import CostTracker
|
|
22
|
-
from .response_handler import ResponseHandler
|
|
23
|
-
from .base_provider import BaseProvider, CompletionResponse
|
|
24
|
-
|
|
25
|
-
# Import legacy providers for backward compatibility
|
|
26
|
-
from .anthropic import Anthropic
|
|
27
|
-
from .openai import OpenAI
|
|
28
|
-
from .google import Google
|
|
29
|
-
from .groq import Groq
|
|
30
|
-
from .deepseek import DeepSeek
|
|
31
|
-
from .llama import Llama
|
|
32
|
-
from .perplexity import Perplexity
|
|
33
|
-
from .genai_factory import genai_factory
|
|
34
|
-
|
|
35
|
-
logger = logging.getLogger(__name__)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class GenAI:
|
|
39
|
-
"""
|
|
40
|
-
Unified interface for multiple AI providers.
|
|
41
|
-
|
|
42
|
-
This class provides a consistent API for interacting with various AI providers
|
|
43
|
-
while handling authentication, chat history, cost tracking, and response processing.
|
|
44
|
-
|
|
45
|
-
Args:
|
|
46
|
-
provider: Provider name (e.g., 'openai', 'anthropic', 'google')
|
|
47
|
-
api_key: Optional API key (if not provided, will use environment variable)
|
|
48
|
-
model: Model name (if not provided, will use provider's default)
|
|
49
|
-
system_prompt: Optional system prompt to prepend to conversations
|
|
50
|
-
**kwargs: Additional provider-specific configuration
|
|
51
|
-
|
|
52
|
-
Example:
|
|
53
|
-
>>> from scitex.ai.genai import GenAI
|
|
54
|
-
>>>
|
|
55
|
-
>>> # Basic usage
|
|
56
|
-
>>> ai = GenAI(provider="openai")
|
|
57
|
-
>>> response = ai.complete("What is the capital of France?")
|
|
58
|
-
>>> print(response)
|
|
59
|
-
"The capital of France is Paris."
|
|
60
|
-
>>>
|
|
61
|
-
>>> # With specific model and system prompt
|
|
62
|
-
>>> ai = GenAI(
|
|
63
|
-
... provider="anthropic",
|
|
64
|
-
... model="claude-3-opus-20240229",
|
|
65
|
-
... system_prompt="You are a helpful geography expert."
|
|
66
|
-
... )
|
|
67
|
-
>>> response = ai.complete("Tell me about Paris.")
|
|
68
|
-
>>>
|
|
69
|
-
>>> # Check costs
|
|
70
|
-
>>> print(ai.get_cost_summary())
|
|
71
|
-
"Total cost: $0.015 | Requests: 2 | Tokens: 1,234"
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
def __init__(
|
|
75
|
-
self,
|
|
76
|
-
provider: Union[str, Provider],
|
|
77
|
-
api_key: Optional[str] = None,
|
|
78
|
-
model: Optional[str] = None,
|
|
79
|
-
system_prompt: Optional[str] = None,
|
|
80
|
-
**kwargs
|
|
81
|
-
):
|
|
82
|
-
"""Initialize GenAI with specified provider."""
|
|
83
|
-
# Store provider name
|
|
84
|
-
if isinstance(provider, str):
|
|
85
|
-
self.provider_name = provider.lower()
|
|
86
|
-
else:
|
|
87
|
-
self.provider_name = provider.value
|
|
88
|
-
|
|
89
|
-
# Initialize components
|
|
90
|
-
self.auth_manager = AuthManager(api_key, self.provider_name)
|
|
91
|
-
self.chat_history = ChatHistory(n_keep=-1) # Keep all messages by default
|
|
92
|
-
self.response_handler = ResponseHandler()
|
|
93
|
-
|
|
94
|
-
# Get API key from auth manager if not provided
|
|
95
|
-
if api_key is None:
|
|
96
|
-
api_key = self.auth_manager.api_key
|
|
97
|
-
|
|
98
|
-
# Create provider instance
|
|
99
|
-
self.provider = create_provider(
|
|
100
|
-
provider=self.provider_name, api_key=api_key, model=model, **kwargs
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
# Initialize cost tracker with provider and model
|
|
104
|
-
# Note: provider instance may have a model attribute set during initialization
|
|
105
|
-
actual_model = getattr(self.provider, "model", None) or model or "unknown"
|
|
106
|
-
self.cost_tracker = CostTracker(provider=self.provider_name, model=actual_model)
|
|
107
|
-
|
|
108
|
-
# Add system prompt if provided
|
|
109
|
-
if system_prompt:
|
|
110
|
-
self.chat_history.add_message("system", system_prompt)
|
|
111
|
-
|
|
112
|
-
logger.info(f"Initialized GenAI with provider: {self.provider_name}")
|
|
113
|
-
|
|
114
|
-
def complete(
|
|
115
|
-
self, prompt: str, images: Optional[List[str]] = None, **kwargs
|
|
116
|
-
) -> str:
|
|
117
|
-
"""
|
|
118
|
-
Generate a completion for the given prompt.
|
|
119
|
-
|
|
120
|
-
Args:
|
|
121
|
-
prompt: The input prompt
|
|
122
|
-
images: Optional list of image URLs or base64 strings
|
|
123
|
-
**kwargs: Additional provider-specific parameters
|
|
124
|
-
|
|
125
|
-
Returns:
|
|
126
|
-
The generated response text
|
|
127
|
-
|
|
128
|
-
Raises:
|
|
129
|
-
ValueError: If the provider doesn't support images but images are provided
|
|
130
|
-
Exception: Provider-specific exceptions
|
|
131
|
-
"""
|
|
132
|
-
# Add user message to history
|
|
133
|
-
self.chat_history.add_message("user", prompt, images)
|
|
134
|
-
|
|
135
|
-
# Get messages for API call
|
|
136
|
-
messages = [msg.to_dict() for msg in self.chat_history.get_messages()]
|
|
137
|
-
|
|
138
|
-
# Call provider
|
|
139
|
-
try:
|
|
140
|
-
response: CompletionResponse = self.provider.complete(
|
|
141
|
-
messages=messages, **kwargs
|
|
142
|
-
)
|
|
143
|
-
except Exception as e:
|
|
144
|
-
logger.error(f"Provider {self.provider_name} failed: {str(e)}")
|
|
145
|
-
raise
|
|
146
|
-
|
|
147
|
-
# Process response - CompletionResponse has a content attribute
|
|
148
|
-
content = response.content
|
|
149
|
-
|
|
150
|
-
# Add assistant message to history
|
|
151
|
-
self.chat_history.add_message("assistant", content)
|
|
152
|
-
|
|
153
|
-
# Track costs - CompletionResponse has input_tokens and output_tokens
|
|
154
|
-
self.cost_tracker.update(
|
|
155
|
-
input_tokens=response.input_tokens, output_tokens=response.output_tokens
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
return content
|
|
159
|
-
|
|
160
|
-
def complete_async(self, prompt: str, images: Optional[List[str]] = None, **kwargs):
|
|
161
|
-
"""
|
|
162
|
-
Async version of complete method.
|
|
163
|
-
|
|
164
|
-
Args:
|
|
165
|
-
prompt: The input prompt
|
|
166
|
-
images: Optional list of image URLs or base64 strings
|
|
167
|
-
**kwargs: Additional provider-specific parameters
|
|
168
|
-
|
|
169
|
-
Returns:
|
|
170
|
-
Awaitable that resolves to the generated response text
|
|
171
|
-
"""
|
|
172
|
-
raise NotImplementedError("Async completion not yet implemented")
|
|
173
|
-
|
|
174
|
-
def stream(self, prompt: str, images: Optional[List[str]] = None, **kwargs):
|
|
175
|
-
"""
|
|
176
|
-
Stream completions for the given prompt.
|
|
177
|
-
|
|
178
|
-
Args:
|
|
179
|
-
prompt: The input prompt
|
|
180
|
-
images: Optional list of image URLs or base64 strings
|
|
181
|
-
**kwargs: Additional provider-specific parameters
|
|
182
|
-
|
|
183
|
-
Yields:
|
|
184
|
-
Chunks of the generated response
|
|
185
|
-
"""
|
|
186
|
-
raise NotImplementedError("Streaming not yet implemented")
|
|
187
|
-
|
|
188
|
-
def clear_history(self):
|
|
189
|
-
"""Clear the chat history."""
|
|
190
|
-
self.chat_history.clear()
|
|
191
|
-
logger.info("Chat history cleared")
|
|
192
|
-
|
|
193
|
-
def get_history(self) -> List[Dict[str, str]]:
|
|
194
|
-
"""Get the current chat history."""
|
|
195
|
-
return self.chat_history.messages
|
|
196
|
-
|
|
197
|
-
def get_cost_summary(self) -> str:
|
|
198
|
-
"""Get a summary of costs incurred."""
|
|
199
|
-
return self.cost_tracker.get_summary()
|
|
200
|
-
|
|
201
|
-
def get_detailed_costs(self) -> Dict[str, Any]:
|
|
202
|
-
"""Get detailed cost breakdown."""
|
|
203
|
-
return {
|
|
204
|
-
"total_cost": self.cost_tracker.total_cost,
|
|
205
|
-
"total_prompt_tokens": self.cost_tracker.total_prompt_tokens,
|
|
206
|
-
"total_completion_tokens": self.cost_tracker.total_completion_tokens,
|
|
207
|
-
"request_count": self.cost_tracker.request_count,
|
|
208
|
-
"cost_by_model": self.cost_tracker.cost_by_model,
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
def reset_costs(self):
|
|
212
|
-
"""Reset cost tracking."""
|
|
213
|
-
self.cost_tracker.reset()
|
|
214
|
-
logger.info("Cost tracking reset")
|
|
215
|
-
|
|
216
|
-
def __repr__(self) -> str:
|
|
217
|
-
"""String representation of GenAI instance."""
|
|
218
|
-
return (
|
|
219
|
-
f"GenAI(provider='{self.provider_name}', "
|
|
220
|
-
f"model='{self.provider.model}', "
|
|
221
|
-
f"requests={self.cost_tracker.request_count})"
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
# Convenience function for one-off completions
|
|
226
|
-
def complete(
|
|
227
|
-
prompt: str,
|
|
228
|
-
provider: Union[str, Provider] = "openai",
|
|
229
|
-
model: Optional[str] = None,
|
|
230
|
-
api_key: Optional[str] = None,
|
|
231
|
-
**kwargs
|
|
232
|
-
) -> str:
|
|
233
|
-
"""
|
|
234
|
-
Convenience function for one-off completions without managing state.
|
|
235
|
-
|
|
236
|
-
Args:
|
|
237
|
-
prompt: The input prompt
|
|
238
|
-
provider: Provider name or enum
|
|
239
|
-
model: Optional model name
|
|
240
|
-
api_key: Optional API key
|
|
241
|
-
**kwargs: Additional parameters
|
|
242
|
-
|
|
243
|
-
Returns:
|
|
244
|
-
The generated response text
|
|
245
|
-
|
|
246
|
-
Example:
|
|
247
|
-
>>> from scitex.ai.genai import complete
|
|
248
|
-
>>> response = complete("What is 2+2?", provider="anthropic")
|
|
249
|
-
>>> print(response)
|
|
250
|
-
"2 + 2 = 4"
|
|
251
|
-
"""
|
|
252
|
-
genai = GenAI(provider=provider, model=model, api_key=api_key)
|
|
253
|
-
return genai.complete(prompt, **kwargs)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
# Export public API
|
|
257
|
-
__all__ = [
|
|
258
|
-
# New API
|
|
259
|
-
"GenAI",
|
|
260
|
-
"GenAIFactory",
|
|
261
|
-
"complete",
|
|
262
|
-
"Provider",
|
|
263
|
-
"create_provider",
|
|
264
|
-
"AuthManager",
|
|
265
|
-
"ChatHistory",
|
|
266
|
-
"CostTracker",
|
|
267
|
-
"ResponseHandler",
|
|
268
|
-
# Legacy API for backward compatibility
|
|
269
|
-
"genai_factory",
|
|
270
|
-
"Anthropic",
|
|
271
|
-
"OpenAI",
|
|
272
|
-
"Google",
|
|
273
|
-
"Groq",
|
|
274
|
-
"DeepSeek",
|
|
275
|
-
"Llama",
|
|
276
|
-
"Perplexity",
|
|
277
|
-
]
|
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Time-stamp: "2024-11-25 12:00:00"
|
|
4
|
-
# Author: Yusuke Watanabe (ywatanabe@alumni.u-tokyo.ac.jp)
|
|
5
|
-
# scitex/src/scitex/ai/genai/anthropic_provider.py
|
|
6
|
-
|
|
7
|
-
"""
|
|
8
|
-
Anthropic provider implementation for GenAI.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from typing import List, Dict, Any, Optional, Generator
|
|
12
|
-
import logging
|
|
13
|
-
|
|
14
|
-
from .base_provider import BaseProvider, CompletionResponse
|
|
15
|
-
|
|
16
|
-
logger = logging.getLogger(__name__)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class AnthropicProvider(BaseProvider):
|
|
20
|
-
"""
|
|
21
|
-
Anthropic provider implementation.
|
|
22
|
-
|
|
23
|
-
Supports Claude 3 models (Opus, Sonnet, Haiku).
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
SUPPORTED_MODELS = [
|
|
27
|
-
"claude-3-opus-20240229",
|
|
28
|
-
"claude-3-sonnet-20240229",
|
|
29
|
-
"claude-3-haiku-20240307",
|
|
30
|
-
"claude-2.1",
|
|
31
|
-
"claude-2.0",
|
|
32
|
-
"claude-instant-1.2",
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
DEFAULT_MODEL = "claude-3-sonnet-20240229"
|
|
36
|
-
|
|
37
|
-
def __init__(self, config):
|
|
38
|
-
"""Initialize Anthropic provider."""
|
|
39
|
-
self.config = config
|
|
40
|
-
self.api_key = config.api_key
|
|
41
|
-
self.model = config.model or self.DEFAULT_MODEL
|
|
42
|
-
self.kwargs = config.kwargs or {}
|
|
43
|
-
|
|
44
|
-
# Import Anthropic client
|
|
45
|
-
try:
|
|
46
|
-
from anthropic import Anthropic as AnthropicClient
|
|
47
|
-
|
|
48
|
-
self.client = AnthropicClient(api_key=api_key)
|
|
49
|
-
except ImportError:
|
|
50
|
-
raise ImportError(
|
|
51
|
-
"Anthropic package not installed. Install with: pip install anthropic"
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
def complete(self, messages: List[Dict[str, Any]], **kwargs) -> CompletionResponse:
|
|
55
|
-
"""
|
|
56
|
-
Generate completion using Anthropic API.
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
messages: List of message dictionaries
|
|
60
|
-
**kwargs: Additional parameters (max_tokens, temperature, etc.)
|
|
61
|
-
|
|
62
|
-
Returns:
|
|
63
|
-
CompletionResponse with generated text and usage info
|
|
64
|
-
"""
|
|
65
|
-
# Validate messages
|
|
66
|
-
if not self.validate_messages(messages):
|
|
67
|
-
raise ValueError("Invalid message format")
|
|
68
|
-
|
|
69
|
-
# Format messages for Anthropic
|
|
70
|
-
formatted_messages = self.format_messages(messages)
|
|
71
|
-
|
|
72
|
-
# Extract system message if present
|
|
73
|
-
system_message = None
|
|
74
|
-
user_messages = []
|
|
75
|
-
|
|
76
|
-
for msg in formatted_messages:
|
|
77
|
-
if msg["role"] == "system":
|
|
78
|
-
system_message = msg["content"]
|
|
79
|
-
else:
|
|
80
|
-
user_messages.append(msg)
|
|
81
|
-
|
|
82
|
-
# Prepare API parameters
|
|
83
|
-
api_params = {
|
|
84
|
-
"model": self.model,
|
|
85
|
-
"messages": user_messages,
|
|
86
|
-
"max_tokens": kwargs.get("max_tokens", 4096),
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
# Add system message if present
|
|
90
|
-
if system_message:
|
|
91
|
-
api_params["system"] = system_message
|
|
92
|
-
|
|
93
|
-
# Add optional parameters
|
|
94
|
-
for param in ["temperature", "top_p", "top_k", "stop_sequences"]:
|
|
95
|
-
if param in kwargs:
|
|
96
|
-
api_params[param] = kwargs[param]
|
|
97
|
-
|
|
98
|
-
try:
|
|
99
|
-
# Make API call
|
|
100
|
-
response = self.client.messages.create(**api_params)
|
|
101
|
-
|
|
102
|
-
# Extract content
|
|
103
|
-
content = response.content[0].text if response.content else ""
|
|
104
|
-
|
|
105
|
-
# Extract usage
|
|
106
|
-
usage = {
|
|
107
|
-
"prompt_tokens": response.usage.input_tokens,
|
|
108
|
-
"completion_tokens": response.usage.output_tokens,
|
|
109
|
-
"total_tokens": response.usage.input_tokens
|
|
110
|
-
+ response.usage.output_tokens,
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return CompletionResponse(content=content, usage=usage)
|
|
114
|
-
|
|
115
|
-
except Exception as e:
|
|
116
|
-
logger.error(f"Anthropic API error: {str(e)}")
|
|
117
|
-
raise
|
|
118
|
-
|
|
119
|
-
def format_messages(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
120
|
-
"""
|
|
121
|
-
Format messages for Anthropic API.
|
|
122
|
-
|
|
123
|
-
Anthropic expects messages in the format::
|
|
124
|
-
|
|
125
|
-
[
|
|
126
|
-
{"role": "user", "content": "..."},
|
|
127
|
-
{"role": "assistant", "content": "..."}
|
|
128
|
-
]
|
|
129
|
-
|
|
130
|
-
System messages are passed separately.
|
|
131
|
-
|
|
132
|
-
For images, the content should be a list::
|
|
133
|
-
|
|
134
|
-
{
|
|
135
|
-
"role": "user",
|
|
136
|
-
"content": [
|
|
137
|
-
{"type": "text", "text": "What's in this image?"},
|
|
138
|
-
{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": "..."}}
|
|
139
|
-
]
|
|
140
|
-
}
|
|
141
|
-
"""
|
|
142
|
-
formatted_messages = []
|
|
143
|
-
|
|
144
|
-
for msg in messages:
|
|
145
|
-
role = msg["role"]
|
|
146
|
-
content = msg["content"]
|
|
147
|
-
images = msg.get("images", [])
|
|
148
|
-
|
|
149
|
-
if images and self.model.startswith("claude-3"):
|
|
150
|
-
# Format with images (only Claude 3 supports images)
|
|
151
|
-
content_parts = [{"type": "text", "text": content}]
|
|
152
|
-
|
|
153
|
-
for img in images:
|
|
154
|
-
if img.startswith("data:"):
|
|
155
|
-
# Extract base64 data
|
|
156
|
-
header, data = img.split(",", 1)
|
|
157
|
-
media_type = header.split(":")[1].split(";")[0]
|
|
158
|
-
|
|
159
|
-
content_parts.append(
|
|
160
|
-
{
|
|
161
|
-
"type": "image",
|
|
162
|
-
"source": {
|
|
163
|
-
"type": "base64",
|
|
164
|
-
"media_type": media_type,
|
|
165
|
-
"data": data,
|
|
166
|
-
},
|
|
167
|
-
}
|
|
168
|
-
)
|
|
169
|
-
else:
|
|
170
|
-
# URL images not directly supported, would need to download first
|
|
171
|
-
logger.warning("URL images not directly supported by Anthropic")
|
|
172
|
-
|
|
173
|
-
formatted_messages.append({"role": role, "content": content_parts})
|
|
174
|
-
else:
|
|
175
|
-
# Regular text message
|
|
176
|
-
formatted_messages.append({"role": role, "content": content})
|
|
177
|
-
|
|
178
|
-
return formatted_messages
|
|
179
|
-
|
|
180
|
-
def validate_messages(self, messages: List[Dict[str, Any]]) -> bool:
|
|
181
|
-
"""Validate message format."""
|
|
182
|
-
if not messages:
|
|
183
|
-
return False
|
|
184
|
-
|
|
185
|
-
for msg in messages:
|
|
186
|
-
if not isinstance(msg, dict):
|
|
187
|
-
return False
|
|
188
|
-
if "role" not in msg or "content" not in msg:
|
|
189
|
-
return False
|
|
190
|
-
if msg["role"] not in ["system", "user", "assistant"]:
|
|
191
|
-
return False
|
|
192
|
-
|
|
193
|
-
return True
|
|
194
|
-
|
|
195
|
-
def stream(
|
|
196
|
-
self, messages: List[Dict[str, Any]], **kwargs
|
|
197
|
-
) -> Generator[str, None, CompletionResponse]:
|
|
198
|
-
"""Generate a streaming completion.
|
|
199
|
-
|
|
200
|
-
Args:
|
|
201
|
-
messages: List of messages in standard format
|
|
202
|
-
**kwargs: Additional parameters
|
|
203
|
-
|
|
204
|
-
Yields:
|
|
205
|
-
Text chunks during streaming
|
|
206
|
-
|
|
207
|
-
Returns:
|
|
208
|
-
Final CompletionResponse when complete
|
|
209
|
-
"""
|
|
210
|
-
# Validate messages
|
|
211
|
-
if not self.validate_messages(messages):
|
|
212
|
-
raise ValueError("Invalid message format")
|
|
213
|
-
|
|
214
|
-
# Format messages for Anthropic
|
|
215
|
-
formatted_messages = self.format_messages(messages)
|
|
216
|
-
|
|
217
|
-
# Extract system message if present
|
|
218
|
-
system_message = None
|
|
219
|
-
user_messages = []
|
|
220
|
-
|
|
221
|
-
for msg in formatted_messages:
|
|
222
|
-
if msg["role"] == "system":
|
|
223
|
-
system_message = msg["content"]
|
|
224
|
-
else:
|
|
225
|
-
user_messages.append(msg)
|
|
226
|
-
|
|
227
|
-
# Prepare API parameters
|
|
228
|
-
api_params = {
|
|
229
|
-
"model": self.model,
|
|
230
|
-
"messages": user_messages,
|
|
231
|
-
"max_tokens": kwargs.get("max_tokens", 4096),
|
|
232
|
-
"stream": True,
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
# Add system message if present
|
|
236
|
-
if system_message:
|
|
237
|
-
api_params["system"] = system_message
|
|
238
|
-
|
|
239
|
-
# Add optional parameters
|
|
240
|
-
for param in ["temperature", "top_p", "top_k", "stop_sequences"]:
|
|
241
|
-
if param in kwargs:
|
|
242
|
-
api_params[param] = kwargs[param]
|
|
243
|
-
|
|
244
|
-
try:
|
|
245
|
-
# Make streaming API call
|
|
246
|
-
full_content = ""
|
|
247
|
-
prompt_tokens = 0
|
|
248
|
-
completion_tokens = 0
|
|
249
|
-
|
|
250
|
-
with self.client.messages.stream(**api_params) as stream:
|
|
251
|
-
for text in stream.text_stream:
|
|
252
|
-
full_content += text
|
|
253
|
-
yield text
|
|
254
|
-
|
|
255
|
-
# Get final message with usage info
|
|
256
|
-
message = stream.get_final_message()
|
|
257
|
-
if hasattr(message, "usage"):
|
|
258
|
-
prompt_tokens = message.usage.input_tokens
|
|
259
|
-
completion_tokens = message.usage.output_tokens
|
|
260
|
-
|
|
261
|
-
# Return final response
|
|
262
|
-
return CompletionResponse(
|
|
263
|
-
content=full_content,
|
|
264
|
-
usage={
|
|
265
|
-
"prompt_tokens": prompt_tokens,
|
|
266
|
-
"completion_tokens": completion_tokens,
|
|
267
|
-
"total_tokens": prompt_tokens + completion_tokens,
|
|
268
|
-
},
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
except Exception as e:
|
|
272
|
-
logger.error(f"Anthropic streaming error: {str(e)}")
|
|
273
|
-
raise
|
|
274
|
-
|
|
275
|
-
def count_tokens(self, text: str) -> int:
|
|
276
|
-
"""Count tokens in the given text.
|
|
277
|
-
|
|
278
|
-
Args:
|
|
279
|
-
text: Text to count tokens for
|
|
280
|
-
|
|
281
|
-
Returns:
|
|
282
|
-
Number of tokens
|
|
283
|
-
"""
|
|
284
|
-
try:
|
|
285
|
-
# Anthropic uses its own tokenizer
|
|
286
|
-
return self.client.count_tokens(text)
|
|
287
|
-
except Exception:
|
|
288
|
-
# Fallback: rough estimate (Claude tends to use fewer tokens than GPT)
|
|
289
|
-
return len(text.split()) * 3 // 4
|
|
290
|
-
|
|
291
|
-
@property
|
|
292
|
-
def supports_images(self) -> bool:
|
|
293
|
-
"""Check if this provider/model supports image inputs."""
|
|
294
|
-
# Only Claude 3 models support images
|
|
295
|
-
return self.model.startswith("claude-3")
|
|
296
|
-
|
|
297
|
-
@property
|
|
298
|
-
def supports_streaming(self) -> bool:
|
|
299
|
-
"""Check if this provider/model supports streaming."""
|
|
300
|
-
return True # All Anthropic models support streaming
|
|
301
|
-
|
|
302
|
-
@property
|
|
303
|
-
def max_context_length(self) -> int:
|
|
304
|
-
"""Get maximum context length for this model."""
|
|
305
|
-
context_lengths = {
|
|
306
|
-
"claude-3-opus-20240229": 200000,
|
|
307
|
-
"claude-3-sonnet-20240229": 200000,
|
|
308
|
-
"claude-3-haiku-20240307": 200000,
|
|
309
|
-
"claude-2.1": 200000,
|
|
310
|
-
"claude-2.0": 100000,
|
|
311
|
-
"claude-instant-1.2": 100000,
|
|
312
|
-
}
|
|
313
|
-
return context_lengths.get(self.model, 100000)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
# Auto-register when module is imported
|
|
317
|
-
from .base_provider import Provider
|
|
318
|
-
from .provider_factory import register_provider
|
|
319
|
-
|
|
320
|
-
register_provider(Provider.ANTHROPIC.value, AnthropicProvider)
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Refactored Anthropic provider using component architecture."""
|
|
3
|
-
|
|
4
|
-
from typing import List, Dict, Any, Generator
|
|
5
|
-
import anthropic
|
|
6
|
-
|
|
7
|
-
from .provider_base import ProviderBase, ProviderConfig
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class AnthropicProvider(ProviderBase):
|
|
11
|
-
"""Anthropic (Claude) provider implementation."""
|
|
12
|
-
|
|
13
|
-
def _init_client(self) -> anthropic.Anthropic:
|
|
14
|
-
"""Initialize Anthropic client."""
|
|
15
|
-
client_config = self.auth.get_client_config()
|
|
16
|
-
return anthropic.Anthropic(**client_config)
|
|
17
|
-
|
|
18
|
-
def _api_call(self, messages: List[Dict[str, Any]]) -> Any:
|
|
19
|
-
"""Make a non-streaming API call to Anthropic."""
|
|
20
|
-
# Extract system prompt if present
|
|
21
|
-
system_prompt = None
|
|
22
|
-
filtered_messages = []
|
|
23
|
-
|
|
24
|
-
for msg in messages:
|
|
25
|
-
if msg["role"] == "system":
|
|
26
|
-
system_prompt = msg["content"]
|
|
27
|
-
else:
|
|
28
|
-
filtered_messages.append(msg)
|
|
29
|
-
|
|
30
|
-
# Make API call
|
|
31
|
-
response = self.client.messages.create(
|
|
32
|
-
model=self.config.model,
|
|
33
|
-
messages=filtered_messages,
|
|
34
|
-
max_tokens=self.config.max_tokens,
|
|
35
|
-
temperature=self.config.temperature,
|
|
36
|
-
system=system_prompt or self.config.system_prompt,
|
|
37
|
-
stream=False,
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
return response
|
|
41
|
-
|
|
42
|
-
def _api_stream(self, messages: List[Dict[str, Any]]) -> Generator[Any, None, None]:
|
|
43
|
-
"""Make a streaming API call to Anthropic."""
|
|
44
|
-
# Extract system prompt
|
|
45
|
-
system_prompt = None
|
|
46
|
-
filtered_messages = []
|
|
47
|
-
|
|
48
|
-
for msg in messages:
|
|
49
|
-
if msg["role"] == "system":
|
|
50
|
-
system_prompt = msg["content"]
|
|
51
|
-
else:
|
|
52
|
-
filtered_messages.append(msg)
|
|
53
|
-
|
|
54
|
-
# Make streaming API call
|
|
55
|
-
stream = self.client.messages.create(
|
|
56
|
-
model=self.config.model,
|
|
57
|
-
messages=filtered_messages,
|
|
58
|
-
max_tokens=self.config.max_tokens,
|
|
59
|
-
temperature=self.config.temperature,
|
|
60
|
-
system=system_prompt or self.config.system_prompt,
|
|
61
|
-
stream=True,
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
for chunk in stream:
|
|
65
|
-
yield chunk
|
|
66
|
-
|
|
67
|
-
def _extract_token_counts(self, response: Any) -> tuple[int, int]:
|
|
68
|
-
"""Extract token counts from Anthropic response."""
|
|
69
|
-
input_tokens = getattr(response.usage, "input_tokens", 0)
|
|
70
|
-
output_tokens = getattr(response.usage, "output_tokens", 0)
|
|
71
|
-
return input_tokens, output_tokens
|
|
72
|
-
|
|
73
|
-
def count_tokens(self, text: str) -> int:
|
|
74
|
-
"""Count tokens using Anthropic's tokenizer."""
|
|
75
|
-
# Anthropic doesn't provide a public tokenizer
|
|
76
|
-
# Use approximation for now
|
|
77
|
-
# Claude's tokenization is roughly 1 token per 3.5 characters
|
|
78
|
-
return len(text) // 3
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
# Example usage:
|
|
82
|
-
if __name__ == "__main__":
|
|
83
|
-
# Create configuration
|
|
84
|
-
config = ProviderConfig(
|
|
85
|
-
provider="anthropic",
|
|
86
|
-
model="claude-3-opus-20240229",
|
|
87
|
-
system_prompt="You are a helpful assistant.",
|
|
88
|
-
temperature=0.7,
|
|
89
|
-
max_tokens=1024,
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
# Create provider instance
|
|
93
|
-
claude = AnthropicProvider(config)
|
|
94
|
-
|
|
95
|
-
# Use it
|
|
96
|
-
messages = [{"role": "user", "content": "Hello, how are you?"}]
|
|
97
|
-
|
|
98
|
-
# Non-streaming
|
|
99
|
-
response = claude.complete(messages)
|
|
100
|
-
print(response.content)
|
|
101
|
-
print(f"Tokens: {response.input_tokens} in, {response.output_tokens} out")
|
|
102
|
-
|
|
103
|
-
# Streaming
|
|
104
|
-
print("\nStreaming response:")
|
|
105
|
-
for chunk in claude.stream(messages):
|
|
106
|
-
print(chunk, end="", flush=True)
|
|
107
|
-
|
|
108
|
-
# Get cost summary
|
|
109
|
-
print("\n\n" + claude.get_cost_summary())
|