besser-agentic-framework 4.5.0__tar.gz → 4.5.2__tar.gz
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.
- {besser_agentic_framework-4.5.0/besser_agentic_framework.egg-info → besser_agentic_framework-4.5.2}/PKG-INFO +5 -1
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/state.py +22 -2
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/__init__.py +110 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_anthropic.py +270 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_deepseek.py +17 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_google.py +21 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_groq.py +18 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_meta.py +18 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_mistral.py +18 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_openai_api.py +34 -0
- besser_agentic_framework-4.5.0/baf/nlp/llm/llm_openai_api.py → besser_agentic_framework-4.5.2/baf/nlp/llm/llm_openai_compatible.py +58 -33
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_openrouter.py +20 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_qwen.py +18 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_together.py +19 -0
- besser_agentic_framework-4.5.2/baf/nlp/llm/llm_xai.py +17 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/rag/rag.py +107 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/test_extras.py +11 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/test_llms.py +6 -0
- besser_agentic_framework-4.5.2/baf/test/examples/hybrid_rag_agent.py +126 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2/besser_agentic_framework.egg-info}/PKG-INFO +5 -1
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/besser_agentic_framework.egg-info/SOURCES.txt +12 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/besser_agentic_framework.egg-info/requires.txt +4 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/requirements/requirements-extras.txt +1 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/requirements/requirements-llms.txt +1 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/setup.cfg +1 -1
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/LICENSE +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/MANIFEST.in +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/README.md +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/entity/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/entity/entity.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/entity/entity_entry.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/file.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/gui/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/gui/agent_gui.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/gui/gui_deserializer.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/gui/gui_llm.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/gui/gui_schema.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/gui/gui_serializer.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/intent/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/intent/intent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/intent/intent_parameter.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/message.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/processors/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/processors/audio_language_detection_processor.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/processors/language_detection_processor.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/processors/processor.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/processors/user_adaptation_processor.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/property.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/session.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/transition/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/transition/condition.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/transition/event.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/transition/transition.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/core/transition/transition_builder.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/db_handler.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_db.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/db_connection.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/flow_graph.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/home.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/intent_details.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/monitoring_ui.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/sidebar.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/table_overview.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/db/monitoring_ui/utils.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/exceptions/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/exceptions/exceptions.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/exceptions/logger.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/coroutine/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/coroutine/async_helpers.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/entity/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/entity/base_entities.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/intent/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/intent/intent_library.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/state/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/state/reasoning_state_library.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/state/state_library.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/tool/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/tool/task_tools.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/tool/workspace_tools.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/transition/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/transition/condition_functions.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/transition/conditions.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/transition/events/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/transition/events/base_events.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/transition/events/github_webhooks_events.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/library/transition/events/gitlab_webhooks_events.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/intent_classifier/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/intent_classifier/intent_classifier.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/intent_classifier/intent_classifier_configuration.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/intent_classifier/intent_classifier_prediction.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/intent_classifier/llm_intent_classifier.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/intent_classifier/simple_intent_classifier_pytorch.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/intent_classifier/simple_intent_classifier_tensorflow.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/llm/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/llm/llm.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/llm/llm_huggingface.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/llm/llm_huggingface_api.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/llm/llm_ollama.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/llm/llm_replicate_api.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/base/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/base/any.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/base/datetime.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/base/number.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/matched_parameter.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/ner.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/ner_prediction.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/ner/simple_ner.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/nlp_engine.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/preprocessing/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/preprocessing/pipelines.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/preprocessing/text_preprocessing.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/rag/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/speech2text/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/speech2text/api_speech2text.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/speech2text/hf_speech2text.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/speech2text/luxasr_speech2text.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/speech2text/openai_speech2text.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/speech2text/speech2text.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/text2speech/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/text2speech/hf_text2speech.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/text2speech/openai_text2speech.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/text2speech/piper_text2speech.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/text2speech/text2speech.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/nlp/utils.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/a2a_platform.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/agent_card.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/agent_registry.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/client.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/error_handler.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/message_router.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/server.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/a2a/task_protocol.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/github/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/github/github_actions.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/github/github_objects.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/github/github_platform.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/gitlab/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/gitlab/gitlab_actions.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/gitlab/gitlab_objects.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/gitlab/gitlab_platform.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/payload.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/platform.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/telegram/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/telegram/telegram_platform.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/audio_queue.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/chat.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/chat_interface_style.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/initialization.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/login.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/message_input.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/profile_selector.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/reasoning.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/session_management.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/sidebar.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/streamlit_ui.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/user_db.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/vars.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/streamlit_ui/websocket_callbacks.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/platforms/websocket/websocket_platform.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/reasoning/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/reasoning/skill.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/reasoning/tool.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/reasoning/workspace.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/conftest.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_intent_entity.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_message.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_processor.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_property.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_session.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_state.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_core_transition.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_library_events.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_nlp_configurations.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_nlp_engine.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_nlp_preprocessing.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_platforms.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/components/test_workflows.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/conftest.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/test_core.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/test_docs.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/test_framework.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/test_tensorflow.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/dependencies/test_torch.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/a2a_multiagent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/api_speech2text_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/github_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/gitlab_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/greetings_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/llm_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/multiagent/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/multiagent/coder_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/multiagent/main_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/multiagent/reviewer_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/rag_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/reasoning_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/speech2speech_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/speech2text_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/stargazer_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/telegram_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/text2speech_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/weather_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/test/examples/web_crawl_agent.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/utils/__init__.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/baf/utils/web_crawl.py +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/besser_agentic_framework.egg-info/dependency_links.txt +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/besser_agentic_framework.egg-info/top_level.txt +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/pyproject.toml +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/requirements/requirements-core.txt +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/requirements/requirements-docs.txt +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/requirements/requirements-tensorflow.txt +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/requirements/requirements-torch.txt +0 -0
- {besser_agentic_framework-4.5.0 → besser_agentic_framework-4.5.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: besser-agentic-framework
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.2
|
|
4
4
|
Summary: BESSER Agentic Framework (BAF)
|
|
5
5
|
Author: Luxembourg Institute of Science and Technology
|
|
6
6
|
License: MIT
|
|
@@ -53,10 +53,12 @@ Requires-Dist: langchain-community==0.3.10; python_version >= "3.13" and extra =
|
|
|
53
53
|
Requires-Dist: pypdf==4.3.1; extra == "extras"
|
|
54
54
|
Requires-Dist: python-docx==1.2.0; extra == "extras"
|
|
55
55
|
Requires-Dist: tiktoken==0.9.0; extra == "extras"
|
|
56
|
+
Requires-Dist: rank_bm25==0.2.2; extra == "extras"
|
|
56
57
|
Provides-Extra: llms
|
|
57
58
|
Requires-Dist: openai==1.93.0; extra == "llms"
|
|
58
59
|
Requires-Dist: replicate==0.23.1; extra == "llms"
|
|
59
60
|
Requires-Dist: transformers==4.53.0; extra == "llms"
|
|
61
|
+
Requires-Dist: anthropic>=0.40.0; extra == "llms"
|
|
60
62
|
Provides-Extra: tensorflow
|
|
61
63
|
Requires-Dist: keras==3.12.0; extra == "tensorflow"
|
|
62
64
|
Requires-Dist: tensorflow-cpu==2.20.0; extra == "tensorflow"
|
|
@@ -86,9 +88,11 @@ Requires-Dist: langchain-community==0.3.10; python_version >= "3.13" and extra =
|
|
|
86
88
|
Requires-Dist: pypdf==4.3.1; extra == "all"
|
|
87
89
|
Requires-Dist: python-docx==1.2.0; extra == "all"
|
|
88
90
|
Requires-Dist: tiktoken==0.9.0; extra == "all"
|
|
91
|
+
Requires-Dist: rank_bm25==0.2.2; extra == "all"
|
|
89
92
|
Requires-Dist: openai==1.93.0; extra == "all"
|
|
90
93
|
Requires-Dist: replicate==0.23.1; extra == "all"
|
|
91
94
|
Requires-Dist: transformers==4.53.0; extra == "all"
|
|
95
|
+
Requires-Dist: anthropic>=0.40.0; extra == "all"
|
|
92
96
|
Requires-Dist: keras==3.12.0; extra == "all"
|
|
93
97
|
Requires-Dist: tensorflow-cpu==2.20.0; extra == "all"
|
|
94
98
|
Requires-Dist: torch==2.6.0; extra == "all"
|
|
@@ -139,6 +139,24 @@ class State:
|
|
|
139
139
|
raise BodySignatureError(self._agent, self, body, body_template_signature, body_signature)
|
|
140
140
|
self._body = body
|
|
141
141
|
|
|
142
|
+
def body(self, func: Callable[[Session], None]) -> Callable[[Session], None]:
|
|
143
|
+
"""Decorator to set the state body.
|
|
144
|
+
|
|
145
|
+
Usage::
|
|
146
|
+
|
|
147
|
+
@state.body
|
|
148
|
+
def my_body(session: Session):
|
|
149
|
+
...
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
func (Callable[[Session], None]): the body function
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Callable[[Session], None]: the body function unchanged
|
|
156
|
+
"""
|
|
157
|
+
self.set_body(func)
|
|
158
|
+
return func
|
|
159
|
+
|
|
142
160
|
def set_fallback_body(self, body: Callable[[Session], None]):
|
|
143
161
|
"""Set the state fallback body.
|
|
144
162
|
|
|
@@ -337,8 +355,10 @@ class State:
|
|
|
337
355
|
if (isinstance(session.event, ReceiveTextEvent) and session.event.human) or (isinstance(session.event, ReceiveJSONEvent) and session.event.contains_message and session.event.human):
|
|
338
356
|
# There is a ReceiveTextEvent or ReceiveJSONEvent (with message) and we couldn't match any transition so far
|
|
339
357
|
run_fallback = True
|
|
340
|
-
if
|
|
341
|
-
#
|
|
358
|
+
if any(t.is_event() for t in self.transitions[i+1:]):
|
|
359
|
+
# Only preserve the event if there are more event-based transitions left to check.
|
|
360
|
+
# Condition-based transitions don't consume events, so preserving the event for them
|
|
361
|
+
# would cause it to remain in the queue after the fallback fires, creating an infinite loop.
|
|
342
362
|
fallback_deque.appendleft(session.event)
|
|
343
363
|
else:
|
|
344
364
|
fallback_deque.appendleft(session.event)
|
|
@@ -111,6 +111,116 @@ type: ``str``
|
|
|
111
111
|
default value: ``None``
|
|
112
112
|
"""
|
|
113
113
|
|
|
114
|
+
MISTRAL_API_KEY = Property('nlp.mistral.api_key', str, None)
|
|
115
|
+
"""
|
|
116
|
+
The Mistral AI API key, necessary to use a Mistral LLM.
|
|
117
|
+
|
|
118
|
+
name: ``nlp.mistral.api_key``
|
|
119
|
+
|
|
120
|
+
type: ``str``
|
|
121
|
+
|
|
122
|
+
default value: ``None``
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
DEEPSEEK_API_KEY = Property('nlp.deepseek.api_key', str, None)
|
|
126
|
+
"""
|
|
127
|
+
The DeepSeek API key, necessary to use a DeepSeek LLM.
|
|
128
|
+
|
|
129
|
+
name: ``nlp.deepseek.api_key``
|
|
130
|
+
|
|
131
|
+
type: ``str``
|
|
132
|
+
|
|
133
|
+
default value: ``None``
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
GOOGLE_API_KEY = Property('nlp.google.api_key', str, None)
|
|
137
|
+
"""
|
|
138
|
+
The Google AI (Gemini) API key, necessary to use a Google LLM.
|
|
139
|
+
|
|
140
|
+
name: ``nlp.google.api_key``
|
|
141
|
+
|
|
142
|
+
type: ``str``
|
|
143
|
+
|
|
144
|
+
default value: ``None``
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
META_API_KEY = Property('nlp.meta.api_key', str, None)
|
|
148
|
+
"""
|
|
149
|
+
The Meta AI API key, necessary to use a Meta Llama LLM via Meta's hosted API.
|
|
150
|
+
|
|
151
|
+
name: ``nlp.meta.api_key``
|
|
152
|
+
|
|
153
|
+
type: ``str``
|
|
154
|
+
|
|
155
|
+
default value: ``None``
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
ANTHROPIC_API_KEY = Property('nlp.anthropic.api_key', str, None)
|
|
159
|
+
"""
|
|
160
|
+
The Anthropic API key, necessary to use an Anthropic Claude LLM.
|
|
161
|
+
|
|
162
|
+
name: ``nlp.anthropic.api_key``
|
|
163
|
+
|
|
164
|
+
type: ``str``
|
|
165
|
+
|
|
166
|
+
default value: ``None``
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
QWEN_API_KEY = Property('nlp.qwen.api_key', str, None)
|
|
170
|
+
"""
|
|
171
|
+
The Alibaba DashScope API key, necessary to use a Qwen LLM.
|
|
172
|
+
|
|
173
|
+
name: ``nlp.qwen.api_key``
|
|
174
|
+
|
|
175
|
+
type: ``str``
|
|
176
|
+
|
|
177
|
+
default value: ``None``
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
XAI_API_KEY = Property('nlp.xai.api_key', str, None)
|
|
181
|
+
"""
|
|
182
|
+
The xAI API key, necessary to use an xAI Grok LLM.
|
|
183
|
+
|
|
184
|
+
name: ``nlp.xai.api_key``
|
|
185
|
+
|
|
186
|
+
type: ``str``
|
|
187
|
+
|
|
188
|
+
default value: ``None``
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
GROQ_API_KEY = Property('nlp.groq.api_key', str, None)
|
|
192
|
+
"""
|
|
193
|
+
The Groq API key, necessary to use a Groq-hosted LLM.
|
|
194
|
+
|
|
195
|
+
name: ``nlp.groq.api_key``
|
|
196
|
+
|
|
197
|
+
type: ``str``
|
|
198
|
+
|
|
199
|
+
default value: ``None``
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
TOGETHER_API_KEY = Property('nlp.together.api_key', str, None)
|
|
203
|
+
"""
|
|
204
|
+
The Together AI API key, necessary to use a Together AI-hosted LLM.
|
|
205
|
+
|
|
206
|
+
name: ``nlp.together.api_key``
|
|
207
|
+
|
|
208
|
+
type: ``str``
|
|
209
|
+
|
|
210
|
+
default value: ``None``
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
OPENROUTER_API_KEY = Property('nlp.openrouter.api_key', str, None)
|
|
214
|
+
"""
|
|
215
|
+
The OpenRouter API key, necessary to use an OpenRouter-proxied LLM.
|
|
216
|
+
|
|
217
|
+
name: ``nlp.openrouter.api_key``
|
|
218
|
+
|
|
219
|
+
type: ``str``
|
|
220
|
+
|
|
221
|
+
default value: ``None``
|
|
222
|
+
"""
|
|
223
|
+
|
|
114
224
|
OLLAMA_BASE_URL = Property('nlp.ollama.base_url', str, 'http://localhost:11434')
|
|
115
225
|
"""
|
|
116
226
|
The base URL for a locally hosted Ollama server.
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from baf import nlp
|
|
7
|
+
from baf.core.message import MessageType, Message
|
|
8
|
+
from baf.exceptions.logger import logger
|
|
9
|
+
from baf.nlp.intent_classifier.intent_classifier_prediction import IntentClassifierPrediction
|
|
10
|
+
from baf.nlp.llm.llm import LLM, LLMResponse, ToolCall
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from baf.core.agent import Agent
|
|
14
|
+
from baf.core.session import Session
|
|
15
|
+
from baf.nlp.intent_classifier.llm_intent_classifier import LLMIntentClassifier
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import anthropic as anthropic_sdk
|
|
19
|
+
except ImportError:
|
|
20
|
+
anthropic_sdk = None
|
|
21
|
+
logger.warning("anthropic dependencies in LLMAnthropic could not be imported. You can install them via "
|
|
22
|
+
"'pip install anthropic' or by adding it to requirements/requirements-llms.txt")
|
|
23
|
+
|
|
24
|
+
_DEFAULT_MAX_TOKENS = 4096
|
|
25
|
+
"""Default ``max_tokens`` used when the caller does not supply one.
|
|
26
|
+
|
|
27
|
+
The Anthropic Messages API requires ``max_tokens`` to be provided explicitly; this
|
|
28
|
+
constant is used as a safe default when it is absent from ``self.parameters``.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class LLMAnthropic(LLM):
|
|
33
|
+
"""LLM wrapper for Anthropic Claude models using the native ``anthropic`` SDK.
|
|
34
|
+
|
|
35
|
+
Anthropic's API differs enough from the OpenAI shape (system-prompt placement,
|
|
36
|
+
tool-use schema, required ``max_tokens``, streaming model) that a dedicated
|
|
37
|
+
implementation is cleaner than relying on the OpenAI-compat endpoint.
|
|
38
|
+
|
|
39
|
+
Requires ``nlp.anthropic.api_key`` to be set in the agent config file (or
|
|
40
|
+
passed as ``"api_key"`` inside ``parameters`` for a one-time override).
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
agent (Agent): the agent the LLM belongs to
|
|
44
|
+
name (str): the model identifier (e.g. ``"claude-opus-4-5"``,
|
|
45
|
+
``"claude-sonnet-4-5"``, ``"claude-haiku-4-5-20251001"``).
|
|
46
|
+
parameters (dict): parameters forwarded to ``messages.create``
|
|
47
|
+
(e.g. ``{"temperature": 0.7, "max_tokens": 2048}``). May also contain
|
|
48
|
+
``"api_key"`` which is consumed by :meth:`initialize` and not forwarded.
|
|
49
|
+
num_previous_messages (int): number of previous conversation turns to include
|
|
50
|
+
in :meth:`chat` calls (must be > 0).
|
|
51
|
+
global_context (str): system-level context injected into every request.
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
client: the ``anthropic.Anthropic`` client, instantiated in :meth:`initialize`.
|
|
55
|
+
num_previous_messages (int): number of previous messages used in :meth:`chat`.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self, agent: 'Agent', name: str, parameters: dict, num_previous_messages: int = 1,
|
|
59
|
+
global_context: str = None):
|
|
60
|
+
super().__init__(agent, name, parameters, global_context=global_context)
|
|
61
|
+
self.client: Any = None
|
|
62
|
+
self.num_previous_messages: int = num_previous_messages
|
|
63
|
+
|
|
64
|
+
def set_model(self, name: str) -> None:
|
|
65
|
+
"""Set the Claude model identifier.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
name (str): the new model identifier
|
|
69
|
+
"""
|
|
70
|
+
self.name = name
|
|
71
|
+
|
|
72
|
+
def set_num_previous_messages(self, num_previous_messages: int) -> None:
|
|
73
|
+
"""Set the number of previous messages used in :meth:`chat`.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
num_previous_messages (int): the new number of previous messages
|
|
77
|
+
"""
|
|
78
|
+
self.num_previous_messages = num_previous_messages
|
|
79
|
+
|
|
80
|
+
def initialize(self) -> None:
|
|
81
|
+
"""Instantiate the Anthropic client.
|
|
82
|
+
|
|
83
|
+
Reads ``api_key`` from ``self.parameters`` first (popping it so it is not
|
|
84
|
+
forwarded to the API call), then falls back to the ``nlp.anthropic.api_key``
|
|
85
|
+
config-file property.
|
|
86
|
+
"""
|
|
87
|
+
if anthropic_sdk is None:
|
|
88
|
+
raise ImportError(
|
|
89
|
+
"The 'anthropic' package is required for LLMAnthropic. "
|
|
90
|
+
"Install it with: pip install anthropic"
|
|
91
|
+
)
|
|
92
|
+
api_key = self.parameters.pop('api_key', None) \
|
|
93
|
+
or self._nlp_engine.get_property(nlp.ANTHROPIC_API_KEY)
|
|
94
|
+
self.client = anthropic_sdk.Anthropic(api_key=api_key)
|
|
95
|
+
|
|
96
|
+
# ------------------------------------------------------------------
|
|
97
|
+
# Internal helpers
|
|
98
|
+
# ------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
def _build_system(self, system_message: str = None, session: 'Session' = None) -> str | anthropic_sdk.NOT_GIVEN:
|
|
101
|
+
"""Assemble the Anthropic ``system`` parameter.
|
|
102
|
+
|
|
103
|
+
Anthropic's API requires a single top-level ``system`` string (or ``NOT_GIVEN``),
|
|
104
|
+
not a list of system-role messages. We concatenate global context, session user
|
|
105
|
+
context, and the per-call system message in that order.
|
|
106
|
+
"""
|
|
107
|
+
parts = []
|
|
108
|
+
if self._global_context:
|
|
109
|
+
parts.append(self._global_context)
|
|
110
|
+
if session and session.id in self._user_context:
|
|
111
|
+
parts.append(self._user_context[session.id])
|
|
112
|
+
if system_message:
|
|
113
|
+
parts.append(system_message)
|
|
114
|
+
if parts:
|
|
115
|
+
return "\n\n".join(parts)
|
|
116
|
+
return anthropic_sdk.NOT_GIVEN
|
|
117
|
+
|
|
118
|
+
def _resolve_params(self, parameters: dict) -> dict:
|
|
119
|
+
"""Merge call-time parameters with defaults.
|
|
120
|
+
|
|
121
|
+
Ensures ``max_tokens`` is always present (Anthropic requires it).
|
|
122
|
+
"""
|
|
123
|
+
params = dict(self.parameters) if not parameters else dict(parameters)
|
|
124
|
+
params.setdefault('max_tokens', _DEFAULT_MAX_TOKENS)
|
|
125
|
+
return params
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def _openai_tools_to_anthropic(tools: list[dict]) -> list[dict]:
|
|
129
|
+
"""Convert OpenAI-style tool schemas to Anthropic tool format.
|
|
130
|
+
|
|
131
|
+
OpenAI: ``{"type": "function", "function": {"name", "description", "parameters"}}``
|
|
132
|
+
Anthropic: ``{"name", "description", "input_schema"}``
|
|
133
|
+
"""
|
|
134
|
+
result = []
|
|
135
|
+
for t in tools:
|
|
136
|
+
fn = t.get("function", {}) if t.get("type") == "function" else t
|
|
137
|
+
result.append({
|
|
138
|
+
"name": fn.get("name", ""),
|
|
139
|
+
"description": fn.get("description", ""),
|
|
140
|
+
"input_schema": fn.get("parameters", {"type": "object", "properties": {}}),
|
|
141
|
+
})
|
|
142
|
+
return result
|
|
143
|
+
|
|
144
|
+
# ------------------------------------------------------------------
|
|
145
|
+
# Public API (implements LLM abstract methods)
|
|
146
|
+
# ------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
def predict(self, message: str, parameters: dict = None, session: 'Session' = None,
|
|
149
|
+
system_message: str = None) -> str:
|
|
150
|
+
params = self._resolve_params(parameters)
|
|
151
|
+
system = self._build_system(system_message=system_message, session=session)
|
|
152
|
+
response = self.client.messages.create(
|
|
153
|
+
model=self.name,
|
|
154
|
+
system=system,
|
|
155
|
+
messages=[{"role": "user", "content": message}],
|
|
156
|
+
**params,
|
|
157
|
+
)
|
|
158
|
+
return response.content[0].text
|
|
159
|
+
|
|
160
|
+
def chat(self, session: 'Session', parameters: dict = None, system_message: str = None) -> str:
|
|
161
|
+
if self.num_previous_messages <= 0:
|
|
162
|
+
raise ValueError('The number of previous messages to send to the LLM must be > 0')
|
|
163
|
+
params = self._resolve_params(parameters)
|
|
164
|
+
system = self._build_system(system_message=system_message, session=session)
|
|
165
|
+
chat_history: list[Message] = session.get_chat_history(n=self.num_previous_messages)
|
|
166
|
+
messages = [
|
|
167
|
+
{'role': 'user' if message.is_user else 'assistant', 'content': message.content}
|
|
168
|
+
for message in chat_history
|
|
169
|
+
if message.type in [MessageType.STR, MessageType.LOCATION, MessageType.JSON]
|
|
170
|
+
]
|
|
171
|
+
response = self.client.messages.create(
|
|
172
|
+
model=self.name,
|
|
173
|
+
system=system,
|
|
174
|
+
messages=messages,
|
|
175
|
+
**params,
|
|
176
|
+
)
|
|
177
|
+
return response.content[0].text
|
|
178
|
+
|
|
179
|
+
def predict_with_tools(
|
|
180
|
+
self,
|
|
181
|
+
messages: list[dict],
|
|
182
|
+
tools: list[dict],
|
|
183
|
+
parameters: dict = None,
|
|
184
|
+
system_message: str = None,
|
|
185
|
+
) -> LLMResponse:
|
|
186
|
+
"""Make a tool-calling prediction using the native Anthropic SDK.
|
|
187
|
+
|
|
188
|
+
Input ``messages`` and ``tools`` use OpenAI schema; this method translates them
|
|
189
|
+
to the Anthropic format and maps the response back to the shared
|
|
190
|
+
:class:`~baf.nlp.llm.llm.LLMResponse` / :class:`~baf.nlp.llm.llm.ToolCall`
|
|
191
|
+
types so callers remain provider-agnostic.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
messages (list[dict]): OpenAI-style chat messages. Tool result messages must
|
|
195
|
+
include ``"tool_call_id"`` matching the call they answer.
|
|
196
|
+
tools (list[dict]): OpenAI-style tool schemas.
|
|
197
|
+
parameters (dict): extra parameters (e.g. ``temperature``, ``max_tokens``).
|
|
198
|
+
system_message (str): high-priority system message.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
LLMResponse: final text or list of tool calls.
|
|
202
|
+
"""
|
|
203
|
+
params = self._resolve_params(parameters)
|
|
204
|
+
system = self._build_system(system_message=system_message)
|
|
205
|
+
anthropic_tools = self._openai_tools_to_anthropic(tools) if tools else anthropic_sdk.NOT_GIVEN
|
|
206
|
+
|
|
207
|
+
# Convert OpenAI tool-result messages (role=tool) to Anthropic's user/tool_result format.
|
|
208
|
+
converted: list[dict] = []
|
|
209
|
+
for msg in messages:
|
|
210
|
+
if msg.get("role") == "tool":
|
|
211
|
+
converted.append({
|
|
212
|
+
"role": "user",
|
|
213
|
+
"content": [{
|
|
214
|
+
"type": "tool_result",
|
|
215
|
+
"tool_use_id": msg.get("tool_call_id", ""),
|
|
216
|
+
"content": msg.get("content", ""),
|
|
217
|
+
}]
|
|
218
|
+
})
|
|
219
|
+
else:
|
|
220
|
+
converted.append(msg)
|
|
221
|
+
|
|
222
|
+
response = self.client.messages.create(
|
|
223
|
+
model=self.name,
|
|
224
|
+
system=system,
|
|
225
|
+
messages=converted,
|
|
226
|
+
tools=anthropic_tools,
|
|
227
|
+
**params,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Map Anthropic response blocks back to the shared LLMResponse shape.
|
|
231
|
+
tool_use_blocks = [b for b in response.content if b.type == "tool_use"]
|
|
232
|
+
if tool_use_blocks:
|
|
233
|
+
calls = [
|
|
234
|
+
ToolCall(id=b.id, name=b.name, arguments=b.input if isinstance(b.input, dict) else {})
|
|
235
|
+
for b in tool_use_blocks
|
|
236
|
+
]
|
|
237
|
+
return LLMResponse(text=None, tool_calls=calls, raw=response)
|
|
238
|
+
|
|
239
|
+
text_blocks = [b for b in response.content if b.type == "text"]
|
|
240
|
+
text = text_blocks[0].text if text_blocks else ""
|
|
241
|
+
return LLMResponse(text=text, tool_calls=None, raw=response)
|
|
242
|
+
|
|
243
|
+
def intent_classification(
|
|
244
|
+
self,
|
|
245
|
+
intent_classifier: 'LLMIntentClassifier',
|
|
246
|
+
message: str,
|
|
247
|
+
parameters: dict = None
|
|
248
|
+
) -> list[IntentClassifierPrediction]:
|
|
249
|
+
"""Classify intent via the Anthropic API, returning the same shape as LLMOpenAI.
|
|
250
|
+
|
|
251
|
+
The output is fed to
|
|
252
|
+
:meth:`~baf.nlp.intent_classifier.llm_intent_classifier.LLMIntentClassifier.default_json_to_intent_classifier_predictions`
|
|
253
|
+
so that intent classifiers remain provider-agnostic.
|
|
254
|
+
"""
|
|
255
|
+
params = self._resolve_params(parameters)
|
|
256
|
+
response = self.client.messages.create(
|
|
257
|
+
model=self.name,
|
|
258
|
+
messages=[{"role": "user", "content": message}],
|
|
259
|
+
**params,
|
|
260
|
+
)
|
|
261
|
+
raw_text = response.content[0].text
|
|
262
|
+
try:
|
|
263
|
+
response_json = json.loads(raw_text)
|
|
264
|
+
except json.JSONDecodeError:
|
|
265
|
+
logger.warning(f"LLMAnthropic: could not JSON-decode intent response: {raw_text!r}")
|
|
266
|
+
response_json = {}
|
|
267
|
+
return intent_classifier.default_json_to_intent_classifier_predictions(
|
|
268
|
+
message=message,
|
|
269
|
+
response_json=response_json
|
|
270
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from baf import nlp
|
|
4
|
+
from baf.nlp.llm.llm_openai_compatible import LLMOpenAICompatible
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LLMDeepSeek(LLMOpenAICompatible):
|
|
8
|
+
"""LLM wrapper for DeepSeek models via DeepSeek's OpenAI-compatible API.
|
|
9
|
+
|
|
10
|
+
Requires ``nlp.deepseek.api_key`` to be set in the agent config file.
|
|
11
|
+
The default base URL points to ``https://api.deepseek.com``.
|
|
12
|
+
|
|
13
|
+
Example model names: ``"deepseek-chat"``, ``"deepseek-reasoner"``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
DEFAULT_BASE_URL = "https://api.deepseek.com"
|
|
17
|
+
API_KEY_PROPERTY = nlp.DEEPSEEK_API_KEY
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from baf import nlp
|
|
4
|
+
from baf.nlp.llm.llm_openai_compatible import LLMOpenAICompatible
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LLMGoogle(LLMOpenAICompatible):
|
|
8
|
+
"""LLM wrapper for Google Gemini models via Google's OpenAI-compatible endpoint.
|
|
9
|
+
|
|
10
|
+
Requires ``nlp.google.api_key`` to be set in the agent config file.
|
|
11
|
+
The default base URL points to the Gemini OpenAI-compatible endpoint.
|
|
12
|
+
|
|
13
|
+
Example model names: ``"gemini-2.5-pro"``, ``"gemini-2.5-flash"``,
|
|
14
|
+
``"gemini-2.0-flash"``, ``"gemini-1.5-pro"``.
|
|
15
|
+
|
|
16
|
+
Note: for advanced Gemini-specific features (grounding, multimodal tool use, etc.)
|
|
17
|
+
a native ``google-genai`` SDK wrapper can be added separately.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
|
|
21
|
+
API_KEY_PROPERTY = nlp.GOOGLE_API_KEY
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from baf import nlp
|
|
4
|
+
from baf.nlp.llm.llm_openai_compatible import LLMOpenAICompatible
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LLMGroq(LLMOpenAICompatible):
|
|
8
|
+
"""LLM wrapper for Groq-hosted models via Groq's OpenAI-compatible API.
|
|
9
|
+
|
|
10
|
+
Requires ``nlp.groq.api_key`` to be set in the agent config file.
|
|
11
|
+
The default base URL points to ``https://api.groq.com/openai/v1``.
|
|
12
|
+
|
|
13
|
+
Example model names: ``"llama-3.3-70b-versatile"``, ``"llama3-8b-8192"``,
|
|
14
|
+
``"gemma2-9b-it"``, ``"mixtral-8x7b-32768"``.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
DEFAULT_BASE_URL = "https://api.groq.com/openai/v1"
|
|
18
|
+
API_KEY_PROPERTY = nlp.GROQ_API_KEY
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from baf import nlp
|
|
4
|
+
from baf.nlp.llm.llm_openai_compatible import LLMOpenAICompatible
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LLMMeta(LLMOpenAICompatible):
|
|
8
|
+
"""LLM wrapper for Meta Llama models via Meta's OpenAI-compatible API.
|
|
9
|
+
|
|
10
|
+
Requires ``nlp.meta.api_key`` to be set in the agent config file.
|
|
11
|
+
The default base URL points to ``https://api.llama.com/compat/v1/``.
|
|
12
|
+
|
|
13
|
+
Example model names: ``"Llama-4-Scout-17B-16E-Instruct-FP8"``,
|
|
14
|
+
``"Llama-4-Maverick-17B-128E-Instruct-FP8"``, ``"Llama-3.3-70B-Instruct"``.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
DEFAULT_BASE_URL = "https://api.llama.com/compat/v1/"
|
|
18
|
+
API_KEY_PROPERTY = nlp.META_API_KEY
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from baf import nlp
|
|
4
|
+
from baf.nlp.llm.llm_openai_compatible import LLMOpenAICompatible
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LLMMistral(LLMOpenAICompatible):
|
|
8
|
+
"""LLM wrapper for Mistral AI models via Mistral's OpenAI-compatible API.
|
|
9
|
+
|
|
10
|
+
Requires ``nlp.mistral.api_key`` to be set in the agent config file.
|
|
11
|
+
The default base URL points to ``https://api.mistral.ai/v1``.
|
|
12
|
+
|
|
13
|
+
Example model names: ``"mistral-small-latest"``, ``"mistral-large-latest"``,
|
|
14
|
+
``"mistral-medium-latest"``, ``"open-mistral-nemo"``.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
DEFAULT_BASE_URL = "https://api.mistral.ai/v1"
|
|
18
|
+
API_KEY_PROPERTY = nlp.MISTRAL_API_KEY
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from baf import nlp
|
|
6
|
+
from baf.nlp.llm.llm_openai_compatible import LLMOpenAICompatible
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from baf.core.agent import Agent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LLMOpenAI(LLMOpenAICompatible):
|
|
13
|
+
"""An LLM wrapper for OpenAI's models through the OpenAI API.
|
|
14
|
+
|
|
15
|
+
Inherits all prediction logic from :class:`~baf.nlp.llm.llm_openai_compatible.LLMOpenAICompatible`.
|
|
16
|
+
The OpenAI client is initialised with the ``nlp.openai.api_key`` config property and the
|
|
17
|
+
standard ``https://api.openai.com`` base URL.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
agent (Agent): the agent the LLM belongs to
|
|
21
|
+
name (str): the model identifier (e.g. ``"gpt-4o-mini"``)
|
|
22
|
+
parameters (dict): parameters forwarded to ``chat.completions.create``
|
|
23
|
+
(e.g. ``{"temperature": 0.7}``).
|
|
24
|
+
num_previous_messages (int): number of previous turns to include in :meth:`chat`
|
|
25
|
+
calls (must be > 0).
|
|
26
|
+
global_context (str): system-level context injected into every request.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
client (OpenAI): the OpenAI client, instantiated in :meth:`initialize`.
|
|
30
|
+
num_previous_messages (int): number of previous messages used in :meth:`chat`.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
DEFAULT_BASE_URL: str | None = None # use the OpenAI SDK default
|
|
34
|
+
API_KEY_PROPERTY = nlp.OPENAI_API_KEY
|