springbootAI 2.3.10__tar.gz → 2.3.11__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.
- {springbootai-2.3.10 → springbootai-2.3.11}/CHANGELOG.md +10 -0
- {springbootai-2.3.10/springbootAI.egg-info → springbootai-2.3.11}/PKG-INFO +8 -7
- {springbootai-2.3.10 → springbootai-2.3.11}/README.md +5 -5
- {springbootai-2.3.10 → springbootai-2.3.11}/pyproject.toml +41 -3
- springbootai-2.3.11/requirements-ai.txt +44 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/requirements.txt +1 -6
- {springbootai-2.3.10 → springbootai-2.3.11/springbootAI.egg-info}/PKG-INFO +8 -7
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootAI.egg-info/SOURCES.txt +6 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootAI.egg-info/requires.txt +1 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/__init__.py +4 -3
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/advisors.py +102 -10
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/annotation_runtime.py +138 -18
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/annotations.py +26 -4
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/autoconfig.py +95 -14
- springbootai-2.3.11/springbootai/ai/core.py +1076 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/memory.py +79 -15
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/observability.py +5 -3
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/providers.py +211 -49
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/resilience.py +186 -8
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/tools.py +268 -20
- springbootai-2.3.11/springbootai/ai/vectorstore.py +719 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/cache.py +2 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/core.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/aop/cloud_aop.py +62 -4
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/aop/comprehensive_aop.py +264 -129
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cli/scaffold.py +5 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/__init__.py +3 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/bus.py +226 -59
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/discovery.py +39 -21
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/feign.py +28 -2
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/gateway.py +328 -108
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/nacos_config.py +6 -2
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/tracer.py +103 -56
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/config/binding.py +3 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/config/spring-configuration-metadata.json +25 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/context/application_context.py +20 -5
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/context/bean_factory.py +185 -140
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/core/graceful_shutdown.py +3 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/csv/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/data/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/data/repository.py +113 -27
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/datasource/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/datasource/dynamic.py +5 -1
- springbootai-2.3.11/springbootai/event/publisher.py +103 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/adapters.py +6 -2
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/autoconfig.py +10 -4
- springbootai-2.3.11/springbootai/langchain/loaders/loaders.py +440 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/partners.py +3 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/tools/tools.py +32 -4
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langgraph/autoconfig.py +10 -4
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langgraph/config.py +36 -3
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langgraph/runtime.py +292 -51
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/logging/context.py +8 -3
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/main.py +28 -17
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/mcp/autoconfig.py +3 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/mcp/client.py +295 -38
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/mcp/config.py +37 -0
- springbootai-2.3.11/springbootai/messaging/kafka.py +552 -0
- springbootai-2.3.11/springbootai/messaging/rabbitmq.py +925 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/monitoring/prometheus.py +24 -7
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/__init__.py +2 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/database.py +190 -50
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/migration.py +328 -222
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/mybatis_integration.py +3 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/__init__.py +4 -3
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/cache/redis_cache.py +226 -160
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/circuit_breaker/circuit_breaker.py +73 -23
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/configuration.py +3 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/core/sql_session.py +1003 -24
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/dynamic_sql/dynamic_sql.py +6 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/pool/connection_pool.py +29 -86
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/security/__init__.py +7 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/security/access_control.py +120 -47
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/security/sql_injection_detector.py +35 -10
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/transaction/transaction.py +41 -7
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/version.py +1 -1
- springbootai-2.3.11/springbootai/py.typed +1 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/retry/retry_decorator.py +55 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/scheduling/scheduler.py +230 -125
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/security/jwt_utils.py +2 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/security/oauth2.py +141 -35
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/security/replay_protection.py +94 -26
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/test/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/tx/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/tx/events.py +28 -2
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/tx/synchronization.py +34 -13
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/utils/banner.py +2 -2
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/utils/redis_client.py +123 -68
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/validation/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/actuator.py +140 -47
- springbootai-2.3.11/springbootai/web/exception_handler.py +101 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/health.py +108 -88
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/interceptor.py +33 -15
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/request_metrics.py +23 -5
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/swagger.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/web_context.py +149 -12
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/websocket/__init__.py +1 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/websocket/broker.py +108 -16
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/websocket/handler.py +8 -4
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/websocket/router.py +207 -20
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/websocket/session.py +92 -39
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_actuator_prometheus_admin.py +12 -8
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ai_comprehensive.py +105 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ai_module.py +42 -7
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ai_stream_hardening.py +59 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_cloud_embedded_full.py +32 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_config_fixes_185.py +24 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_di_config_event_full.py +32 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_enterprise_safety_regressions.py +68 -0
- springbootai-2.3.11/tests/test_final_enterprise_hardening.py +452 -0
- springbootai-2.3.11/tests/test_followup_enterprise_fixes.py +422 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_io_http_logging_hardening.py +153 -5
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_langchain_comprehensive.py +3 -1
- springbootai-2.3.11/tests/test_latest_enterprise_audit_fixes.py +267 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_mcp_module.py +52 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_oauth2.py +36 -1
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_optional_component_timeouts.py +95 -5
- springbootai-2.3.11/tests/test_post_audit_enterprise_fixes.py +425 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_production_readiness.py +4 -3
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_pymybatis_contract.py +37 -0
- springbootai-2.3.11/tests/test_remaining_enterprise_hardening.py +684 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_scheduling.py +25 -12
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_security.py +3 -2
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_security_full.py +12 -5
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_websocket_module.py +40 -2
- springbootai-2.3.10/requirements-ai.txt +0 -50
- springbootai-2.3.10/springbootai/ai/core.py +0 -526
- springbootai-2.3.10/springbootai/ai/vectorstore.py +0 -428
- springbootai-2.3.10/springbootai/event/publisher.py +0 -69
- springbootai-2.3.10/springbootai/langchain/loaders/loaders.py +0 -207
- springbootai-2.3.10/springbootai/messaging/kafka.py +0 -275
- springbootai-2.3.10/springbootai/messaging/rabbitmq.py +0 -506
- springbootai-2.3.10/springbootai/web/exception_handler.py +0 -60
- {springbootai-2.3.10 → springbootai-2.3.11}/LICENSE +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/MANIFEST.in +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/SECURITY.md +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/requirements-langgraph.txt +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/requirements-mcp.txt +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/setup.cfg +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/setup.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootAI.egg-info/dependency_links.txt +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootAI.egg-info/entry_points.txt +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootAI.egg-info/top_level.txt +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/ai/etl.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/batch.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/cloud.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/conditional.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/data.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/enterprise.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/langchain.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/langgraph.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/lombok.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/messaging.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/annotations/security.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/aop/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/aop/aspect.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/aop/method_interceptor.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/aop/proxy_factory.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/batch/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cli/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cli/main.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/config_center.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/load_balancer.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/seata.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/seata_at_proxy.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/seata_bridge.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/sentinel.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/cloud/transaction_store.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/config/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/config/config_loader.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/config/config_monitor.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/context/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/context/bean_definition.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/context/lifecycle.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/context/registry.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/context/scanner.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/core/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/core/typing_utils.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/csv/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/csv/converters.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/csv/easy_csv.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/csv/exceptions.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/csv/reader.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/csv/writer.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/data/page.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/data/rest.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/data/specification.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/datasource/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/datasource/context.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/devtools.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/event/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/converters.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/easy_excel.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/exceptions.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/reader.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/style.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/excel/writer.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/accessor.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/auto_config.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/holder.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/locale.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/locale_resolver.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/message_source.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/middleware.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/properties.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/i18n/sources.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/agents/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/agents/services.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/callbacks/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/callbacks/handlers.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/chains/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/chains/services.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/core.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/indexes/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/indexes/index.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/loaders/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/memory/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/memory/memory.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/parsers/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/parsers/parsers.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/prompts/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/prompts/templates.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/retrievers/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/retrievers/retrievers.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/tools/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/utilities/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/utilities/utils.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/vectorstores/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langchain/vectorstores/stores.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langgraph/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langgraph/annotation_runtime.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langgraph/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/langgraph/checkpoint.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/logging/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/logging/loguru_logger.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/mcp/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/mcp/annotation_runtime.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/mcp/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/mcp/server.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/messaging/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/monitoring/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/monitoring/admin_client.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/ddl_auto.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/annotations/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/annotations/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/cache/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/cache/cache.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/circuit_breaker/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/core/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/core/sql_session_factory.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/dialect/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/dialect/dialect.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/dynamic_sql/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/interceptor/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/interceptor/interceptor.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/mapper/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/mapper/mapper.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/metrics/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/metrics/metrics.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/pool/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/security/password_encoder.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/security/sensitive_data_masker.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/transaction/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/type_handler/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/type_handler/type_handler.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/xml_parser/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/orm/pymybatis/xml_parser/xml_parser.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/retry/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/retry/recovery.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/retry/retry_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/scheduling/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/security/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/security/secret_manager.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/security/security_aop.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/security/security_context.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/test/slicing.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/tracing/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/tracing/skywalking.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/utils/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/utils/bean_utils.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/utils/logger.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/validation/aop.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/validation/constraints.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/validation/exceptions.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/validation/validator.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/__init__.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/csrf.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/hateoas.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/web/result.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/websocket/annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/springbootai/websocket/exceptions.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/sql/seata_undo_log.sql +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_actuator.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ai_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ai_declarative_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ai_enterprise_hardening.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_annotation_combinations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_annotations_contract.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_aop_annotations_full.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_aop_pointcut_enhancements.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_audit_time.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_batch.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_bean_utils.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_bus.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_cache_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_cli.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_cloud_log_safety.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_component_init_error.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_compositional_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_conditional_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_config_admin_hardening.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_config_binding.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_config_center.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_config_center_hardening.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_config_monitor.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_connection_resilience.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_core.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_core_annotations_full.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_csrf.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_csv_module.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_data_repository.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_data_rest.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_datasource_routing.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ddl_auto.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_declarative_aop_post_authorize_recover.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_devtools.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_devtools_lifecycle_hardening.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_excel_module.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_hateoas.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_i18n_module.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_ioc_lifecycle_enhancements.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_jpa_version_transient.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_kafka.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_langchain_ext.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_langchain_module.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_langgraph_comprehensive.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_langgraph_module.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_logging_config.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_lombok_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_metadata.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_migration.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_nacos_config.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_new_annotations.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_new_features.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_orm_pymybatis_full.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_pymybatis_configuration_hardening.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_request_metrics.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_retry.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_runtime_configuration_fixes.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_scaffold_hardening.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_seata_at_proxy.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_seata_bridge.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_seata_durable_store.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_security_hardening.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_select_page.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_starter.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_startup_lifecycle.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_swagger_module.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_test_slicing.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_tracing.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_transactional_events.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_validation_module.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_web_annotations_full.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_web_file_upload.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_web_root_mapping.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_web_security_responses.py +0 -0
- {springbootai-2.3.10 → springbootai-2.3.11}/tests/test_web_static_files.py +0 -0
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.3.11] - 2026-09-01
|
|
4
|
+
|
|
5
|
+
- 修复 PyMyBatis 访问控制仅覆盖查询、行级条件直接拼接及 SQL 尾部条件位置错误,写操作和字段权限现在失败关闭,动态租户值必须使用绑定参数。
|
|
6
|
+
- 修复事务提交前监听器异常被吞掉及 `REQUIRES_NEW`/`NOT_SUPPORTED` 同步上下文错误,提交否决会触发回滚并恢复外层上下文。
|
|
7
|
+
- 修复 Spring Cloud Bus RabbitMQ API 调用错误和缺失消费者,增加 Broker 确认、广播消费者、去重、消息大小限制及明确的失败状态。
|
|
8
|
+
- 加固 MCP/AI 工具边界:限制 HTTP 响应、队列、集合和 Schema 深度,拒绝压缩炸弹及高风险正则表达式。
|
|
9
|
+
- 修复 Prometheus Summary 创建失败、Tracer 已结束 Span 无界增长以及 Actuator/启动日志暴露原始异常的问题。
|
|
10
|
+
- 修复 CI 在 AI 测试切片后提前执行总覆盖率门槛的问题,覆盖率阈值现在只在全部测试切片完成后统一校验。
|
|
11
|
+
- 修复 LangChain 完整演示未声明文档加载根目录的问题,并为临时文件自动清理及 Windows 重定向控制台增加 UTF-8 输出兼容。
|
|
12
|
+
|
|
3
13
|
## [2.3.10] - 2026-08-29
|
|
4
14
|
|
|
5
15
|
- 修复 AI 代理上下游消息被 SQL 注入检测误报:`#{...}` 绑定值始终按数据处理,不再扫描消息内容;`${...}` 原始替换仍默认拒绝,只有配置允许且值完整匹配严格白名单时才能使用。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: springbootAI
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.11
|
|
4
4
|
Summary: Spring-style Python framework with Web, ORM, Cloud and AI integrations
|
|
5
5
|
Author-email: YuConggen <1516933915@qq.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
20
20
|
Classifier: Topic :: Database
|
|
21
21
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
22
|
-
Requires-Python:
|
|
22
|
+
Requires-Python: <3.13,>=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: fastapi==0.141.1
|
|
@@ -120,6 +120,7 @@ Requires-Dist: psutil==6.1.1; extra == "all"
|
|
|
120
120
|
Provides-Extra: dev
|
|
121
121
|
Requires-Dist: pytest==9.1.1; extra == "dev"
|
|
122
122
|
Requires-Dist: pytest-cov==7.1.0; extra == "dev"
|
|
123
|
+
Requires-Dist: mypy==1.18.2; extra == "dev"
|
|
123
124
|
Requires-Dist: redis==8.1.0; extra == "dev"
|
|
124
125
|
Requires-Dist: sqlglot==27.28.1; extra == "dev"
|
|
125
126
|
Provides-Extra: full
|
|
@@ -218,7 +219,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
|
|
|
218
219
|
| AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
|
|
219
220
|
| 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
|
|
220
221
|
|
|
221
|
-
当前版本是 `2.3.
|
|
222
|
+
当前版本是 `2.3.11`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 是无 TC 全局锁的单进程受限补偿模式,不应当作跨服务强一致方案。
|
|
222
223
|
|
|
223
224
|
[新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
|
|
224
225
|
|
|
@@ -349,10 +350,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
|
|
|
349
350
|
|
|
350
351
|
| 组件 | 当前版本 |
|
|
351
352
|
|------|----------|
|
|
352
|
-
| `springbootai` 框架 API | 2.3.
|
|
353
|
-
| `springbootai.orm.pymybatis` | 2.3.
|
|
354
|
-
| `springbootai.ai` AI 模块 | 2.3.
|
|
355
|
-
| `springbootai.langchain` LangChain 模块 | 2.3.
|
|
353
|
+
| `springbootai` 框架 API | 2.3.11 |
|
|
354
|
+
| `springbootai.orm.pymybatis` | 2.3.11 |
|
|
355
|
+
| `springbootai.ai` AI 模块 | 2.3.11 |
|
|
356
|
+
| `springbootai.langchain` LangChain 模块 | 2.3.11 |
|
|
356
357
|
| Python | 3.10+ |
|
|
357
358
|
|
|
358
359
|
### 1.4 适合什么场景
|
|
@@ -56,7 +56,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
|
|
|
56
56
|
| AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
|
|
57
57
|
| 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
|
|
58
58
|
|
|
59
|
-
当前版本是 `2.3.
|
|
59
|
+
当前版本是 `2.3.11`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 是无 TC 全局锁的单进程受限补偿模式,不应当作跨服务强一致方案。
|
|
60
60
|
|
|
61
61
|
[新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
|
|
62
62
|
|
|
@@ -187,10 +187,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
|
|
|
187
187
|
|
|
188
188
|
| 组件 | 当前版本 |
|
|
189
189
|
|------|----------|
|
|
190
|
-
| `springbootai` 框架 API | 2.3.
|
|
191
|
-
| `springbootai.orm.pymybatis` | 2.3.
|
|
192
|
-
| `springbootai.ai` AI 模块 | 2.3.
|
|
193
|
-
| `springbootai.langchain` LangChain 模块 | 2.3.
|
|
190
|
+
| `springbootai` 框架 API | 2.3.11 |
|
|
191
|
+
| `springbootai.orm.pymybatis` | 2.3.11 |
|
|
192
|
+
| `springbootai.ai` AI 模块 | 2.3.11 |
|
|
193
|
+
| `springbootai.langchain` LangChain 模块 | 2.3.11 |
|
|
194
194
|
| Python | 3.10+ |
|
|
195
195
|
|
|
196
196
|
### 1.4 适合什么场景
|
|
@@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"
|
|
|
12
12
|
[project]
|
|
13
13
|
# Distribution name: springbootAI (pip install springbootAI); import package: springbootai.
|
|
14
14
|
name = "springbootAI"
|
|
15
|
-
version = "2.3.
|
|
15
|
+
version = "2.3.11"
|
|
16
16
|
description = "Spring-style Python framework with Web, ORM, Cloud and AI integrations"
|
|
17
17
|
readme = "README.md"
|
|
18
18
|
license = "MIT"
|
|
@@ -32,7 +32,7 @@ classifiers = [
|
|
|
32
32
|
"Topic :: Database",
|
|
33
33
|
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
|
34
34
|
]
|
|
35
|
-
requires-python = ">=3.10"
|
|
35
|
+
requires-python = ">=3.10,<3.13"
|
|
36
36
|
|
|
37
37
|
# ========================================
|
|
38
38
|
# 核心依赖——类似 Spring Boot Starter Web/Core
|
|
@@ -199,6 +199,7 @@ all = [
|
|
|
199
199
|
dev = [
|
|
200
200
|
"pytest==9.1.1",
|
|
201
201
|
"pytest-cov==7.1.0",
|
|
202
|
+
"mypy==1.18.2",
|
|
202
203
|
"redis==8.1.0",
|
|
203
204
|
"sqlglot==27.28.1",
|
|
204
205
|
]
|
|
@@ -278,6 +279,43 @@ markers = [
|
|
|
278
279
|
"seata_integration: requires a compatible Seata SDK and real Seata Server",
|
|
279
280
|
]
|
|
280
281
|
|
|
282
|
+
[tool.coverage.run]
|
|
283
|
+
branch = true
|
|
284
|
+
source = ["springbootai"]
|
|
285
|
+
|
|
286
|
+
[tool.coverage.report]
|
|
287
|
+
fail_under = 68
|
|
288
|
+
show_missing = true
|
|
289
|
+
|
|
290
|
+
[tool.mypy]
|
|
291
|
+
python_version = "3.10"
|
|
292
|
+
files = [
|
|
293
|
+
"springbootai/ai/annotation_runtime.py",
|
|
294
|
+
"springbootai/ai/advisors.py",
|
|
295
|
+
"springbootai/ai/vectorstore.py",
|
|
296
|
+
"springbootai/cloud/gateway.py",
|
|
297
|
+
"springbootai/websocket/router.py",
|
|
298
|
+
"springbootai/messaging/kafka.py",
|
|
299
|
+
"springbootai/messaging/rabbitmq.py",
|
|
300
|
+
"springbootai/data/repository.py",
|
|
301
|
+
"springbootai/retry/retry_decorator.py",
|
|
302
|
+
"springbootai/ai/tools.py",
|
|
303
|
+
"springbootai/cloud/bus.py",
|
|
304
|
+
"springbootai/cloud/tracer.py",
|
|
305
|
+
"springbootai/mcp/client.py",
|
|
306
|
+
"springbootai/mcp/config.py",
|
|
307
|
+
"springbootai/monitoring/prometheus.py",
|
|
308
|
+
"springbootai/orm/pymybatis/core/sql_session.py",
|
|
309
|
+
"springbootai/orm/pymybatis/security/access_control.py",
|
|
310
|
+
"springbootai/tx/synchronization.py",
|
|
311
|
+
]
|
|
312
|
+
ignore_missing_imports = true
|
|
313
|
+
follow_imports = "skip"
|
|
314
|
+
allow_untyped_defs = true
|
|
315
|
+
allow_incomplete_defs = true
|
|
316
|
+
check_untyped_defs = true
|
|
317
|
+
show_error_codes = true
|
|
318
|
+
|
|
281
319
|
[project.urls]
|
|
282
320
|
Homepage = "https://github.com/YUCONGGEN/springbootAI"
|
|
283
321
|
Repository = "https://github.com/YUCONGGEN/springbootAI.git"
|
|
@@ -296,4 +334,4 @@ include = ["springbootai*"]
|
|
|
296
334
|
namespaces = false
|
|
297
335
|
|
|
298
336
|
[tool.setuptools.package-data]
|
|
299
|
-
springbootai = ["*.py", "**/*.py", "**/*.xml", "**/*.yml", "**/*.yaml"]
|
|
337
|
+
springbootai = ["*.py", "py.typed", "**/*.py", "**/*.xml", "**/*.yml", "**/*.yaml"]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# ========================================
|
|
2
|
+
# SpringBootAI optional AI/LangChain dependencies (exact versions)
|
|
3
|
+
# ========================================
|
|
4
|
+
# The AI module uses optional dependencies with a built-in fallback:
|
|
5
|
+
# - Without this file, native HTTP providers and FakeChatModel remain usable.
|
|
6
|
+
# - Installing it enables LangChain adapters detected by ai/providers.py.
|
|
7
|
+
#
|
|
8
|
+
# Install examples:
|
|
9
|
+
# pip install -r requirements-ai.txt
|
|
10
|
+
# pip install langchain-openai==1.4.2
|
|
11
|
+
#
|
|
12
|
+
# Recommended Python: 3.10+ (CI covers 3.10, 3.11 and 3.12).
|
|
13
|
+
# Every pinned version is covered by tests and dependency auditing.
|
|
14
|
+
# Keep this file ASCII-only: pip-audit may use the Windows system encoding.
|
|
15
|
+
# ========================================
|
|
16
|
+
|
|
17
|
+
# LangChain core (BaseChatModel, Embeddings and Runnable APIs).
|
|
18
|
+
langchain-core==1.5.4
|
|
19
|
+
|
|
20
|
+
# Classic APIs including LLMChain, ConversationChain and initialize_agent.
|
|
21
|
+
langchain-classic==1.0.8
|
|
22
|
+
|
|
23
|
+
# OpenAI-compatible providers (OpenAI, Azure, DeepSeek and Moonshot).
|
|
24
|
+
langchain-openai==1.4.2
|
|
25
|
+
|
|
26
|
+
# RecursiveCharacterTextSplitter and CharacterTextSplitter.
|
|
27
|
+
langchain-text-splitters==1.1.2
|
|
28
|
+
|
|
29
|
+
# Community integrations including FAISS, Chroma, DuckDuckGo and Wikipedia.
|
|
30
|
+
langchain-community==0.4.2
|
|
31
|
+
|
|
32
|
+
# Vector similarity calculations; 2.2.6 retains Python 3.10 compatibility.
|
|
33
|
+
numpy==2.2.6
|
|
34
|
+
|
|
35
|
+
# Pydantic v2 for validation and structured output parsing.
|
|
36
|
+
pydantic==2.13.4
|
|
37
|
+
|
|
38
|
+
# ========================================
|
|
39
|
+
# Additional optional packages (install only when needed)
|
|
40
|
+
# ========================================
|
|
41
|
+
|
|
42
|
+
# Vector database: faiss-cpu
|
|
43
|
+
# PDF document loading: pypdf
|
|
44
|
+
# HTML parsing: beautifulsoup4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: springbootAI
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.11
|
|
4
4
|
Summary: Spring-style Python framework with Web, ORM, Cloud and AI integrations
|
|
5
5
|
Author-email: YuConggen <1516933915@qq.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
20
20
|
Classifier: Topic :: Database
|
|
21
21
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
22
|
-
Requires-Python:
|
|
22
|
+
Requires-Python: <3.13,>=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: fastapi==0.141.1
|
|
@@ -120,6 +120,7 @@ Requires-Dist: psutil==6.1.1; extra == "all"
|
|
|
120
120
|
Provides-Extra: dev
|
|
121
121
|
Requires-Dist: pytest==9.1.1; extra == "dev"
|
|
122
122
|
Requires-Dist: pytest-cov==7.1.0; extra == "dev"
|
|
123
|
+
Requires-Dist: mypy==1.18.2; extra == "dev"
|
|
123
124
|
Requires-Dist: redis==8.1.0; extra == "dev"
|
|
124
125
|
Requires-Dist: sqlglot==27.28.1; extra == "dev"
|
|
125
126
|
Provides-Extra: full
|
|
@@ -218,7 +219,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
|
|
|
218
219
|
| AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
|
|
219
220
|
| 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
|
|
220
221
|
|
|
221
|
-
当前版本是 `2.3.
|
|
222
|
+
当前版本是 `2.3.11`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 是无 TC 全局锁的单进程受限补偿模式,不应当作跨服务强一致方案。
|
|
222
223
|
|
|
223
224
|
[新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
|
|
224
225
|
|
|
@@ -349,10 +350,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
|
|
|
349
350
|
|
|
350
351
|
| 组件 | 当前版本 |
|
|
351
352
|
|------|----------|
|
|
352
|
-
| `springbootai` 框架 API | 2.3.
|
|
353
|
-
| `springbootai.orm.pymybatis` | 2.3.
|
|
354
|
-
| `springbootai.ai` AI 模块 | 2.3.
|
|
355
|
-
| `springbootai.langchain` LangChain 模块 | 2.3.
|
|
353
|
+
| `springbootai` 框架 API | 2.3.11 |
|
|
354
|
+
| `springbootai.orm.pymybatis` | 2.3.11 |
|
|
355
|
+
| `springbootai.ai` AI 模块 | 2.3.11 |
|
|
356
|
+
| `springbootai.langchain` LangChain 模块 | 2.3.11 |
|
|
356
357
|
| Python | 3.10+ |
|
|
357
358
|
|
|
358
359
|
### 1.4 适合什么场景
|
|
@@ -18,6 +18,7 @@ springbootAI.egg-info/top_level.txt
|
|
|
18
18
|
springbootai/__init__.py
|
|
19
19
|
springbootai/devtools.py
|
|
20
20
|
springbootai/main.py
|
|
21
|
+
springbootai/py.typed
|
|
21
22
|
springbootai/ai/__init__.py
|
|
22
23
|
springbootai/ai/advisors.py
|
|
23
24
|
springbootai/ai/annotation_runtime.py
|
|
@@ -306,6 +307,8 @@ tests/test_devtools_lifecycle_hardening.py
|
|
|
306
307
|
tests/test_di_config_event_full.py
|
|
307
308
|
tests/test_enterprise_safety_regressions.py
|
|
308
309
|
tests/test_excel_module.py
|
|
310
|
+
tests/test_final_enterprise_hardening.py
|
|
311
|
+
tests/test_followup_enterprise_fixes.py
|
|
309
312
|
tests/test_hateoas.py
|
|
310
313
|
tests/test_i18n_module.py
|
|
311
314
|
tests/test_io_http_logging_hardening.py
|
|
@@ -317,6 +320,7 @@ tests/test_langchain_ext.py
|
|
|
317
320
|
tests/test_langchain_module.py
|
|
318
321
|
tests/test_langgraph_comprehensive.py
|
|
319
322
|
tests/test_langgraph_module.py
|
|
323
|
+
tests/test_latest_enterprise_audit_fixes.py
|
|
320
324
|
tests/test_logging_config.py
|
|
321
325
|
tests/test_lombok_annotations.py
|
|
322
326
|
tests/test_mcp_module.py
|
|
@@ -328,9 +332,11 @@ tests/test_new_features.py
|
|
|
328
332
|
tests/test_oauth2.py
|
|
329
333
|
tests/test_optional_component_timeouts.py
|
|
330
334
|
tests/test_orm_pymybatis_full.py
|
|
335
|
+
tests/test_post_audit_enterprise_fixes.py
|
|
331
336
|
tests/test_production_readiness.py
|
|
332
337
|
tests/test_pymybatis_configuration_hardening.py
|
|
333
338
|
tests/test_pymybatis_contract.py
|
|
339
|
+
tests/test_remaining_enterprise_hardening.py
|
|
334
340
|
tests/test_request_metrics.py
|
|
335
341
|
tests/test_retry.py
|
|
336
342
|
tests/test_runtime_configuration_fixes.py
|
|
@@ -16,7 +16,8 @@ SpringBootAI AI 模块 - 对齐 Spring AI 的 ChatClient/Advisor/ETL 抽象,
|
|
|
16
16
|
from springbootai.ai.core import (
|
|
17
17
|
Advisor, AdvisorRequest, ChatClient, ChatClientBuilder, ChatModel,
|
|
18
18
|
ChatResponse, EmbeddingModel, Generation, Message, MessageType,
|
|
19
|
-
PromptSpec,
|
|
19
|
+
PromptSpec, AIConcurrencyLimitError, TokenBudgetExceededError,
|
|
20
|
+
ToolLoopLimitExceededError,
|
|
20
21
|
)
|
|
21
22
|
from springbootai.ai.annotations import (
|
|
22
23
|
Agent, AiAdvisor, AiCache, AiClient, AiMemory, AiRetry, ContentModeration,
|
|
@@ -57,14 +58,14 @@ from springbootai.ai.observability import AIMetrics, ai_metrics
|
|
|
57
58
|
from springbootai.ai.autoconfig import AIProperties, bind_ai_config, configure_ai
|
|
58
59
|
from springbootai.ai.annotation_runtime import ContentModerationError
|
|
59
60
|
|
|
60
|
-
__version__ = "2.3.
|
|
61
|
+
__version__ = "2.3.11"
|
|
61
62
|
|
|
62
63
|
__all__ = [
|
|
63
64
|
# core
|
|
64
65
|
"Advisor", "AdvisorRequest", "ChatClient", "ChatClientBuilder",
|
|
65
66
|
"ChatModel", "ChatResponse", "EmbeddingModel", "Generation", "Message",
|
|
66
67
|
"MessageType", "PromptSpec", "TokenBudgetExceededError",
|
|
67
|
-
"ToolLoopLimitExceededError",
|
|
68
|
+
"ToolLoopLimitExceededError", "AIConcurrencyLimitError",
|
|
68
69
|
# annotations
|
|
69
70
|
"AiAdvisor", "AiClient", "AiMemory", "Tool", "Prompt", "RAG",
|
|
70
71
|
"StructuredOutput", "Agent", "Embedding", "VectorStore", "AiRetry",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Advisor 实现 - QuestionAnswerAdvisor(RAG)与 MessageChatMemoryAdvisor(会话记忆)。
|
|
3
3
|
"""
|
|
4
4
|
import inspect
|
|
5
|
+
import hashlib
|
|
5
6
|
from urllib.parse import quote
|
|
6
7
|
from typing import Any, Dict, List, Optional, Sequence
|
|
7
8
|
|
|
@@ -27,8 +28,14 @@ class MessageChatMemoryAdvisor(Advisor):
|
|
|
27
28
|
|
|
28
29
|
@staticmethod
|
|
29
30
|
def _build_namespace(context: dict) -> str:
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
def identity_part(value: Any) -> str:
|
|
32
|
+
raw = str(value or "").strip()
|
|
33
|
+
if len(raw) > 128:
|
|
34
|
+
raw = "sha256-" + hashlib.sha256(raw.encode("utf-8")).hexdigest()
|
|
35
|
+
return quote(raw, safe="-_.~")
|
|
36
|
+
|
|
37
|
+
tenant = identity_part(context.get("tenant_id", ""))
|
|
38
|
+
user = identity_part(context.get("user_id", ""))
|
|
32
39
|
parts = [p for p in (tenant, user) if p]
|
|
33
40
|
return ":".join(parts) if parts else ""
|
|
34
41
|
|
|
@@ -52,9 +59,17 @@ class MessageChatMemoryAdvisor(Advisor):
|
|
|
52
59
|
kwargs["namespace"] = namespace
|
|
53
60
|
return method(*args, **kwargs)
|
|
54
61
|
|
|
55
|
-
def __init__(self, memory: ChatMemory, max_messages: int = 20
|
|
62
|
+
def __init__(self, memory: ChatMemory, max_messages: int = 20,
|
|
63
|
+
allow_global_namespace: bool = False):
|
|
64
|
+
if isinstance(max_messages, bool) or not isinstance(max_messages, int):
|
|
65
|
+
raise TypeError("max_messages must be an integer")
|
|
66
|
+
if not 1 <= max_messages <= 100_000:
|
|
67
|
+
raise ValueError("max_messages must be in [1, 100000]")
|
|
68
|
+
if not isinstance(allow_global_namespace, bool):
|
|
69
|
+
raise TypeError("allow_global_namespace must be a boolean")
|
|
56
70
|
self.memory = memory
|
|
57
71
|
self.max_messages = max_messages
|
|
72
|
+
self.allow_global_namespace = allow_global_namespace
|
|
58
73
|
|
|
59
74
|
def advise_request(self, request: AdvisorRequest) -> AdvisorRequest:
|
|
60
75
|
conv_id = request.context.get("conversation_id")
|
|
@@ -69,6 +84,14 @@ class MessageChatMemoryAdvisor(Advisor):
|
|
|
69
84
|
# Namespace is passed per operation. Never mutate a shared memory bean:
|
|
70
85
|
# concurrent requests may belong to different tenants.
|
|
71
86
|
ns = self._build_namespace(request.context)
|
|
87
|
+
if not ns and not self.allow_global_namespace:
|
|
88
|
+
request.context["memory_disabled"] = True
|
|
89
|
+
logger = __import__("logging").getLogger("Spring.AI")
|
|
90
|
+
logger.debug(
|
|
91
|
+
"MessageChatMemoryAdvisor: authenticated tenant/user identity "
|
|
92
|
+
"is missing; skipping global memory access")
|
|
93
|
+
return request
|
|
94
|
+
request.context.pop("memory_disabled", None)
|
|
72
95
|
request.context["memory_namespace"] = ns
|
|
73
96
|
|
|
74
97
|
history = self._call_memory(
|
|
@@ -82,7 +105,7 @@ class MessageChatMemoryAdvisor(Advisor):
|
|
|
82
105
|
def advise_response(self, response: ChatResponse,
|
|
83
106
|
request: AdvisorRequest) -> ChatResponse:
|
|
84
107
|
conv_id = request.context.get("conversation_id")
|
|
85
|
-
if not conv_id:
|
|
108
|
+
if not conv_id or request.context.get("memory_disabled"):
|
|
86
109
|
return response
|
|
87
110
|
ns = str(request.context.get("memory_namespace") or
|
|
88
111
|
self._build_namespace(request.context))
|
|
@@ -120,7 +143,20 @@ class QuestionAnswerAdvisor(Advisor):
|
|
|
120
143
|
embedding_model=None,
|
|
121
144
|
harden_injection: bool = True,
|
|
122
145
|
filter_metadata: Optional[Dict[str, Any]] = None,
|
|
123
|
-
filter_context_keys: Sequence[str] = ("tenant_id",)
|
|
146
|
+
filter_context_keys: Sequence[str] = ("tenant_id",),
|
|
147
|
+
max_context_chars: int = 100_000,
|
|
148
|
+
max_document_chars: int = 25_000):
|
|
149
|
+
if isinstance(top_k, bool) or not isinstance(top_k, int):
|
|
150
|
+
raise TypeError("top_k must be an integer")
|
|
151
|
+
if not 1 <= top_k <= 1000:
|
|
152
|
+
raise ValueError("top_k must be in [1, 1000]")
|
|
153
|
+
for name, value in (
|
|
154
|
+
("max_context_chars", max_context_chars),
|
|
155
|
+
("max_document_chars", max_document_chars)):
|
|
156
|
+
if isinstance(value, bool) or not isinstance(value, int):
|
|
157
|
+
raise TypeError(f"{name} must be an integer")
|
|
158
|
+
if not 1 <= value <= 10_000_000:
|
|
159
|
+
raise ValueError(f"{name} must be in [1, 10000000]")
|
|
124
160
|
self.vector_store = vector_store
|
|
125
161
|
self.prompt_template = prompt_template or self.DEFAULT_PROMPT_TEMPLATE
|
|
126
162
|
self.top_k = top_k
|
|
@@ -128,6 +164,8 @@ class QuestionAnswerAdvisor(Advisor):
|
|
|
128
164
|
self.harden_injection = harden_injection
|
|
129
165
|
self.filter_metadata = dict(filter_metadata or {})
|
|
130
166
|
self.filter_context_keys = tuple(filter_context_keys)
|
|
167
|
+
self.max_context_chars = max_context_chars
|
|
168
|
+
self.max_document_chars = max_document_chars
|
|
131
169
|
|
|
132
170
|
def advise_request(self, request: AdvisorRequest) -> AdvisorRequest:
|
|
133
171
|
# 取最后一条用户消息作为查询
|
|
@@ -160,10 +198,49 @@ class QuestionAnswerAdvisor(Advisor):
|
|
|
160
198
|
filter_metadata=filters or None,
|
|
161
199
|
)
|
|
162
200
|
docs = self.vector_store.similarity_search(search_req)
|
|
201
|
+
# Missing identity must never become an implicit "all tenants" scope.
|
|
202
|
+
# Public documents (without tenant/user metadata) remain available for
|
|
203
|
+
# single-tenant and public-knowledge use cases.
|
|
204
|
+
identity_keys = set(self.filter_context_keys) | {"user_id"}
|
|
205
|
+
identity_scoped = any(key in filters for key in identity_keys)
|
|
206
|
+
if not identity_scoped:
|
|
207
|
+
docs = [
|
|
208
|
+
doc for doc in docs
|
|
209
|
+
if isinstance(doc.metadata, dict)
|
|
210
|
+
and not any(
|
|
211
|
+
doc.metadata.get(key) not in (None, "")
|
|
212
|
+
for key in identity_keys
|
|
213
|
+
)
|
|
214
|
+
]
|
|
163
215
|
if not docs:
|
|
164
216
|
return request
|
|
165
217
|
|
|
166
|
-
|
|
218
|
+
selected_docs = []
|
|
219
|
+
context_parts: List[str] = []
|
|
220
|
+
remaining = self.max_context_chars
|
|
221
|
+
truncated = False
|
|
222
|
+
separator = "\n---\n"
|
|
223
|
+
for doc in docs:
|
|
224
|
+
content = str(doc.content or "")
|
|
225
|
+
if len(content) > self.max_document_chars:
|
|
226
|
+
content = content[:self.max_document_chars]
|
|
227
|
+
truncated = True
|
|
228
|
+
separator_cost = len(separator) if context_parts else 0
|
|
229
|
+
available = remaining - separator_cost
|
|
230
|
+
if available <= 0:
|
|
231
|
+
truncated = True
|
|
232
|
+
break
|
|
233
|
+
if len(content) > available:
|
|
234
|
+
content = content[:available]
|
|
235
|
+
truncated = True
|
|
236
|
+
if not content:
|
|
237
|
+
continue
|
|
238
|
+
context_parts.append(content)
|
|
239
|
+
selected_docs.append(doc)
|
|
240
|
+
remaining -= separator_cost + len(content)
|
|
241
|
+
if not context_parts:
|
|
242
|
+
return request
|
|
243
|
+
context = separator.join(context_parts)
|
|
167
244
|
system_text = self.prompt_template.format(context=context)
|
|
168
245
|
if self.harden_injection:
|
|
169
246
|
# Prompt 注入加固:把外部文档与指令清晰隔离,并要求模型将上下文
|
|
@@ -179,8 +256,10 @@ class QuestionAnswerAdvisor(Advisor):
|
|
|
179
256
|
request.messages = new_messages
|
|
180
257
|
# 记录引用文档
|
|
181
258
|
request.context["retrieved_documents"] = [
|
|
182
|
-
{"id": d.id, "content": d.content[:200]}
|
|
259
|
+
{"id": d.id, "content": str(d.content)[:200]}
|
|
260
|
+
for d in selected_docs
|
|
183
261
|
]
|
|
262
|
+
request.context["retrieval_truncated"] = truncated
|
|
184
263
|
return request
|
|
185
264
|
|
|
186
265
|
|
|
@@ -190,11 +269,24 @@ class SimpleLoggerAdvisor(Advisor):
|
|
|
190
269
|
"""
|
|
191
270
|
order = 0
|
|
192
271
|
|
|
193
|
-
def __init__(self):
|
|
272
|
+
def __init__(self, max_events: int = 1000):
|
|
273
|
+
if isinstance(max_events, bool) or not isinstance(max_events, int) \
|
|
274
|
+
or max_events <= 0 or max_events > 100_000:
|
|
275
|
+
raise ValueError("max_events must be between 1 and 100000")
|
|
276
|
+
import threading
|
|
277
|
+
self.max_events = max_events
|
|
194
278
|
self.events: List[Dict[str, Any]] = []
|
|
279
|
+
self._events_lock = threading.RLock()
|
|
280
|
+
|
|
281
|
+
def _record(self, event: Dict[str, Any]) -> None:
|
|
282
|
+
with self._events_lock:
|
|
283
|
+
self.events.append(event)
|
|
284
|
+
overflow = len(self.events) - self.max_events
|
|
285
|
+
if overflow > 0:
|
|
286
|
+
del self.events[:overflow]
|
|
195
287
|
|
|
196
288
|
def advise_request(self, request: AdvisorRequest) -> AdvisorRequest:
|
|
197
|
-
self.
|
|
289
|
+
self._record({
|
|
198
290
|
"phase": "request",
|
|
199
291
|
"message_count": len(request.messages),
|
|
200
292
|
"tools": len(request.tool_registry.names())
|
|
@@ -204,7 +296,7 @@ class SimpleLoggerAdvisor(Advisor):
|
|
|
204
296
|
|
|
205
297
|
def advise_response(self, response: ChatResponse,
|
|
206
298
|
request: AdvisorRequest) -> ChatResponse:
|
|
207
|
-
self.
|
|
299
|
+
self._record({
|
|
208
300
|
"phase": "response",
|
|
209
301
|
"content_length": len(response.content()),
|
|
210
302
|
})
|