Fix issue #7658: [Bug]: BadRequestError from ContentPolicyViolationError (#7660)

Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
This commit is contained in:
OpenHands 2025-04-03 15:36:16 -04:00 committed by GitHub
parent 6cfaad86ea
commit 06c68082bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 2 deletions

View File

@ -4494,6 +4494,21 @@
"tr": "OpenHands kredileriniz tükendi",
"de": "Ihre OpenHands-Guthaben sind aufgebraucht"
},
"STATUS$ERROR_LLM_CONTENT_POLICY_VIOLATION": {
"en": "Content policy violation. The output was blocked by content filtering policy.",
"ja": "コンテンツポリシー違反。出力はコンテンツフィルタリングポリシーによってブロックされました。",
"zh-CN": "内容政策违规。输出被内容过滤策略阻止。",
"zh-TW": "內容政策違規。輸出被內容過濾政策阻止。",
"ko-KR": "콘텐츠 정책 위반. 출력이 콘텐츠 필터링 정책에 의해 차단되었습니다.",
"de": "Verstoß gegen Inhaltsrichtlinien. Die Ausgabe wurde durch die Inhaltsfilterrichtlinie blockiert.",
"no": "Brudd på innholdspolicy. Utdata ble blokkert av innholdsfiltrering.",
"it": "Violazione della policy sui contenuti. L'output è stato bloccato dalla policy di filtraggio dei contenuti.",
"pt": "Violação da política de conteúdo. A saída foi bloqueada pela política de filtragem de conteúdo.",
"es": "Violación de la política de contenido. La salida fue bloqueada por la política de filtrado de contenido.",
"ar": "انتهاك سياسة المحتوى. تم حظر المخرجات بواسطة سياسة تصفية المحتوى.",
"fr": "Violation de la politique de contenu. La sortie a été bloquée par la politique de filtrage de contenu.",
"tr": "İçerik politikası ihlali. Çıktı, içerik filtreleme politikası tarafından engellendi."
},
"STATUS$ERROR_RUNTIME_DISCONNECTED": {
"en": "There was an error while connecting to the runtime. Please refresh the page.",
"zh-CN": "运行时已断开连接",

View File

@ -10,6 +10,7 @@ from litellm.exceptions import ( # noqa
APIError,
AuthenticationError,
BadRequestError,
ContentPolicyViolationError,
ContextWindowExceededError,
InternalServerError,
NotFoundError,
@ -250,7 +251,12 @@ class AgentController:
self.state.last_error = err_id
elif isinstance(e, BadRequestError) and 'ExceededBudget' in str(e):
err_id = 'STATUS$ERROR_LLM_OUT_OF_CREDITS'
# Set error reason for budget exceeded
self.state.last_error = err_id
elif isinstance(e, ContentPolicyViolationError) or (
isinstance(e, BadRequestError)
and 'ContentPolicyViolationError' in str(e)
):
err_id = 'STATUS$ERROR_LLM_CONTENT_POLICY_VIOLATION'
self.state.last_error = err_id
elif isinstance(e, RateLimitError):
await self.set_agent_state_to(AgentState.RATE_LIMITED)
@ -283,6 +289,7 @@ class AgentController:
or isinstance(e, InternalServerError)
or isinstance(e, AuthenticationError)
or isinstance(e, RateLimitError)
or isinstance(e, ContentPolicyViolationError)
or isinstance(e, LLMContextWindowExceedError)
):
reported = e

View File

@ -3,7 +3,7 @@ from unittest.mock import ANY, AsyncMock, MagicMock, patch
from uuid import uuid4
import pytest
from litellm import ContextWindowExceededError
from litellm import ContentPolicyViolationError, ContextWindowExceededError
from openhands.controller.agent import Agent
from openhands.controller.agent_controller import AgentController
@ -166,6 +166,45 @@ async def test_react_to_exception(mock_agent, mock_event_stream, mock_status_cal
await controller.close()
@pytest.mark.asyncio
async def test_react_to_content_policy_violation(
mock_agent, mock_event_stream, mock_status_callback
):
"""Test that the controller properly handles content policy violations from the LLM."""
controller = AgentController(
agent=mock_agent,
event_stream=mock_event_stream,
status_callback=mock_status_callback,
max_iterations=10,
sid='test',
confirmation_mode=False,
headless_mode=True,
)
controller.state.agent_state = AgentState.RUNNING
# Create and handle the content policy violation error
error = ContentPolicyViolationError(
message='Output blocked by content filtering policy',
model='gpt-4',
llm_provider='openai',
)
await controller._react_to_exception(error)
# Verify the status callback was called with correct parameters
mock_status_callback.assert_called_once_with(
'error',
'STATUS$ERROR_LLM_CONTENT_POLICY_VIOLATION',
'STATUS$ERROR_LLM_CONTENT_POLICY_VIOLATION',
)
# Verify the state was updated correctly
assert controller.state.last_error == 'STATUS$ERROR_LLM_CONTENT_POLICY_VIOLATION'
assert controller.state.agent_state == AgentState.ERROR
await controller.close()
@pytest.mark.asyncio
async def test_run_controller_with_fatal_error(test_event_stream, mock_memory):
config = AppConfig()