volcengine-python-sdk 4.0.16__py2.py3-none-any.whl → 4.0.18__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of volcengine-python-sdk might be problematic. Click here for more details.
- {volcengine_python_sdk-4.0.16.dist-info → volcengine_python_sdk-4.0.18.dist-info}/METADATA +1 -1
- {volcengine_python_sdk-4.0.16.dist-info → volcengine_python_sdk-4.0.18.dist-info}/RECORD +270 -141
- {volcengine_python_sdk-4.0.16.dist-info → volcengine_python_sdk-4.0.18.dist-info}/top_level.txt +1 -0
- volcenginesdkapig/__init__.py +52 -10
- volcenginesdkapig/api/apig_api.py +1489 -228
- volcenginesdkapig/models/__init__.py +52 -10
- volcenginesdkapig/models/apm_trace_spec_for_create_gateway_input.py +123 -0
- volcenginesdkapig/models/apm_trace_spec_for_get_gateway_output.py +95 -0
- volcenginesdkapig/models/apm_trace_spec_for_list_gateways_output.py +95 -0
- volcenginesdkapig/models/apm_trace_spec_for_update_gateway_trace_input.py +123 -0
- volcenginesdkapig/models/attach_gateway_lb_request.py +150 -0
- volcenginesdkapig/models/{tag_for_get_upstream_output.py → attach_gateway_lb_response.py} +20 -46
- volcenginesdkapig/models/create_custom_domain_request.py +255 -0
- volcenginesdkapig/models/create_custom_domain_response.py +123 -0
- volcenginesdkapig/models/create_gateway_request.py +17 -43
- volcenginesdkapig/models/create_upstream_request.py +1 -53
- volcenginesdkapig/models/create_upstream_version_request.py +150 -0
- volcenginesdkapig/models/create_upstream_version_response.py +149 -0
- volcenginesdkapig/models/custom_domain_for_get_custom_domain_output.py +357 -0
- volcenginesdkapig/models/delete_custom_domain_request.py +124 -0
- volcenginesdkapig/models/delete_custom_domain_response.py +95 -0
- volcenginesdkapig/models/delete_gateway_request.py +1 -27
- volcenginesdkapig/models/delete_upstream_version_request.py +151 -0
- volcenginesdkapig/models/delete_upstream_version_response.py +95 -0
- volcenginesdkapig20221112/models/tag_for_get_route_output.py → volcenginesdkapig/models/detach_gateway_lb_request.py +22 -47
- volcenginesdkapig/models/detach_gateway_lb_response.py +95 -0
- volcenginesdkapig/models/domain_spec_for_get_gateway_service_output.py +123 -0
- volcenginesdkapig/models/domain_spec_for_list_gateway_services_output.py +123 -0
- volcenginesdkapig/models/domain_spec_for_update_gateway_service_input.py +123 -0
- volcenginesdkapig/models/filter_for_list_gateways_input.py +1 -27
- volcenginesdkapig/models/gateway_for_get_gateway_output.py +17 -43
- volcenginesdkapig/models/gateway_service_for_get_gateway_service_output.py +29 -29
- volcenginesdkapig20221112/models/tag_for_list_routes_output.py → volcenginesdkapig/models/get_custom_domain_request.py +22 -47
- volcenginesdkapig/models/get_custom_domain_response.py +123 -0
- volcenginesdkapig/models/get_jwt_token_request.py +123 -0
- volcenginesdkapig/models/{tag_for_list_gateways_input.py → get_jwt_token_response.py} +20 -46
- volcenginesdkapig/models/imported_clb_spec_for_attach_gateway_lb_input.py +149 -0
- volcenginesdkapig/models/imported_clb_spec_for_list_gateway_lbs_output.py +201 -0
- volcenginesdkapig/models/ip_list_for_list_gateway_lbs_output.py +149 -0
- volcenginesdkapig/models/item_for_list_custom_domains_output.py +357 -0
- volcenginesdkapig/models/item_for_list_gateway_lbs_output.py +305 -0
- volcenginesdkapig/models/item_for_list_gateway_services_output.py +29 -29
- volcenginesdkapig/models/item_for_list_gateways_output.py +27 -1
- volcenginesdkapig/models/item_for_list_upstreams_output.py +1 -53
- volcenginesdkapig/models/{tag_for_list_gateway_services_output.py → label_for_create_upstream_version_input.py} +13 -13
- volcenginesdkapig/models/{tag_for_get_gateway_service_output.py → label_for_update_upstream_version_input.py} +13 -13
- volcenginesdkapig/models/list_custom_domains_request.py +201 -0
- volcenginesdkapig/models/list_custom_domains_response.py +149 -0
- volcenginesdkapig/models/list_gateway_lbs_request.py +124 -0
- volcenginesdkapig/models/list_gateway_lbs_response.py +149 -0
- volcenginesdkapig/models/list_upstreams_request.py +1 -27
- volcenginesdkapig/models/port_for_list_gateway_lbs_output.py +149 -0
- volcenginesdkapig/models/tls_trace_spec_for_create_gateway_input.py +201 -0
- volcenginesdkapig/models/tls_trace_spec_for_get_gateway_output.py +149 -0
- volcenginesdkapig/models/tls_trace_spec_for_list_gateways_output.py +149 -0
- volcenginesdkapig/models/tls_trace_spec_for_update_gateway_trace_input.py +201 -0
- volcenginesdkapig/models/trace_spec_for_create_gateway_input.py +201 -0
- volcenginesdkapig/models/trace_spec_for_get_gateway_output.py +201 -0
- volcenginesdkapig/models/trace_spec_for_list_gateways_output.py +201 -0
- volcenginesdkapig/models/trace_spec_for_update_gateway_trace_input.py +201 -0
- volcenginesdkapig/models/update_custom_domain_request.py +228 -0
- volcenginesdkapig/models/update_custom_domain_response.py +123 -0
- volcenginesdkapig/models/update_gateway_service_request.py +27 -1
- volcenginesdkapig/models/update_gateway_trace_request.py +150 -0
- volcenginesdkapig/models/update_gateway_trace_response.py +123 -0
- volcenginesdkapig/models/update_upstream_version_request.py +150 -0
- volcenginesdkapig/models/update_upstream_version_response.py +149 -0
- volcenginesdkapig/models/upstream_for_get_upstream_output.py +1 -53
- volcenginesdkapig/models/upstream_version_for_create_upstream_version_input.py +175 -0
- volcenginesdkapig/models/upstream_version_for_update_upstream_version_input.py +175 -0
- volcenginesdkapig20221112/__init__.py +12 -3
- volcenginesdkapig20221112/models/__init__.py +12 -3
- volcenginesdkapig/models/tag_for_list_upstreams_output.py → volcenginesdkapig20221112/models/allow_origin_for_create_route_input.py +25 -25
- volcenginesdkapig20221112/models/{tag_for_create_route_input.py → allow_origin_for_get_route_output.py} +24 -24
- volcenginesdkapig20221112/models/allow_origin_for_list_routes_output.py +149 -0
- volcenginesdkapig20221112/models/allow_origin_for_update_route_input.py +149 -0
- volcenginesdkapig20221112/models/cors_policy_setting_for_create_route_input.py +159 -3
- volcenginesdkapig20221112/models/cors_policy_setting_for_get_route_output.py +159 -3
- volcenginesdkapig20221112/models/cors_policy_setting_for_list_routes_output.py +159 -3
- volcenginesdkapig20221112/models/cors_policy_setting_for_update_route_input.py +159 -3
- volcenginesdkapig20221112/models/create_route_request.py +27 -53
- volcenginesdkapig20221112/models/fallback_setting_for_create_route_input.py +175 -0
- volcenginesdkapig20221112/models/fallback_setting_for_get_route_output.py +175 -0
- volcenginesdkapig20221112/models/fallback_setting_for_list_routes_output.py +175 -0
- volcenginesdkapig20221112/models/fallback_setting_for_update_route_input.py +175 -0
- volcenginesdkapig20221112/models/fallback_upstream_for_create_route_input.py +201 -0
- volcenginesdkapig20221112/models/fallback_upstream_for_get_route_output.py +201 -0
- volcenginesdkapig20221112/models/fallback_upstream_for_list_routes_output.py +201 -0
- volcenginesdkapig20221112/models/fallback_upstream_for_update_route_input.py +201 -0
- volcenginesdkapig20221112/models/header_operation_for_create_route_input.py +1 -27
- volcenginesdkapig20221112/models/header_operation_for_get_route_output.py +1 -27
- volcenginesdkapig20221112/models/header_operation_for_list_routes_output.py +1 -27
- volcenginesdkapig20221112/models/header_operation_for_update_route_input.py +1 -27
- volcenginesdkapig20221112/models/item_for_list_routes_output.py +27 -53
- volcenginesdkapig20221112/models/list_routes_request.py +1 -27
- volcenginesdkapig20221112/models/route_for_get_route_output.py +27 -53
- volcenginesdkapig20221112/models/update_route_request.py +27 -1
- volcenginesdkarkruntime/resources/images/images.py +178 -4
- volcenginesdkarkruntime/types/images/__init__.py +3 -2
- volcenginesdkarkruntime/types/images/image_gen_completed_event.py +51 -0
- volcenginesdkarkruntime/types/images/image_gen_generating_event.py +53 -0
- volcenginesdkarkruntime/types/images/image_gen_stream_event.py +24 -0
- volcenginesdkarkruntime/types/images/images.py +6 -2
- volcenginesdkarkruntime/types/responses/mcp_input_item_param.py +109 -0
- volcenginesdkarkruntime/types/responses/mcp_tool.py +80 -0
- volcenginesdkarkruntime/types/responses/mcp_tool_param.py +78 -0
- volcenginesdkarkruntime/types/responses/response_create_params.py +2 -1
- volcenginesdkarkruntime/types/responses/response_input_param.py +5 -0
- volcenginesdkarkruntime/types/responses/response_item.py +4 -0
- volcenginesdkarkruntime/types/responses/response_mcp_call_arguments_delta_event.py +37 -0
- volcenginesdkarkruntime/types/responses/response_mcp_call_arguments_done_event.py +34 -0
- volcenginesdkarkruntime/types/responses/response_mcp_call_completed_event.py +31 -0
- volcenginesdkarkruntime/types/responses/response_mcp_call_failed_event.py +31 -0
- volcenginesdkarkruntime/types/responses/response_mcp_call_in_progress_event.py +31 -0
- volcenginesdkarkruntime/types/responses/response_mcp_item.py +110 -0
- volcenginesdkarkruntime/types/responses/response_mcp_list_tools_completed_event.py +31 -0
- volcenginesdkarkruntime/types/responses/response_mcp_list_tools_failed_event.py +31 -0
- volcenginesdkarkruntime/types/responses/response_mcp_list_tools_in_progress_event.py +31 -0
- volcenginesdkarkruntime/types/responses/response_output_item.py +4 -0
- volcenginesdkarkruntime/types/responses/response_stream_event.py +18 -0
- volcenginesdkarkruntime/types/responses/response_tool_usage.py +32 -0
- volcenginesdkarkruntime/types/responses/response_usage.py +7 -0
- volcenginesdkarkruntime/types/responses/tool.py +3 -1
- volcenginesdkarkruntime/types/responses/tool_choice_mcp_param.py +29 -0
- volcenginesdkarkruntime/types/responses/tool_param.py +2 -1
- volcenginesdkarkruntime/types/responses/web_search_tool.py +49 -0
- volcenginesdkarkruntime/types/responses/web_search_tool_param.py +1 -1
- volcenginesdkcen/__init__.py +9 -0
- volcenginesdkcen/api/cen_api.py +388 -0
- volcenginesdkcen/models/__init__.py +9 -0
- volcenginesdkcen/models/associate_cen_bandwidth_package_response.py +1 -29
- volcenginesdkcen/models/attach_instance_to_cen_response.py +1 -29
- volcenginesdkcen/models/cen_bandwidth_package_for_describe_cen_bandwidth_packages_billing_output.py +279 -0
- volcenginesdkcen/models/cen_bandwidth_package_for_describe_cen_bandwidth_packages_output.py +50 -24
- volcenginesdkcen/models/create_cen_bandwidth_package_request.py +27 -1
- volcenginesdkcen/models/create_cen_bandwidth_package_response.py +3 -29
- volcenginesdkcen/models/create_cen_inter_region_bandwidth_request.py +27 -1
- volcenginesdkcen/models/create_cen_inter_region_bandwidth_response.py +3 -29
- volcenginesdkcen/models/create_cen_request.py +3 -0
- volcenginesdkcen/models/create_cen_response.py +3 -29
- volcenginesdkcen/models/create_cen_service_route_entry_response.py +1 -29
- volcenginesdkcen/models/create_cen_summary_route_entry_response.py +1 -29
- volcenginesdkcen/models/delete_cen_bandwidth_package_response.py +1 -29
- volcenginesdkcen/models/delete_cen_inter_region_bandwidth_response.py +1 -29
- volcenginesdkcen/models/delete_cen_response.py +1 -29
- volcenginesdkcen/models/delete_cen_service_route_entry_response.py +1 -29
- volcenginesdkcen/models/delete_cen_summary_route_entry_response.py +1 -29
- volcenginesdkcen/models/describe_cen_attached_instance_attributes_response.py +27 -27
- volcenginesdkcen/models/describe_cen_attached_instances_response.py +1 -27
- volcenginesdkcen/models/describe_cen_attributes_response.py +1 -27
- volcenginesdkcen/models/describe_cen_bandwidth_package_attributes_response.py +41 -41
- volcenginesdkcen/models/describe_cen_bandwidth_packages_billing_request.py +175 -0
- volcenginesdkcen/models/describe_cen_bandwidth_packages_billing_response.py +201 -0
- volcenginesdkcen/models/describe_cen_bandwidth_packages_response.py +1 -27
- volcenginesdkcen/models/describe_cen_inter_region_bandwidth_attributes_response.py +1 -27
- volcenginesdkcen/models/describe_cen_inter_region_bandwidths_response.py +1 -27
- volcenginesdkcen/models/describe_cen_route_entries_response.py +1 -27
- volcenginesdkcen/models/describe_cen_summary_route_entries_response.py +1 -27
- volcenginesdkcen/models/describe_cens_response.py +1 -27
- volcenginesdkcen/models/describe_grant_rules_to_cen_response.py +1 -27
- volcenginesdkcen/models/describe_instance_granted_rules_response.py +1 -27
- volcenginesdkcen/models/detach_instance_from_cen_response.py +1 -29
- volcenginesdkcen/models/disassociate_cen_bandwidth_package_response.py +1 -29
- volcenginesdkcen/models/grant_instance_to_cen_response.py +1 -29
- volcenginesdkcen/models/list_tags_for_resources_response.py +1 -27
- volcenginesdkcen/models/modify_cen_attributes_response.py +1 -29
- volcenginesdkcen/models/modify_cen_bandwidth_package_association_request.py +151 -0
- volcenginesdkcen/models/modify_cen_bandwidth_package_association_response.py +95 -0
- volcenginesdkcen/models/modify_cen_bandwidth_package_attributes_response.py +1 -29
- volcenginesdkcen/models/modify_cen_inter_region_bandwidth_attributes_request.py +27 -1
- volcenginesdkcen/models/modify_cen_inter_region_bandwidth_attributes_response.py +1 -29
- volcenginesdkcen/models/modify_cen_service_route_entry_attributes_response.py +1 -29
- volcenginesdkcen/models/publish_cen_route_entry_response.py +1 -29
- volcenginesdkcen/models/renew_cen_bandwidth_package_request.py +176 -0
- volcenginesdkcen/models/renew_cen_bandwidth_package_response.py +95 -0
- volcenginesdkcen/models/revoke_instance_from_cen_response.py +1 -29
- volcenginesdkcen/models/set_cen_bandwidth_package_renewal_request.py +203 -0
- volcenginesdkcen/models/set_cen_bandwidth_package_renewal_response.py +95 -0
- volcenginesdkcen/models/tag_filter_for_describe_cens_input.py +15 -15
- volcenginesdkcen/models/tag_resources_response.py +1 -29
- volcenginesdkcen/models/untag_resources_response.py +1 -29
- volcenginesdkcen/models/withdraw_cen_route_entry_response.py +1 -29
- volcenginesdkclb/__init__.py +2 -0
- volcenginesdkclb/api/clb_api.py +97 -0
- volcenginesdkclb/models/__init__.py +2 -0
- volcenginesdkclb/models/certificate_for_describe_nlb_listener_certificates_output.py +27 -1
- volcenginesdkclb/models/create_nlb_listener_request.py +157 -1
- volcenginesdkclb/models/describe_certificates_response.py +1 -53
- volcenginesdkclb/models/describe_load_balancers_request.py +53 -1
- volcenginesdkclb/models/describe_load_balancers_response.py +1 -27
- volcenginesdkclb/models/describe_nlb_listener_attributes_response.py +131 -1
- volcenginesdkclb/models/describe_nlb_listener_certificates_request.py +27 -1
- volcenginesdkclb/models/describe_nlb_server_group_attributes_response.py +1 -27
- volcenginesdkclb/models/modify_nlb_listener_additional_certificates_request.py +202 -0
- volcenginesdkclb/models/modify_nlb_listener_additional_certificates_response.py +123 -0
- volcenginesdkclb/models/modify_nlb_listener_attributes_request.py +157 -1
- volcenginesdkcore/api_client.py +1 -1
- volcenginesdkcore/auth/providers/sts_provider.py +1 -1
- volcenginesdkcore/configuration.py +1 -1
- volcenginesdkllmshield/__init__.py +82 -0
- volcenginesdkllmshield/api/__init__.py +4 -0
- volcenginesdkllmshield/api/llm_shield_sdk_v2.py +470 -0
- volcenginesdkllmshield/models/__init__.py +20 -0
- volcenginesdkllmshield/models/llm_shield_sign.py +159 -0
- volcenginesdktransitrouter/__init__.py +49 -6
- volcenginesdktransitrouter/api/transitrouter_api.py +2318 -572
- volcenginesdktransitrouter/models/__init__.py +49 -4
- volcenginesdktransitrouter/models/associate_transit_router_multicast_domain_request.py +178 -0
- volcenginesdktransitrouter/models/associate_transit_router_multicast_domain_response.py +95 -0
- volcenginesdktransitrouter/models/create_transit_router_bandwidth_package_request.py +27 -1
- volcenginesdktransitrouter/models/create_transit_router_flow_log_request.py +388 -0
- volcenginesdktransitrouter/models/create_transit_router_flow_log_response.py +123 -0
- volcenginesdktransitrouter/models/create_transit_router_forward_policy_entry_request.py +27 -1
- volcenginesdktransitrouter/models/create_transit_router_multicast_domain_request.py +228 -0
- volcenginesdktransitrouter/models/create_transit_router_multicast_domain_response.py +123 -0
- volcenginesdktransitrouter/models/create_transit_router_multicast_group_member_request.py +204 -0
- volcenginesdktransitrouter/models/create_transit_router_multicast_group_member_response.py +95 -0
- volcenginesdktransitrouter/models/create_transit_router_multicast_group_source_request.py +204 -0
- volcenginesdktransitrouter/models/create_transit_router_multicast_group_source_response.py +95 -0
- volcenginesdktransitrouter/models/create_transit_router_request.py +27 -1
- volcenginesdktransitrouter/models/create_transit_router_route_policy_entry_request.py +27 -1
- volcenginesdktransitrouter/models/delete_transit_router_flow_log_request.py +124 -0
- volcenginesdktransitrouter/models/delete_transit_router_flow_log_response.py +95 -0
- volcenginesdktransitrouter/models/delete_transit_router_multicast_domain_request.py +124 -0
- volcenginesdktransitrouter/models/delete_transit_router_multicast_domain_response.py +95 -0
- volcenginesdktransitrouter/models/delete_transit_router_multicast_group_member_request.py +178 -0
- volcenginesdktransitrouter/models/delete_transit_router_multicast_group_member_response.py +95 -0
- volcenginesdktransitrouter/models/delete_transit_router_multicast_group_source_request.py +178 -0
- volcenginesdktransitrouter/models/delete_transit_router_multicast_group_source_response.py +95 -0
- volcenginesdktransitrouter/models/describe_transit_router_flow_logs_request.py +386 -0
- volcenginesdktransitrouter/models/describe_transit_router_flow_logs_response.py +123 -0
- volcenginesdktransitrouter/models/describe_transit_router_forward_policy_entries_request.py +27 -1
- volcenginesdktransitrouter/models/describe_transit_router_multicast_domain_associations_request.py +279 -0
- volcenginesdktransitrouter/models/describe_transit_router_multicast_domain_associations_response.py +201 -0
- volcenginesdktransitrouter/models/describe_transit_router_multicast_domains_request.py +254 -0
- volcenginesdktransitrouter/models/describe_transit_router_multicast_domains_response.py +201 -0
- volcenginesdktransitrouter/models/describe_transit_router_multicast_groups_request.py +435 -0
- volcenginesdktransitrouter/models/describe_transit_router_multicast_groups_response.py +123 -0
- volcenginesdktransitrouter/models/describe_transit_router_route_entries_request.py +79 -1
- volcenginesdktransitrouter/models/describe_transit_router_route_entries_response.py +55 -3
- volcenginesdktransitrouter/models/dissociate_transit_router_multicast_domain_request.py +178 -0
- volcenginesdktransitrouter/models/dissociate_transit_router_multicast_domain_response.py +95 -0
- volcenginesdktransitrouter/models/models.py +2198 -2208
- volcenginesdktransitrouter/models/modify_transit_router_flow_log_attributes_request.py +202 -0
- volcenginesdktransitrouter/models/modify_transit_router_flow_log_attributes_response.py +95 -0
- volcenginesdktransitrouter/models/modify_transit_router_forward_policy_entry_attributes_request.py +27 -1
- volcenginesdktransitrouter/models/modify_transit_router_multicast_domain_attributes_request.py +176 -0
- volcenginesdktransitrouter/models/modify_transit_router_multicast_domain_attributes_response.py +95 -0
- volcenginesdktransitrouter/models/modify_transit_router_route_policy_entry_attributes_request.py +27 -1
- volcenginesdktransitrouter/models/start_transit_router_flow_log_request.py +124 -0
- volcenginesdktransitrouter/models/start_transit_router_flow_log_response.py +95 -0
- volcenginesdktransitrouter/models/stop_transit_router_flow_log_request.py +124 -0
- volcenginesdktransitrouter/models/stop_transit_router_flow_log_response.py +95 -0
- volcenginesdktransitrouter/models/tag_filter_for_describe_transit_router_flow_logs_input.py +149 -0
- volcenginesdktransitrouter/models/tag_filter_for_describe_transit_router_multicast_domains_input.py +149 -0
- volcenginesdkapig/models/tag_for_get_gateway_output.py → volcenginesdktransitrouter/models/tag_for_create_transit_router_flow_log_input.py +14 -14
- volcenginesdkapig/models/tag_for_create_gateway_input.py → volcenginesdktransitrouter/models/tag_for_create_transit_router_multicast_domain_input.py +14 -14
- volcenginesdkapig/models/tag_for_create_upstream_input.py → volcenginesdktransitrouter/models/tag_for_describe_transit_router_multicast_domains_output.py +14 -14
- volcenginesdktransitrouter/models/transit_router_attachment_for_describe_transit_router_peer_attachments_output.py +27 -1
- volcenginesdktransitrouter/models/transit_router_attachment_for_describe_transit_router_vpn_attachments_output.py +27 -1
- volcenginesdktransitrouter/models/transit_router_flow_log_for_describe_transit_router_flow_logs_output.py +513 -0
- volcenginesdktransitrouter/models/transit_router_for_describe_transit_routers_output.py +27 -1
- volcenginesdktransitrouter/models/transit_router_multicast_domains_for_describe_transit_router_multicast_domains_output.py +279 -0
- volcenginesdktransitrouter/models/transit_router_multicast_group_for_describe_transit_router_multicast_groups_output.py +487 -0
- volcenginesdkwafruntime/__init__.py +4 -2
- volcenginesdkwafruntime/api/waf_runtime_api.py +7 -3
- volcenginesdkwafruntime/models/llm_stream_session.py +4 -2
- volcenginesdkapig/models/backend_spec_for_create_gateway_input.py +0 -149
- volcenginesdkapig/models/backend_spec_for_get_gateway_output.py +0 -149
- {volcengine_python_sdk-4.0.16.dist-info → volcengine_python_sdk-4.0.18.dist-info}/LICENSE.txt +0 -0
- {volcengine_python_sdk-4.0.16.dist-info → volcengine_python_sdk-4.0.18.dist-info}/NOTICE.md +0 -0
- {volcengine_python_sdk-4.0.16.dist-info → volcengine_python_sdk-4.0.18.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
from pydantic import BaseModel, field_validator, Field
|
|
2
|
+
from typing import List, Optional, Any, Union
|
|
3
|
+
from datetime import datetime, date
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
import requests
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from ..models.llm_shield_sign import request_sign, Version
|
|
9
|
+
|
|
10
|
+
LLM_STREAM_SEND_BASE_WINDOW_V2 = 10
|
|
11
|
+
LLM_STREAM_SEND_EXPONENT_V2 = 2
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# 定义内容类型常量
|
|
15
|
+
class ContentTypeV2:
|
|
16
|
+
TEXT = 1
|
|
17
|
+
AUDIO = 2
|
|
18
|
+
IMAGE = 3
|
|
19
|
+
VIDEO = 4
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# 定义决策类型常量
|
|
23
|
+
class DecisionTypeV2:
|
|
24
|
+
PASS = 1
|
|
25
|
+
BLOCK = 2
|
|
26
|
+
MARK = 3
|
|
27
|
+
REPLACE = 4
|
|
28
|
+
OPTIMIZE = 5
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# 定义用户操作常量
|
|
32
|
+
class UserAction:
|
|
33
|
+
PASS = 1
|
|
34
|
+
BLOCK = 2
|
|
35
|
+
MARK = 3
|
|
36
|
+
REPLACE = 4
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# 定义匹配来源常量
|
|
40
|
+
class MatchSource:
|
|
41
|
+
UNKNOWN = 0
|
|
42
|
+
GLOBAL_CONTENTLIB = 1
|
|
43
|
+
ADMIN_CONTENTLIB = 2
|
|
44
|
+
USER_CONTENTLIB = 3
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# 定义消息结构体
|
|
48
|
+
class MessageV2(BaseModel):
|
|
49
|
+
role: str = Field("", alias="Role")
|
|
50
|
+
content: str = Field("", alias="Content")
|
|
51
|
+
content_type: int = Field(ContentTypeV2.TEXT, alias="ContentType")
|
|
52
|
+
|
|
53
|
+
class Config:
|
|
54
|
+
populate_by_name = True
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# 定义审核请求结构体
|
|
58
|
+
class ModerateV2Request(BaseModel):
|
|
59
|
+
message: MessageV2 = Field(None, alias="Message")
|
|
60
|
+
msg_id: str = Field("", alias="MsgID")
|
|
61
|
+
use_stream: int = Field(0, alias="UseStream")
|
|
62
|
+
scene: str = Field("", alias="Scene")
|
|
63
|
+
history: List[MessageV2] = Field([], alias="History")
|
|
64
|
+
|
|
65
|
+
class Config:
|
|
66
|
+
populate_by_name = True
|
|
67
|
+
|
|
68
|
+
# 深拷贝构造方法:通过 Pydantic 序列化/反序列化实现
|
|
69
|
+
def __init__(self, other=None, **data):
|
|
70
|
+
# 如果传入了其他 ModerateV2Request 实例,则进行深拷贝
|
|
71
|
+
if other is not None and isinstance(other, ModerateV2Request):
|
|
72
|
+
# 1. 将其他实例序列化为字典(包含嵌套对象)
|
|
73
|
+
other_dict = other.model_dump(by_alias=True) # 使用 alias 键名
|
|
74
|
+
# 2. 用序列化后的字典初始化当前实例(实现深拷贝)
|
|
75
|
+
super().__init__(**other_dict)
|
|
76
|
+
else:
|
|
77
|
+
# 正常初始化逻辑
|
|
78
|
+
super().__init__(**data)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# 定义风险匹配结构体
|
|
82
|
+
class RiskMatchV2(BaseModel):
|
|
83
|
+
word: str = Field("", alias="Word")
|
|
84
|
+
action: Optional[int] = Field(None, alias="Action")
|
|
85
|
+
source: Optional[int] = Field(None, alias="Source")
|
|
86
|
+
rule_id: Optional[Any] = Field(None, alias="RuleID")
|
|
87
|
+
|
|
88
|
+
class Config:
|
|
89
|
+
populate_by_name = True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# 定义放行匹配结构体
|
|
93
|
+
class PermitMatchV2(BaseModel):
|
|
94
|
+
word: str = Field("", alias="Word")
|
|
95
|
+
action: Optional[int] = Field(None, alias="Action")
|
|
96
|
+
source: Optional[int] = Field(None, alias="Source")
|
|
97
|
+
rule_id: Optional[Any] = Field(None, alias="RuleID")
|
|
98
|
+
|
|
99
|
+
class Config:
|
|
100
|
+
populate_by_name = True
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# 定义风险结构体
|
|
104
|
+
class RiskV2(BaseModel):
|
|
105
|
+
category: str = Field("", alias="Category")
|
|
106
|
+
label: str = Field("", alias="Label")
|
|
107
|
+
prob: Optional[float] = Field(None, alias="Prob")
|
|
108
|
+
matches: List[RiskMatchV2] = Field([], alias="Matches")
|
|
109
|
+
|
|
110
|
+
@field_validator('matches', mode="before")
|
|
111
|
+
def convert_risk_matches_none_to_list(cls, value):
|
|
112
|
+
return [] if value is None else value
|
|
113
|
+
|
|
114
|
+
class Config:
|
|
115
|
+
populate_by_name = True
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# 定义风险信息结构体 - 添加 None 转换
|
|
119
|
+
class RiskInfoV2(BaseModel):
|
|
120
|
+
risks: List[RiskV2] = Field([], alias="Risks")
|
|
121
|
+
|
|
122
|
+
@field_validator('risks', mode="before")
|
|
123
|
+
def convert_none_to_list(cls, value):
|
|
124
|
+
return [] if value is None else value
|
|
125
|
+
|
|
126
|
+
class Config:
|
|
127
|
+
populate_by_name = True
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# 定义放行结构体
|
|
131
|
+
class PermitV2(BaseModel):
|
|
132
|
+
category: str = Field("", alias="Category")
|
|
133
|
+
label: str = Field("", alias="Label")
|
|
134
|
+
prob: Optional[float] = Field(None, alias="Prob")
|
|
135
|
+
matches: List[PermitMatchV2] = Field([], alias="Matches")
|
|
136
|
+
|
|
137
|
+
@field_validator('matches', mode="before")
|
|
138
|
+
def convert_permit_matches_none_to_list(cls, value):
|
|
139
|
+
return [] if value is None else value
|
|
140
|
+
|
|
141
|
+
class Config:
|
|
142
|
+
populate_by_name = True
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# 定义放行信息结构体 - 添加 None 转换
|
|
146
|
+
class PermitInfoV2(BaseModel):
|
|
147
|
+
permits: List[PermitV2] = Field([], alias="Permits")
|
|
148
|
+
|
|
149
|
+
@field_validator('permits', mode="before")
|
|
150
|
+
def convert_none_to_list(cls, value):
|
|
151
|
+
return [] if value is None else value
|
|
152
|
+
|
|
153
|
+
class Config:
|
|
154
|
+
populate_by_name = True
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# 定义拦截详情结构体
|
|
158
|
+
class BlockDetailV2(BaseModel):
|
|
159
|
+
class Config:
|
|
160
|
+
extra = "forbid"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# 定义替换详情结构体
|
|
164
|
+
class ReplaceDetailV2(BaseModel):
|
|
165
|
+
replacement: Optional[MessageV2] = Field(None, alias="Replacement")
|
|
166
|
+
|
|
167
|
+
class Config:
|
|
168
|
+
populate_by_name = True
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# 定义决策详情结构体
|
|
172
|
+
class DecisionDetailV2(BaseModel):
|
|
173
|
+
block_detail: Optional[BlockDetailV2] = Field(None, alias="BlockDetail")
|
|
174
|
+
replace_detail: Optional[ReplaceDetailV2] = Field(None, alias="ReplaceDetail")
|
|
175
|
+
|
|
176
|
+
class Config:
|
|
177
|
+
populate_by_name = True
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# 定义决策结构体
|
|
181
|
+
class DecisionV2(BaseModel):
|
|
182
|
+
decision_type: int = Field(0, alias="DecisionType")
|
|
183
|
+
decision_detail: DecisionDetailV2 = Field(default_factory=DecisionDetailV2, alias="DecisionDetail")
|
|
184
|
+
decision_strategy_id: Optional[str] = Field(None, alias="DecisionStrategyID")
|
|
185
|
+
hit_strategy_ids: List[str] = Field([], alias="HitStrategyIDs")
|
|
186
|
+
|
|
187
|
+
@field_validator('hit_strategy_ids', mode="before")
|
|
188
|
+
def convert_hit_strategies_none_to_list(cls, value):
|
|
189
|
+
return [] if value is None else value
|
|
190
|
+
|
|
191
|
+
class Config:
|
|
192
|
+
populate_by_name = True
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# 定义审核结果结构体
|
|
196
|
+
class ModerateV2Result(BaseModel):
|
|
197
|
+
msg_id: str = Field("", alias="MsgID")
|
|
198
|
+
risk_info: RiskInfoV2 = Field(default_factory=RiskInfoV2, alias="RiskInfo")
|
|
199
|
+
decision: DecisionV2 = Field(default_factory=DecisionV2, alias="Decision")
|
|
200
|
+
permit_info: PermitInfoV2 = Field(default_factory=PermitInfoV2, alias="PermitInfo")
|
|
201
|
+
degraded: bool = Field(False, alias="Degraded")
|
|
202
|
+
degrade_reason: str = Field("", alias="DegradeReason")
|
|
203
|
+
|
|
204
|
+
class Config:
|
|
205
|
+
populate_by_name = True
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# 定义错误信息结构体
|
|
209
|
+
class ErrorInfo(BaseModel):
|
|
210
|
+
code: str = Field("", alias="Code")
|
|
211
|
+
codeN: Union[int, str] = Field("", alias="CodeN")
|
|
212
|
+
message: str = Field("", alias="Message")
|
|
213
|
+
|
|
214
|
+
class Config:
|
|
215
|
+
populate_by_name = True
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# 定义响应元数据结构体
|
|
219
|
+
class ResponseMetadata(BaseModel):
|
|
220
|
+
error: Union[ErrorInfo, None] = Field(default_factory=ErrorInfo, alias="Error")
|
|
221
|
+
requestId: str = Field(..., alias="RequestId") # 添加requestId字段,映射自RequestId
|
|
222
|
+
service: Union[str, None] = Field(None, alias="Service")
|
|
223
|
+
action: Union[str, None] = Field(None, alias="Action")
|
|
224
|
+
version: Union[str, None] = Field(None, alias="Version")
|
|
225
|
+
region: Union[str, None] = Field(None, alias="Region")
|
|
226
|
+
|
|
227
|
+
class Config:
|
|
228
|
+
populate_by_name = True
|
|
229
|
+
validate_by_name = True
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# 定义审核响应结构体
|
|
233
|
+
class ModerateV2Response(BaseModel):
|
|
234
|
+
response_metadata: ResponseMetadata = Field(default_factory=ResponseMetadata, alias="ResponseMetadata")
|
|
235
|
+
result: Union[ModerateV2Result, None] = Field(default_factory=ModerateV2Result, alias="Result")
|
|
236
|
+
|
|
237
|
+
class Config:
|
|
238
|
+
populate_by_name = True
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class ModerateV2StreamSession:
|
|
242
|
+
"""流式会话结构体,用于积累流式请求、存储未发送长度和默认响应体"""
|
|
243
|
+
|
|
244
|
+
def __init__(self):
|
|
245
|
+
# 用于积累流式的请求(初始为 None,对应 Go 中的指针)
|
|
246
|
+
self.request: Optional[ModerateV2Request] = None
|
|
247
|
+
# 未发送的长度(对应 Go 中的 StreamSendLen)
|
|
248
|
+
self.stream_send_len: int = 0
|
|
249
|
+
self.CurrentSendWindow = LLM_STREAM_SEND_BASE_WINDOW_V2
|
|
250
|
+
# 存储默认响应体(初始为 None,对应 Go 中的指针)
|
|
251
|
+
self.default_body: Optional[ModerateV2Response] = None
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class GenerateStreamV2Request(BaseModel):
|
|
255
|
+
"""生成流V2版本的请求模型"""
|
|
256
|
+
msg_id: str = Field(..., alias="MsgID", description="消息ID,表示请求的唯一标识")
|
|
257
|
+
|
|
258
|
+
class Config:
|
|
259
|
+
populate_by_name = True
|
|
260
|
+
json_schema_extra = {
|
|
261
|
+
"validate": {"required": True} # 对应Go中的validate:"required"
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class GenerateStreamV2Response(BaseModel):
|
|
266
|
+
def __init__(self, reader=None):
|
|
267
|
+
self.Reader = reader
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class GenerateSummarizeV2(BaseModel):
|
|
271
|
+
"""生成过程的总结信息模型"""
|
|
272
|
+
token_cost: int = Field(0, alias="TokenCost", description="消耗的token数量")
|
|
273
|
+
time_cost_ms: int = Field(0, alias="TimeCostMS", description="消耗的时长(毫秒)")
|
|
274
|
+
|
|
275
|
+
class Config:
|
|
276
|
+
populate_by_name = True
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
class GenerateStreamResult(BaseModel):
|
|
280
|
+
"""生成流V2版本的结果模型"""
|
|
281
|
+
message: Optional[MessageV2] = Field(None, alias="Message", description="优化内容,isFinished为true时为空")
|
|
282
|
+
is_finished: bool = Field(False, alias="IsFinished", description="标识是否结束")
|
|
283
|
+
|
|
284
|
+
# summarize: Optional[GenerateSummarizeV2] = Field(None, alias="Summarize", description="总结信息,isFinished为true时有值")
|
|
285
|
+
|
|
286
|
+
class Config:
|
|
287
|
+
populate_by_name = True
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class GenerateStreamV2ResponseData(BaseModel):
|
|
291
|
+
"""生成流V2版本的响应数据模型"""
|
|
292
|
+
response_metadata: ResponseMetadata = Field(..., alias="ResponseMetadata", description="响应元数据")
|
|
293
|
+
result: GenerateStreamResult = Field(..., alias="Result", description="生成流结果")
|
|
294
|
+
|
|
295
|
+
class Config:
|
|
296
|
+
populate_by_name = True
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# 定义客户端类
|
|
300
|
+
class ClientV2:
|
|
301
|
+
def __init__(self, url: str, ak: str, sk: str, region: str, timeout: float):
|
|
302
|
+
self.url = url
|
|
303
|
+
self.ak = ak
|
|
304
|
+
self.sk = sk
|
|
305
|
+
self.region = region
|
|
306
|
+
self.http_client = requests.Session()
|
|
307
|
+
self.http_client.timeout = timeout
|
|
308
|
+
|
|
309
|
+
def Moderate(self, request: Optional[ModerateV2Request] = None) -> ModerateV2Response:
|
|
310
|
+
path = "/v2/moderate"
|
|
311
|
+
action = "Moderate"
|
|
312
|
+
|
|
313
|
+
if request is None:
|
|
314
|
+
request = ModerateV2Request()
|
|
315
|
+
|
|
316
|
+
request_body = request.model_dump_json(by_alias=True).encode("utf-8")
|
|
317
|
+
|
|
318
|
+
header = {
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
sign_header = request_sign(header, self.ak, self.sk, self.region, self.url, path, action, request_body)
|
|
322
|
+
|
|
323
|
+
try:
|
|
324
|
+
resp = self.http_client.post(
|
|
325
|
+
url=self.url + path + "?Action=" + action + "&Version=" + Version,
|
|
326
|
+
data=request_body,
|
|
327
|
+
headers=sign_header
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
response = ModerateV2Response.model_validate(resp.json())
|
|
331
|
+
return response
|
|
332
|
+
|
|
333
|
+
except requests.RequestException as e:
|
|
334
|
+
raise Exception(f"请求失败: {e}")
|
|
335
|
+
except Exception as e:
|
|
336
|
+
raise Exception(f"处理响应失败: {e}")
|
|
337
|
+
|
|
338
|
+
def ModerateStream(
|
|
339
|
+
self, request: ModerateV2Request, session: ModerateV2StreamSession
|
|
340
|
+
) -> Optional[ModerateV2Response]:
|
|
341
|
+
"""
|
|
342
|
+
处理流式审核请求
|
|
343
|
+
:param request: 当前流式请求片段(ModerateV2Request 类型)
|
|
344
|
+
:param session: 流式会话对象(ModerateV2StreamSession 类型)
|
|
345
|
+
:return: 审核响应(ModerateV2Response 类型)
|
|
346
|
+
"""
|
|
347
|
+
# 1. 校验参数合法性
|
|
348
|
+
path = "/v2/moderate"
|
|
349
|
+
action = "Moderate"
|
|
350
|
+
if request is None:
|
|
351
|
+
request = ModerateV2Request() # 初始化空请求
|
|
352
|
+
|
|
353
|
+
# 本接口仅支持流式调用(use_stream 不能为 0,且 session 不能为空)
|
|
354
|
+
if request.use_stream == 0 or session is None:
|
|
355
|
+
raise ValueError("use_stream cannot be 0, and session cannot be None")
|
|
356
|
+
|
|
357
|
+
is_first_request = (session.request is None) # 判断是否为首次请求
|
|
358
|
+
is_last_request = (request.use_stream == 2) # 判断是否为最后一次请求
|
|
359
|
+
|
|
360
|
+
# 2. 初始化或追加会话请求(深拷贝确保隔离)
|
|
361
|
+
if session.request is None:
|
|
362
|
+
# 首次请求:深拷贝初始请求到 session
|
|
363
|
+
session.request = ModerateV2Request(request)
|
|
364
|
+
else:
|
|
365
|
+
# 后续请求:追加当前请求内容到 session 积累的请求中
|
|
366
|
+
# 示例:追加 message.content(根据实际业务调整)
|
|
367
|
+
if request.message and request.message.content:
|
|
368
|
+
if session.request.message is None:
|
|
369
|
+
session.request.message = MessageV2()
|
|
370
|
+
session.request.message.content += request.message.content
|
|
371
|
+
session.request.use_stream = request.use_stream
|
|
372
|
+
session.stream_send_len += len(request.message.content)
|
|
373
|
+
|
|
374
|
+
# 3. 判断是否需要发送请求到后端
|
|
375
|
+
# 只有当未检测长度 >= 10 或者是第一次或者是最后一次请求时,才发送请求
|
|
376
|
+
need_send_request = is_last_request or is_first_request or (
|
|
377
|
+
session.stream_send_len >= session.CurrentSendWindow)
|
|
378
|
+
|
|
379
|
+
# 如果不需要发送请求,直接返回上次的默认响应(如果有)
|
|
380
|
+
if not need_send_request:
|
|
381
|
+
return session.default_body
|
|
382
|
+
else:
|
|
383
|
+
session.CurrentSendWindow = session.CurrentSendWindow * LLM_STREAM_SEND_EXPONENT_V2
|
|
384
|
+
|
|
385
|
+
# 3. 序列化请求(使用 Pydantic 的 model_dump 方法)
|
|
386
|
+
try:
|
|
387
|
+
request_body = session.request.model_dump_json(by_alias=True).encode("utf-8")
|
|
388
|
+
# request_str = session.request.model_dump_json(by_alias=True)
|
|
389
|
+
except Exception as e:
|
|
390
|
+
raise IOError(f"Failed to serialize request: {str(e)}")
|
|
391
|
+
headers = {
|
|
392
|
+
# "Content-Type": "application/json",
|
|
393
|
+
}
|
|
394
|
+
sign_header = request_sign(headers, self.ak, self.sk, self.region, self.url, path, action, request_body)
|
|
395
|
+
try:
|
|
396
|
+
response = requests.post(
|
|
397
|
+
url=self.url + path + "?Action=" + action + "&Version=" + Version,
|
|
398
|
+
data=request_body,
|
|
399
|
+
headers=sign_header
|
|
400
|
+
)
|
|
401
|
+
except requests.exceptions.RequestException as e:
|
|
402
|
+
raise IOError(f"HTTP request failed: {str(e)}")
|
|
403
|
+
|
|
404
|
+
# 5. 解析响应
|
|
405
|
+
try:
|
|
406
|
+
response_data = json.loads(response.text)
|
|
407
|
+
moderate_response = ModerateV2Response(**response_data)
|
|
408
|
+
except Exception as e:
|
|
409
|
+
raise IOError(f"Failed to parse response: {str(e)}")
|
|
410
|
+
|
|
411
|
+
# 6. 更新会话状态
|
|
412
|
+
session.default_body = moderate_response # 存储响应体
|
|
413
|
+
session.stream_send_len = 0 # 重置未发送长度(根据实际业务调整)
|
|
414
|
+
session.request.msg_id = moderate_response.result.msg_id
|
|
415
|
+
|
|
416
|
+
# 7. 若为最后一次流式请求(use_stream == 2),打印最终内容
|
|
417
|
+
if session.request.use_stream == 2:
|
|
418
|
+
final_content = session.request.message.content if (
|
|
419
|
+
session.request.message and session.request.message.content) else ""
|
|
420
|
+
print(f"最终检测内容: {final_content}")
|
|
421
|
+
|
|
422
|
+
return moderate_response
|
|
423
|
+
|
|
424
|
+
def GenerateV2Stream(self, request):
|
|
425
|
+
path = "/v2/generate"
|
|
426
|
+
action = "Generate"
|
|
427
|
+
if request is None:
|
|
428
|
+
request = GenerateStreamV2Request()
|
|
429
|
+
|
|
430
|
+
# 将请求结构体序列化为 JSON
|
|
431
|
+
requestBody = request.model_dump_json(by_alias=True).encode("utf-8")
|
|
432
|
+
|
|
433
|
+
headers = {
|
|
434
|
+
# "Content-Type": "application/json",
|
|
435
|
+
}
|
|
436
|
+
try:
|
|
437
|
+
sign_header = request_sign(headers, self.ak, self.sk, self.region, self.url, path, action, requestBody)
|
|
438
|
+
# 发送 HTTP 请求
|
|
439
|
+
resp = self.http_client.post(url=self.url + path + "?Action=" + action + "&Version=" + Version,
|
|
440
|
+
data=requestBody, headers=sign_header, stream=True)
|
|
441
|
+
if resp.status_code != 200:
|
|
442
|
+
raise Exception("bad response code: %d" % resp.status_code)
|
|
443
|
+
|
|
444
|
+
for line in resp.iter_lines():
|
|
445
|
+
if line:
|
|
446
|
+
line = line.decode('utf-8')
|
|
447
|
+
if line.lstrip().startswith('data:'):
|
|
448
|
+
sse_data = line[line.index(':') + 1:].strip()
|
|
449
|
+
yield sse_data
|
|
450
|
+
except Exception as e:
|
|
451
|
+
return None, Exception("failed to send request: %s" % str(e))
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
# 自定义 JSON 编码器
|
|
455
|
+
class CustomJSONEncoder(json.JSONEncoder):
|
|
456
|
+
def default(self, obj):
|
|
457
|
+
# 处理datetime类型(如2023-10-01T12:00:00)
|
|
458
|
+
if isinstance(obj, datetime):
|
|
459
|
+
return obj.isoformat()
|
|
460
|
+
# 处理date类型(如2023-10-01)
|
|
461
|
+
elif isinstance(obj, date):
|
|
462
|
+
return obj.isoformat()
|
|
463
|
+
# 处理UUID类型
|
|
464
|
+
elif isinstance(obj, UUID):
|
|
465
|
+
return str(obj)
|
|
466
|
+
# 处理其他未知的自定义类型(返回类型信息便于调试)
|
|
467
|
+
elif hasattr(obj, '__dict__'):
|
|
468
|
+
return obj.__dict__ # 返回对象的属性字典
|
|
469
|
+
# 调用默认处理(会抛出TypeError)
|
|
470
|
+
return super().default(obj)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# coding:utf-8
|
|
2
|
+
|
|
3
|
+
from __future__ import absolute_import
|
|
4
|
+
|
|
5
|
+
from .llm_shield_sign import (
|
|
6
|
+
request_sign,
|
|
7
|
+
Service,
|
|
8
|
+
Version,
|
|
9
|
+
ContentType,
|
|
10
|
+
Method
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
'request_sign',
|
|
15
|
+
'Service',
|
|
16
|
+
'Version',
|
|
17
|
+
'ContentType',
|
|
18
|
+
'Method'
|
|
19
|
+
]
|
|
20
|
+
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# coding:utf-8
|
|
2
|
+
"""
|
|
3
|
+
Copyright (year) Beijing Volcano Engine Technology Ltd.
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import datetime
|
|
19
|
+
import hashlib
|
|
20
|
+
import hmac
|
|
21
|
+
from urllib.parse import quote, urlparse
|
|
22
|
+
import requests
|
|
23
|
+
|
|
24
|
+
# 以下参数视服务不同而不同,一个服务内通常是一致的
|
|
25
|
+
Service = "llmshield"
|
|
26
|
+
Version = "2025-08-31"
|
|
27
|
+
ContentType = "application/json"
|
|
28
|
+
Method = "POST"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def norm_query(params):
|
|
32
|
+
query = ""
|
|
33
|
+
for key in sorted(params.keys()):
|
|
34
|
+
if type(params[key]) == list:
|
|
35
|
+
for k in params[key]:
|
|
36
|
+
query = (
|
|
37
|
+
query + quote(key, safe="-_.~") + "=" + quote(k, safe="-_.~") + "&"
|
|
38
|
+
)
|
|
39
|
+
else:
|
|
40
|
+
query = (query + quote(key, safe="-_.~") + "=" + quote(params[key], safe="-_.~") + "&")
|
|
41
|
+
query = query[:-1]
|
|
42
|
+
return query.replace("+", "%20")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# 第一步:准备辅助函数。
|
|
46
|
+
# sha256 非对称加密
|
|
47
|
+
def hmac_sha256(key: bytes, content: str):
|
|
48
|
+
return hmac.new(key, content.encode("utf-8"), hashlib.sha256).digest()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# sha256 hash算法
|
|
52
|
+
def hash_sha256(content: bytes):
|
|
53
|
+
return hashlib.sha256(content).hexdigest()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# 第二步:签名请求函数
|
|
57
|
+
def request_sign(header, ak, sk, region, url, path, action, body):
|
|
58
|
+
host = urlparse(url).netloc
|
|
59
|
+
date = utc_now()
|
|
60
|
+
# 第三步:创建身份证明。其中的 Service 和 Region 字段是固定的。ak 和 sk 分别代表
|
|
61
|
+
# AccessKeyID 和 SecretAccessKey。同时需要初始化签名结构体。一些签名计算时需要的属性也在这里处理。
|
|
62
|
+
# 初始化身份证明结构体
|
|
63
|
+
credential = {
|
|
64
|
+
"access_key_id": ak,
|
|
65
|
+
"secret_access_key": sk,
|
|
66
|
+
"service": Service,
|
|
67
|
+
"region": region,
|
|
68
|
+
}
|
|
69
|
+
# 初始化签名结构体
|
|
70
|
+
request_param = {
|
|
71
|
+
"body": body,
|
|
72
|
+
"host": host,
|
|
73
|
+
"path": path,
|
|
74
|
+
"method": Method,
|
|
75
|
+
"content_type": ContentType,
|
|
76
|
+
"date": date,
|
|
77
|
+
"query": {"Action": action, "Version": Version},
|
|
78
|
+
}
|
|
79
|
+
if body is None:
|
|
80
|
+
request_param["body"] = ""
|
|
81
|
+
# 第四步:接下来开始计算签名。在计算签名前,先准备好用于接收签算结果的 signResult 变量,并设置一些参数。
|
|
82
|
+
# 初始化签名结果的结构体
|
|
83
|
+
x_date = request_param["date"].strftime("%Y%m%dT%H%M%SZ")
|
|
84
|
+
short_x_date = x_date[:8]
|
|
85
|
+
x_content_sha256 = hash_sha256(request_param["body"])
|
|
86
|
+
sign_result = {
|
|
87
|
+
"Host": request_param["host"],
|
|
88
|
+
"X-Content-Sha256": x_content_sha256,
|
|
89
|
+
"X-Date": x_date,
|
|
90
|
+
"Content-Type": request_param["content_type"],
|
|
91
|
+
}
|
|
92
|
+
# 第五步:计算 Signature 签名。
|
|
93
|
+
signed_headers_str = ";".join(
|
|
94
|
+
["content-type", "host", "x-content-sha256", "x-date"]
|
|
95
|
+
)
|
|
96
|
+
# signed_headers_str = signed_headers_str + ";x-security-token"
|
|
97
|
+
canonical_request_str = "\n".join(
|
|
98
|
+
[request_param["method"].upper(),
|
|
99
|
+
request_param["path"],
|
|
100
|
+
norm_query(request_param["query"]),
|
|
101
|
+
"\n".join(
|
|
102
|
+
[
|
|
103
|
+
"content-type:" + request_param["content_type"],
|
|
104
|
+
"host:" + request_param["host"],
|
|
105
|
+
"x-content-sha256:" + x_content_sha256,
|
|
106
|
+
"x-date:" + x_date,
|
|
107
|
+
]
|
|
108
|
+
),
|
|
109
|
+
"",
|
|
110
|
+
signed_headers_str,
|
|
111
|
+
x_content_sha256,
|
|
112
|
+
]
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# 打印正规化的请求用于调试比对
|
|
116
|
+
# print(canonical_request_str)
|
|
117
|
+
hashed_canonical_request = hash_sha256(canonical_request_str.encode("utf-8"))
|
|
118
|
+
|
|
119
|
+
# 打印hash值用于调试比对
|
|
120
|
+
# print(hashed_canonical_request)
|
|
121
|
+
credential_scope = "/".join([short_x_date, credential["region"], credential["service"], "request"])
|
|
122
|
+
string_to_sign = "\n".join(["HMAC-SHA256", x_date, credential_scope, hashed_canonical_request])
|
|
123
|
+
|
|
124
|
+
# 打印最终计算的签名字符串用于调试比对
|
|
125
|
+
# print(string_to_sign)
|
|
126
|
+
k_date = hmac_sha256(credential["secret_access_key"].encode("utf-8"), short_x_date)
|
|
127
|
+
k_region = hmac_sha256(k_date, credential["region"])
|
|
128
|
+
k_service = hmac_sha256(k_region, credential["service"])
|
|
129
|
+
k_signing = hmac_sha256(k_service, "request")
|
|
130
|
+
signature = hmac_sha256(k_signing, string_to_sign).hex()
|
|
131
|
+
|
|
132
|
+
sign_result["Authorization"] = "HMAC-SHA256 Credential={}, SignedHeaders={}, Signature={}".format(
|
|
133
|
+
credential["access_key_id"] + "/" + credential_scope,
|
|
134
|
+
signed_headers_str,
|
|
135
|
+
signature,
|
|
136
|
+
)
|
|
137
|
+
header = {**header, **sign_result, "X-Top-Service": Service, "X-Top-Region": region}
|
|
138
|
+
# header = {**header, **{"X-Security-Token": SessionToken}}
|
|
139
|
+
# 第六步:将 Signature 签名写入 HTTP Header 中,并发送 HTTP 请求。
|
|
140
|
+
return header
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# datetime.utcnow() 在 3.12+ 已经过期,使用如下方法兼容
|
|
144
|
+
def utc_now():
|
|
145
|
+
try:
|
|
146
|
+
from datetime import timezone
|
|
147
|
+
return datetime.datetime.now(timezone.utc)
|
|
148
|
+
except ImportError:
|
|
149
|
+
class UTC(datetime.tzinfo):
|
|
150
|
+
def utcoffset(self, dt):
|
|
151
|
+
return datetime.timedelta(0)
|
|
152
|
+
|
|
153
|
+
def tzname(self, dt):
|
|
154
|
+
return "UTC"
|
|
155
|
+
|
|
156
|
+
def dst(self, dt):
|
|
157
|
+
return datetime.timedelta(0)
|
|
158
|
+
|
|
159
|
+
return datetime.datetime.now(UTC())
|