besser-agentic-framework 4.4.2__tar.gz → 4.5.1__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.4.2/besser_agentic_framework.egg-info → besser_agentic_framework-4.5.1}/PKG-INFO +7 -3
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/agent.py +15 -2
- besser_agentic_framework-4.5.1/baf/core/gui/agent_gui.py +291 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/gui/gui_deserializer.py +40 -7
- besser_agentic_framework-4.5.1/baf/core/gui/gui_llm.py +118 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/gui/gui_schema.py +69 -8
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/gui/gui_serializer.py +92 -42
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/message.py +4 -4
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/session.py +10 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/state.py +40 -2
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/transition/condition_functions.py +26 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/transition/conditions.py +24 -1
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/transition/events/base_events.py +31 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/__init__.py +121 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_anthropic.py +270 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_deepseek.py +17 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_google.py +21 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_groq.py +18 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_meta.py +18 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_mistral.py +18 -0
- besser_agentic_framework-4.4.2/baf/nlp/llm/llm_openai_api.py → besser_agentic_framework-4.5.1/baf/nlp/llm/llm_ollama.py +52 -42
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_openai_api.py +34 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_openai_compatible.py +208 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_openrouter.py +20 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_qwen.py +18 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_together.py +19 -0
- besser_agentic_framework-4.5.1/baf/nlp/llm/llm_xai.py +17 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/rag/rag.py +107 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/payload.py +18 -7
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/websocket_platform.py +52 -18
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/test_extras.py +11 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/test_llms.py +6 -0
- besser_agentic_framework-4.5.1/baf/test/examples/hybrid_rag_agent.py +126 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1/besser_agentic_framework.egg-info}/PKG-INFO +7 -3
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/besser_agentic_framework.egg-info/SOURCES.txt +15 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/besser_agentic_framework.egg-info/requires.txt +6 -2
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/requirements/requirements-extras.txt +1 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/requirements/requirements-llms.txt +1 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/requirements/requirements-torch.txt +1 -1
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/setup.cfg +1 -1
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/LICENSE +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/MANIFEST.in +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/README.md +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/entity/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/entity/entity.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/entity/entity_entry.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/file.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/gui/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/intent/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/intent/intent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/intent/intent_parameter.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/processors/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/processors/audio_language_detection_processor.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/processors/language_detection_processor.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/processors/processor.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/processors/user_adaptation_processor.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/property.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/transition/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/transition/condition.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/transition/event.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/transition/transition.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/transition/transition_builder.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/db_handler.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_db.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/db_connection.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/flow_graph.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/home.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/intent_details.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/monitoring_ui.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/sidebar.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/table_overview.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/db/monitoring_ui/utils.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/exceptions/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/exceptions/exceptions.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/exceptions/logger.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/coroutine/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/coroutine/async_helpers.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/entity/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/entity/base_entities.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/intent/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/intent/intent_library.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/state/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/state/reasoning_state_library.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/state/state_library.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/tool/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/tool/task_tools.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/tool/workspace_tools.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/transition/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/transition/events/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/transition/events/github_webhooks_events.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/library/transition/events/gitlab_webhooks_events.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/intent_classifier/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/intent_classifier/intent_classifier.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/intent_classifier/intent_classifier_configuration.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/intent_classifier/intent_classifier_prediction.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/intent_classifier/llm_intent_classifier.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/intent_classifier/simple_intent_classifier_pytorch.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/intent_classifier/simple_intent_classifier_tensorflow.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/llm/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/llm/llm.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/llm/llm_huggingface.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/llm/llm_huggingface_api.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/llm/llm_replicate_api.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/base/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/base/any.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/base/datetime.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/base/number.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/matched_parameter.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/ner.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/ner_prediction.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/ner/simple_ner.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/nlp_engine.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/preprocessing/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/preprocessing/pipelines.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/preprocessing/text_preprocessing.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/rag/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/speech2text/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/speech2text/api_speech2text.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/speech2text/hf_speech2text.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/speech2text/luxasr_speech2text.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/speech2text/openai_speech2text.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/speech2text/speech2text.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/text2speech/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/text2speech/hf_text2speech.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/text2speech/openai_text2speech.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/text2speech/piper_text2speech.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/text2speech/text2speech.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/nlp/utils.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/a2a_platform.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/agent_card.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/agent_registry.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/client.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/error_handler.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/message_router.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/server.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/a2a/task_protocol.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/github/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/github/github_actions.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/github/github_objects.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/github/github_platform.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/gitlab/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/gitlab/gitlab_actions.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/gitlab/gitlab_objects.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/gitlab/gitlab_platform.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/platform.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/telegram/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/telegram/telegram_platform.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/audio_queue.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/chat.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/chat_interface_style.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/initialization.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/login.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/message_input.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/profile_selector.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/reasoning.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/session_management.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/sidebar.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/streamlit_ui.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/user_db.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/vars.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/platforms/websocket/streamlit_ui/websocket_callbacks.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/reasoning/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/reasoning/skill.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/reasoning/tool.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/reasoning/workspace.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/conftest.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_intent_entity.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_message.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_processor.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_property.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_session.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_state.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_core_transition.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_library_events.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_nlp_configurations.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_nlp_engine.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_nlp_preprocessing.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_platforms.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/components/test_workflows.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/conftest.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/test_core.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/test_docs.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/test_framework.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/test_tensorflow.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/dependencies/test_torch.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/a2a_multiagent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/api_speech2text_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/github_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/gitlab_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/greetings_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/llm_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/multiagent/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/multiagent/coder_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/multiagent/main_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/multiagent/reviewer_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/rag_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/reasoning_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/speech2speech_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/speech2text_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/stargazer_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/telegram_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/text2speech_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/weather_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/test/examples/web_crawl_agent.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/utils/__init__.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/utils/web_crawl.py +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/besser_agentic_framework.egg-info/dependency_links.txt +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/besser_agentic_framework.egg-info/top_level.txt +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/pyproject.toml +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/requirements/requirements-core.txt +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/requirements/requirements-docs.txt +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/requirements/requirements-tensorflow.txt +0 -0
- {besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: besser-agentic-framework
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.1
|
|
4
4
|
Summary: BESSER Agentic Framework (BAF)
|
|
5
5
|
Author: Luxembourg Institute of Science and Technology
|
|
6
6
|
License: MIT
|
|
@@ -53,15 +53,17 @@ 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"
|
|
63
65
|
Provides-Extra: torch
|
|
64
|
-
Requires-Dist: torch==2.6.0
|
|
66
|
+
Requires-Dist: torch==2.6.0; extra == "torch"
|
|
65
67
|
Requires-Dist: scikit-learn>=1.7.0; extra == "torch"
|
|
66
68
|
Provides-Extra: docs
|
|
67
69
|
Requires-Dist: sphinx==7.2.3; extra == "docs"
|
|
@@ -86,12 +88,14 @@ 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
|
-
Requires-Dist: torch==2.6.0
|
|
98
|
+
Requires-Dist: torch==2.6.0; extra == "all"
|
|
95
99
|
Requires-Dist: scikit-learn>=1.7.0; extra == "all"
|
|
96
100
|
Dynamic: license-file
|
|
97
101
|
Dynamic: provides-extra
|
|
@@ -9,7 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
from typing import Any, Callable, get_type_hints
|
|
10
10
|
|
|
11
11
|
import yaml
|
|
12
|
-
|
|
12
|
+
from baf.core.gui.agent_gui import AgentGUI
|
|
13
13
|
from baf.core.transition.event import Event
|
|
14
14
|
from baf.core.message import Message, MessageType
|
|
15
15
|
from baf.core.entity.entity import Entity
|
|
@@ -26,7 +26,7 @@ from baf.db.monitoring_db import MonitoringDB
|
|
|
26
26
|
from baf.exceptions.exceptions import AgentNotTrainedError, DuplicatedEntityError, DuplicatedInitialStateError, \
|
|
27
27
|
DuplicatedIntentError, DuplicatedStateError, InitialStateNotFound
|
|
28
28
|
from baf.exceptions.logger import logger
|
|
29
|
-
from baf.library.transition.events.base_events import ReceiveMessageEvent, ReceiveJSONEvent, ReceiveFileEvent
|
|
29
|
+
from baf.library.transition.events.base_events import ReceiveMessageEvent, ReceiveJSONEvent, ReceiveFileEvent, GUIEvent
|
|
30
30
|
from baf.nlp.intent_classifier.intent_classifier_configuration import IntentClassifierConfiguration, \
|
|
31
31
|
SimpleIntentClassifierConfiguration
|
|
32
32
|
from baf.nlp.intent_classifier.intent_classifier_prediction import IntentClassifierPrediction
|
|
@@ -138,6 +138,7 @@ class Agent:
|
|
|
138
138
|
"""dict[str, Any]: The agent configuration parameters."""
|
|
139
139
|
return self._config
|
|
140
140
|
|
|
141
|
+
|
|
141
142
|
def load_properties(self, path: str) -> None:
|
|
142
143
|
"""Read a properties file and store its properties in the agent configuration.
|
|
143
144
|
|
|
@@ -818,6 +819,18 @@ class Agent:
|
|
|
818
819
|
session.save_message(Message(t=t, content=event.message, is_user=True, timestamp=datetime.now()))
|
|
819
820
|
if isinstance(event, ReceiveFileEvent):
|
|
820
821
|
session.save_message(Message(t=MessageType.FILE, content=event.file.get_json_string(), is_user=True, timestamp=datetime.now()))
|
|
822
|
+
if isinstance(event, GUIEvent) and not event.is_broadcasted():
|
|
823
|
+
message_id = event.message_id
|
|
824
|
+
if message_id and message_id in session.gui_inputs:
|
|
825
|
+
action = event.event_data.get('action')
|
|
826
|
+
value = event.event_data.get('value')
|
|
827
|
+
if action == 'onChange':
|
|
828
|
+
field_name = event.event_data.get('name')
|
|
829
|
+
if field_name is not None:
|
|
830
|
+
session.gui_inputs[message_id][field_name] = value
|
|
831
|
+
elif action == 'onSubmit':
|
|
832
|
+
if isinstance(value, dict):
|
|
833
|
+
session.gui_inputs[message_id].update(value)
|
|
821
834
|
|
|
822
835
|
logger.info(f'Received event: {event.log()}')
|
|
823
836
|
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""AgentGUI: BAF's interface to besser's GUIModel, with optional-dependency handling."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import copy
|
|
5
|
+
import uuid
|
|
6
|
+
|
|
7
|
+
from baf.exceptions.logger import logger
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from besser.BUML.metamodel.gui.graphical_ui import GUIModel, ViewContainer
|
|
11
|
+
_BESSER_AVAILABLE = True
|
|
12
|
+
except ImportError:
|
|
13
|
+
logger.warning(
|
|
14
|
+
"besser GUI dependencies could not be imported. GUI features will be unavailable. "
|
|
15
|
+
"Install with 'pip install --no-deps besser'."
|
|
16
|
+
)
|
|
17
|
+
GUIModel = None
|
|
18
|
+
ViewContainer = None
|
|
19
|
+
_BESSER_AVAILABLE = False
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AgentGUI:
|
|
23
|
+
"""BAF's interface to besser's :class:`GUIModel`, with helper methods for common GUI operations.
|
|
24
|
+
|
|
25
|
+
Handles the case where besser is not installed: all methods log a warning and return
|
|
26
|
+
``None``/``False`` instead of raising an error. When besser *is* installed, attribute
|
|
27
|
+
access is transparently delegated to the inner model so that existing code that uses
|
|
28
|
+
``gui.modules``, ``gui.name``, etc. continues to work unchanged.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
model: the :class:`GUIModel` instance to wrap, or ``None``.
|
|
32
|
+
gui_id: identifier for the AgentGUI.
|
|
33
|
+
persist: whether to store GUI updates in the session or not. Defaults to true
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
_model: the inner :class:`GUIModel`, or ``None`` when besser is not installed or
|
|
37
|
+
no model has been set.
|
|
38
|
+
_id: identifier for the AgentGUI.
|
|
39
|
+
_persist: whether to store GUI updates in the session or not. Defaults to true
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, model: GUIModel, gui_id: str | None = None, persist: bool = True, width: str | None = None):
|
|
43
|
+
self._model: GUIModel = model
|
|
44
|
+
if gui_id is None:
|
|
45
|
+
gui_id = str(uuid.uuid4())
|
|
46
|
+
self._id: str = gui_id
|
|
47
|
+
self._persist: bool = persist
|
|
48
|
+
self._width: str | None = width
|
|
49
|
+
|
|
50
|
+
# ------------------------------------------------------------------
|
|
51
|
+
# Core proxy behaviour
|
|
52
|
+
# ------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def model(self):
|
|
56
|
+
"""The underlying GUIModel instance, or None."""
|
|
57
|
+
return self._model
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def id(self) -> str:
|
|
61
|
+
"""Unique identifier for this GUI reply message."""
|
|
62
|
+
return self._id
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def persist(self) -> bool:
|
|
66
|
+
"""bool: If True, input values from GUI events for this component are persisted in the session's gui_inputs."""
|
|
67
|
+
return self._persist
|
|
68
|
+
|
|
69
|
+
@persist.setter
|
|
70
|
+
def persist(self, value: bool) -> None:
|
|
71
|
+
self._persist = value
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def width(self) -> str | None:
|
|
75
|
+
"""str | None: CSS width applied to the GUI bubble in chat mode (e.g. '600px', '80%').
|
|
76
|
+
Overrides the default 78% max-width cap. None means use the default."""
|
|
77
|
+
return self._width
|
|
78
|
+
|
|
79
|
+
@width.setter
|
|
80
|
+
def width(self, value: str | None) -> None:
|
|
81
|
+
self._width = value
|
|
82
|
+
|
|
83
|
+
def __getattr__(self, name: str):
|
|
84
|
+
"""Delegate attribute access to the inner GUIModel."""
|
|
85
|
+
model = self._model
|
|
86
|
+
if model is None:
|
|
87
|
+
if not _BESSER_AVAILABLE:
|
|
88
|
+
logger.warning(
|
|
89
|
+
f"Cannot access attribute '{name}': besser is not installed. "
|
|
90
|
+
"Install with 'pip install --no-deps besser'."
|
|
91
|
+
)
|
|
92
|
+
else:
|
|
93
|
+
logger.warning(f"Cannot access attribute '{name}': no GUI model set.")
|
|
94
|
+
return None
|
|
95
|
+
return getattr(model, name)
|
|
96
|
+
|
|
97
|
+
def __setattr__(self, name: str, value):
|
|
98
|
+
"""Delegate attribute assignment to the inner GUIModel for non-private names."""
|
|
99
|
+
if name.startswith('_'):
|
|
100
|
+
super().__setattr__(name, value)
|
|
101
|
+
return
|
|
102
|
+
model = self._model
|
|
103
|
+
if model is None:
|
|
104
|
+
logger.warning(f"Cannot set attribute '{name}': no GUI model set.")
|
|
105
|
+
return
|
|
106
|
+
setattr(model, name, value)
|
|
107
|
+
|
|
108
|
+
def __bool__(self) -> bool:
|
|
109
|
+
return self._model is not None
|
|
110
|
+
|
|
111
|
+
# ------------------------------------------------------------------
|
|
112
|
+
# Helper: deep copy
|
|
113
|
+
# ------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
def deep_copy(self) -> 'AgentGUI':
|
|
116
|
+
"""Return a deep copy of this :class:`AgentGUI` and its inner model.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
AgentGUI: a new instance wrapping a deep-copied model.
|
|
120
|
+
"""
|
|
121
|
+
model = self._model
|
|
122
|
+
if model is None:
|
|
123
|
+
return AgentGUI(None)
|
|
124
|
+
try:
|
|
125
|
+
return AgentGUI(copy.deepcopy(model))
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.warning(f"Could not deep-copy GUI model: {e}. Returning a shallow reference.")
|
|
128
|
+
return AgentGUI(model)
|
|
129
|
+
|
|
130
|
+
# ------------------------------------------------------------------
|
|
131
|
+
# Helper: find
|
|
132
|
+
# ------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
def find_components(self, field: str, value) -> list:
|
|
135
|
+
"""Find all components in the model where ``getattr(component, field) == value``.
|
|
136
|
+
|
|
137
|
+
Recursively searches through all modules → screens → containers.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
field (str): the attribute name to match (e.g. ``'component_id'``,
|
|
141
|
+
``'name'``, ``'content'``).
|
|
142
|
+
value: the value to look for.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
list: all matching :class:`ViewElement` instances (empty list if none found).
|
|
146
|
+
"""
|
|
147
|
+
model: GUIModel = self._model
|
|
148
|
+
if model is None:
|
|
149
|
+
logger.warning("Cannot find components: no GUI model set.")
|
|
150
|
+
return []
|
|
151
|
+
results = []
|
|
152
|
+
for module in model.modules:
|
|
153
|
+
for screen in module.screens:
|
|
154
|
+
self._collect_matching(screen.view_elements, field, value, results)
|
|
155
|
+
return results
|
|
156
|
+
|
|
157
|
+
def find_component(self, field: str, value):
|
|
158
|
+
"""Find the first component in the model where ``getattr(component, field) == value``.
|
|
159
|
+
|
|
160
|
+
Recursively searches through all modules → screens → containers.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
field (str): the attribute name to match (e.g. ``'component_id'``,
|
|
164
|
+
``'name'``, ``'content'``).
|
|
165
|
+
value: the value to look for.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
The first matching :class:`ViewElement`, or ``None`` if not found.
|
|
169
|
+
"""
|
|
170
|
+
results = self.find_components(field, value)
|
|
171
|
+
return results[0] if results else None
|
|
172
|
+
|
|
173
|
+
def _collect_matching(self, elements, field: str, value, results: list) -> None:
|
|
174
|
+
"""Recursively collect into *results* every element where ``getattr(el, field) == value``."""
|
|
175
|
+
for el in elements:
|
|
176
|
+
if getattr(el, field, None) == value:
|
|
177
|
+
results.append(el)
|
|
178
|
+
child_elements = getattr(el, 'view_elements', None)
|
|
179
|
+
if child_elements:
|
|
180
|
+
self._collect_matching(child_elements, field, value, results)
|
|
181
|
+
|
|
182
|
+
# ------------------------------------------------------------------
|
|
183
|
+
# Helper: update
|
|
184
|
+
# ------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
def update_component_by_id(self, component_id: str, **kwargs):
|
|
187
|
+
"""Update attributes of a component located by its ``component_id``.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
component_id (str): identifies the component to update.
|
|
191
|
+
**kwargs: attribute names and their new values.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
The updated component if found, or ``None``.
|
|
195
|
+
"""
|
|
196
|
+
model = self._model
|
|
197
|
+
if model is None:
|
|
198
|
+
logger.warning("Cannot update component: no GUI model set.")
|
|
199
|
+
return None
|
|
200
|
+
component = self.find_component('component_id', component_id)
|
|
201
|
+
if component is None:
|
|
202
|
+
logger.warning(f"Component with id '{component_id}' not found in GUI model.")
|
|
203
|
+
return None
|
|
204
|
+
for attr, value in kwargs.items():
|
|
205
|
+
setattr(component, attr, value)
|
|
206
|
+
return component
|
|
207
|
+
|
|
208
|
+
# ------------------------------------------------------------------
|
|
209
|
+
# Helper: add
|
|
210
|
+
# ------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
def add_component(self, component, parent_id: str = None, screen_name: str = None) -> bool:
|
|
213
|
+
"""Add a component to the GUI model.
|
|
214
|
+
|
|
215
|
+
Resolution order:
|
|
216
|
+
|
|
217
|
+
1. If *parent_id* is given, the component is added to the container that has
|
|
218
|
+
that ``component_id`` (must be a container with ``view_elements``).
|
|
219
|
+
2. If *screen_name* is given, the component is added to the top-level
|
|
220
|
+
``view_elements`` of the named screen.
|
|
221
|
+
3. Otherwise the component is added to the main screen (``is_main_page=True``),
|
|
222
|
+
or to the first screen when no main screen exists.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
component: the :class:`ViewElement` to add.
|
|
226
|
+
parent_id (str | None): ``component_id`` of the target container.
|
|
227
|
+
screen_name (str | None): name of the target screen (used when *parent_id* is
|
|
228
|
+
not given).
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
bool: ``True`` if the component was added, ``False`` otherwise.
|
|
232
|
+
"""
|
|
233
|
+
model = self._model
|
|
234
|
+
if model is None:
|
|
235
|
+
logger.warning("Cannot add component: no GUI model set.")
|
|
236
|
+
return False
|
|
237
|
+
|
|
238
|
+
if parent_id is not None:
|
|
239
|
+
parent = self.find_component('component_id', parent_id)
|
|
240
|
+
if parent is None:
|
|
241
|
+
logger.warning(f"Parent container with id '{parent_id}' not found.")
|
|
242
|
+
return False
|
|
243
|
+
if not hasattr(parent, 'view_elements'):
|
|
244
|
+
logger.warning(f"Component '{parent_id}' is not a container (no view_elements).")
|
|
245
|
+
return False
|
|
246
|
+
parent.view_elements = parent.view_elements | {component}
|
|
247
|
+
return True
|
|
248
|
+
|
|
249
|
+
target = self.get_screen(screen_name)
|
|
250
|
+
if target is None:
|
|
251
|
+
logger.warning("No screen found to add the component to.")
|
|
252
|
+
return False
|
|
253
|
+
target.view_elements = target.view_elements | {component}
|
|
254
|
+
return True
|
|
255
|
+
|
|
256
|
+
# ------------------------------------------------------------------
|
|
257
|
+
# Helper: screens
|
|
258
|
+
# ------------------------------------------------------------------
|
|
259
|
+
|
|
260
|
+
def get_screen(self, screen_name: str = None):
|
|
261
|
+
"""Retrieve a screen by name, or the main screen when no name is given.
|
|
262
|
+
|
|
263
|
+
Falls back to the first screen when there is no screen marked as main.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
screen_name (str | None): the screen name to look for, or ``None`` to get
|
|
267
|
+
the main/first screen.
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
The :class:`Screen`, or ``None`` if not found.
|
|
271
|
+
"""
|
|
272
|
+
model = self._model
|
|
273
|
+
if model is None:
|
|
274
|
+
logger.warning("Cannot get screen: no GUI model set.")
|
|
275
|
+
return None
|
|
276
|
+
|
|
277
|
+
first = None
|
|
278
|
+
for module in model.modules:
|
|
279
|
+
for screen in module.screens:
|
|
280
|
+
if first is None:
|
|
281
|
+
first = screen
|
|
282
|
+
if screen_name is not None:
|
|
283
|
+
if screen.name == screen_name:
|
|
284
|
+
return screen
|
|
285
|
+
elif getattr(screen, 'is_main_page', False):
|
|
286
|
+
return screen
|
|
287
|
+
|
|
288
|
+
# Fallbacks
|
|
289
|
+
if screen_name is None:
|
|
290
|
+
return first
|
|
291
|
+
return None
|
{besser_agentic_framework-4.4.2 → besser_agentic_framework-4.5.1}/baf/core/gui/gui_deserializer.py
RENAMED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
"""Deserialization helpers: JSON string →
|
|
1
|
+
"""Deserialization helpers: JSON string → AgentGUI."""
|
|
2
2
|
import json
|
|
3
3
|
from types import SimpleNamespace
|
|
4
4
|
|
|
5
|
+
from baf.core.gui.agent_gui import AgentGUI
|
|
5
6
|
from baf.exceptions.logger import logger
|
|
6
7
|
|
|
7
8
|
try:
|
|
@@ -10,6 +11,7 @@ try:
|
|
|
10
11
|
ViewElement, ViewContainer, ViewComponent,
|
|
11
12
|
Button, Text, Image, InputField, Form, Menu, MenuItem,
|
|
12
13
|
DataList, EmbeddedContent, Link,
|
|
14
|
+
Alert, AlertSeverity, SelectOption,
|
|
13
15
|
)
|
|
14
16
|
from besser.BUML.metamodel.gui.style import Styling, Size, Position, Color, Layout
|
|
15
17
|
from besser.BUML.metamodel.gui.dashboard import (
|
|
@@ -302,8 +304,22 @@ def _deserialize_view_element(d: dict) -> ViewElement:
|
|
|
302
304
|
)
|
|
303
305
|
|
|
304
306
|
if t == "InputField":
|
|
307
|
+
options_data = d.get("options") or []
|
|
308
|
+
options = [SelectOption(label=o.get("label", ""), value=o.get("value", "")) for o in options_data]
|
|
305
309
|
return InputField(
|
|
306
|
-
field_type=d.get("field_type", "
|
|
310
|
+
field_type=d.get("field_type", "Text"),
|
|
311
|
+
label=d.get("label", ""),
|
|
312
|
+
placeholder=d.get("placeholder", ""),
|
|
313
|
+
required=d.get("required", False),
|
|
314
|
+
default_value=d.get("default_value"),
|
|
315
|
+
options=options if options else None,
|
|
316
|
+
min_value=d.get("min_value"),
|
|
317
|
+
max_value=d.get("max_value"),
|
|
318
|
+
step=d.get("step"),
|
|
319
|
+
help_text=d.get("help_text"),
|
|
320
|
+
disabled=d.get("disabled", False),
|
|
321
|
+
readonly=d.get("readonly", False),
|
|
322
|
+
multiple=d.get("multiple", False),
|
|
307
323
|
validationRules=d.get("validationRules"),
|
|
308
324
|
**base,
|
|
309
325
|
)
|
|
@@ -311,6 +327,11 @@ def _deserialize_view_element(d: dict) -> ViewElement:
|
|
|
311
327
|
if t == "Form":
|
|
312
328
|
return Form(
|
|
313
329
|
inputFields=set(_deserialize_view_element(f) for f in d.get("inputFields", [])),
|
|
330
|
+
title=d.get("title"),
|
|
331
|
+
submit_label=d.get("submit_label", "Submit"),
|
|
332
|
+
show_cancel=d.get("show_cancel", False),
|
|
333
|
+
cancel_label=d.get("cancel_label", "Cancel"),
|
|
334
|
+
columns=d.get("columns", 1),
|
|
314
335
|
**base,
|
|
315
336
|
)
|
|
316
337
|
|
|
@@ -329,6 +350,18 @@ def _deserialize_view_element(d: dict) -> ViewElement:
|
|
|
329
350
|
if t == "DataList":
|
|
330
351
|
return DataList(list_sources=set(), **base)
|
|
331
352
|
|
|
353
|
+
if t == "Alert":
|
|
354
|
+
severity_str = d.get("severity", "info")
|
|
355
|
+
_severity_map = {s.value: s for s in AlertSeverity}
|
|
356
|
+
severity = _severity_map.get(severity_str, AlertSeverity.Info)
|
|
357
|
+
return Alert(
|
|
358
|
+
content=d.get("content", ""),
|
|
359
|
+
severity=severity,
|
|
360
|
+
title=d.get("title"),
|
|
361
|
+
dismissible=d.get("dismissible", False),
|
|
362
|
+
**base,
|
|
363
|
+
)
|
|
364
|
+
|
|
332
365
|
if t == "EmbeddedContent":
|
|
333
366
|
return EmbeddedContent(
|
|
334
367
|
source=d.get("source", ""),
|
|
@@ -367,14 +400,14 @@ def _deserialize_screen(d: dict) -> Screen:
|
|
|
367
400
|
return Screen(**base)
|
|
368
401
|
|
|
369
402
|
|
|
370
|
-
def json_to_gui(json_str: str) ->
|
|
371
|
-
"""Deserialize a JSON string produced by :func:`gui_to_json` back into
|
|
403
|
+
def json_to_gui(json_str: str, gui_id: str | None = None) -> AgentGUI:
|
|
404
|
+
"""Deserialize a JSON string produced by :func:`gui_to_json` back into an :class:`~baf.core.gui.agent_gui.AgentGUI`.
|
|
372
405
|
|
|
373
406
|
Args:
|
|
374
407
|
json_str: JSON string representing the GUI model.
|
|
375
408
|
|
|
376
409
|
Returns:
|
|
377
|
-
A reconstructed :class
|
|
410
|
+
A reconstructed :class:`~baf.core.gui.agent_gui.AgentGUI` instance wrapping the rebuilt model.
|
|
378
411
|
"""
|
|
379
412
|
data = json.loads(json_str)
|
|
380
413
|
modules = set()
|
|
@@ -392,7 +425,7 @@ def json_to_gui(json_str: str) -> GUIModel:
|
|
|
392
425
|
style_entries = data.get("style_entries")
|
|
393
426
|
if style_entries is not None:
|
|
394
427
|
try:
|
|
395
|
-
return GUIModel(**gui_kwargs, style_entries=style_entries)
|
|
428
|
+
return AgentGUI(GUIModel(**gui_kwargs, style_entries=style_entries))
|
|
396
429
|
except TypeError:
|
|
397
430
|
pass
|
|
398
|
-
return GUIModel(**gui_kwargs)
|
|
431
|
+
return AgentGUI(GUIModel(**gui_kwargs), gui_id=gui_id)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""LLM-assisted GUI generation utilities."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import re
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from baf.core.gui.agent_gui import AgentGUI
|
|
9
|
+
from baf.core.gui.gui_deserializer import json_to_gui
|
|
10
|
+
from baf.core.gui.gui_schema import get_json_schema
|
|
11
|
+
from baf.exceptions.logger import logger
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from baf.nlp.llm.llm import LLM
|
|
15
|
+
|
|
16
|
+
_SYSTEM_PROMPT_TEMPLATE = (
|
|
17
|
+
"You are a GUI model generator. Given a user request, respond with a single valid JSON object "
|
|
18
|
+
"that conforms to the JSON Schema below. Output raw JSON only — no explanation, no markdown "
|
|
19
|
+
"code fences, no prose before or after.\n\n"
|
|
20
|
+
"JSON Schema:\n{schema}\n\n"
|
|
21
|
+
"Rules:\n"
|
|
22
|
+
"- The top-level object must contain 'name' and 'modules'.\n"
|
|
23
|
+
"- Each module must have 'name' and 'screens'.\n"
|
|
24
|
+
"- Each screen must have 'name' and 'view_elements'.\n"
|
|
25
|
+
"- Every view element must have a 'type' field discriminating its kind.\n"
|
|
26
|
+
"- Keep the model minimal but meaningful for the user request.\n"
|
|
27
|
+
"- Use realistic placeholder content (titles, labels, button labels, etc.)."
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
_RETRY_PROMPT_TEMPLATE = (
|
|
31
|
+
"The previous response could not be deserialized. Error: {error}\n\n"
|
|
32
|
+
"Please fix the JSON and respond again with a single valid JSON object only. "
|
|
33
|
+
"Original request: {prompt}"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _build_system_prompt() -> str:
|
|
38
|
+
return _SYSTEM_PROMPT_TEMPLATE.format(schema=json.dumps(get_json_schema(), indent=2))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _extract_json(text: str) -> str:
|
|
42
|
+
"""Strip markdown code fences and return the raw JSON string from LLM output."""
|
|
43
|
+
match = re.search(r'```(?:json)?\s*([\s\S]*?)\s*```', text)
|
|
44
|
+
if match:
|
|
45
|
+
return match.group(1).strip()
|
|
46
|
+
match = re.search(r'(\{[\s\S]*\})', text)
|
|
47
|
+
if match:
|
|
48
|
+
return match.group(1).strip()
|
|
49
|
+
return text.strip()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def create_gui_with_llm(
|
|
53
|
+
llm: 'LLM',
|
|
54
|
+
prompt: str,
|
|
55
|
+
gui_id: str | None = None,
|
|
56
|
+
max_retries: int = 2,
|
|
57
|
+
) -> AgentGUI:
|
|
58
|
+
"""Generate an :class:`~baf.core.gui.agent_gui.AgentGUI` from a natural-language description.
|
|
59
|
+
|
|
60
|
+
The LLM is instructed via a system prompt to produce a JSON object conforming to
|
|
61
|
+
the AgentGUI JSON Schema. The JSON is then deserialized into a full
|
|
62
|
+
:class:`~baf.core.gui.agent_gui.AgentGUI` instance. If the first response fails to
|
|
63
|
+
parse or deserialize, the error is fed back to the LLM and the call is retried up to
|
|
64
|
+
*max_retries* times.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
llm (LLM): any BAF :class:`~baf.nlp.llm.llm.LLM` instance with a ``predict`` method.
|
|
68
|
+
prompt (str): natural-language description of the GUI to generate (e.g.
|
|
69
|
+
``"A login form with email, password fields and a Submit button."``).
|
|
70
|
+
gui_id (str | None): optional identifier forwarded to the returned
|
|
71
|
+
:class:`~baf.core.gui.agent_gui.AgentGUI`. A random UUID is used when
|
|
72
|
+
``None`` (default).
|
|
73
|
+
max_retries (int): number of correction attempts when the LLM returns invalid or
|
|
74
|
+
non-deserializable JSON. Defaults to ``2``.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
AgentGUI | None: the generated GUI model, or ``None`` if generation failed after
|
|
78
|
+
all retries.
|
|
79
|
+
|
|
80
|
+
Example::
|
|
81
|
+
|
|
82
|
+
from baf.core.gui.gui_llm import create_gui_with_llm
|
|
83
|
+
|
|
84
|
+
gui = create_gui_with_llm(
|
|
85
|
+
llm=gpt,
|
|
86
|
+
prompt="A dashboard with a line chart and two metric cards.",
|
|
87
|
+
)
|
|
88
|
+
if gui is not None:
|
|
89
|
+
session.set_gui(gui)
|
|
90
|
+
"""
|
|
91
|
+
system_prompt = _build_system_prompt()
|
|
92
|
+
current_prompt = prompt
|
|
93
|
+
last_error: Exception | None = None
|
|
94
|
+
|
|
95
|
+
for attempt in range(1 + max_retries):
|
|
96
|
+
raw = llm.predict(current_prompt, system_message=system_prompt)
|
|
97
|
+
try:
|
|
98
|
+
gui = json_to_gui(_extract_json(raw), gui_id=gui_id)
|
|
99
|
+
if attempt > 0:
|
|
100
|
+
logger.info(f"create_gui_with_llm: succeeded on attempt {attempt + 1}.")
|
|
101
|
+
return gui
|
|
102
|
+
except Exception as exc:
|
|
103
|
+
last_error = exc
|
|
104
|
+
if attempt < max_retries:
|
|
105
|
+
logger.warning(
|
|
106
|
+
f"create_gui_with_llm: attempt {attempt + 1} failed — {exc}. Retrying..."
|
|
107
|
+
)
|
|
108
|
+
current_prompt = _RETRY_PROMPT_TEMPLATE.format(error=exc, prompt=prompt)
|
|
109
|
+
else:
|
|
110
|
+
logger.warning(
|
|
111
|
+
f"create_gui_with_llm: attempt {attempt + 1} failed — {exc}. No more retries."
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
logger.error(
|
|
115
|
+
f"create_gui_with_llm: could not generate a valid GUI after {1 + max_retries} "
|
|
116
|
+
f"attempt(s). Last error: {last_error}"
|
|
117
|
+
)
|
|
118
|
+
return None
|