fix: suggested questions API crash on legacy conversation override configs (#36459)

This commit is contained in:
呆萌闷油瓶 2026-05-21 09:58:52 +08:00 committed by GitHub
parent 60cd346fa6
commit 0cf9597f52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 115 additions and 8 deletions

View File

@ -2,7 +2,6 @@ import logging
from collections.abc import Sequence
from typing import cast
from pydantic import TypeAdapter
from sqlalchemy import select
from sqlalchemy.orm import sessionmaker
@ -23,7 +22,6 @@ from models.model import (
App,
AppMode,
AppModelConfig,
AppModelConfigDict,
EndUser,
Message,
MessageFeedback,
@ -42,7 +40,6 @@ from services.errors.message import (
)
from services.workflow_service import WorkflowService
_app_model_config_adapter: TypeAdapter[AppModelConfigDict] = TypeAdapter(AppModelConfigDict)
logger = logging.getLogger(__name__)
@ -297,14 +294,12 @@ class MessageService:
.limit(1)
)
else:
conversation_override_model_configs = _app_model_config_adapter.validate_json(
conversation.override_model_configs
)
app_model_config = AppModelConfig(
app_id=app_model.id,
)
app_model_config.id = conversation.app_model_config_id
app_model_config = app_model_config.from_model_config_dict(conversation_override_model_configs)
# Reuse Conversation.model_config so suggested-questions reads the same
# compatibility-normalized config as the rest of the message flow.
app_model_config = app_model_config.from_model_config_dict(conversation.model_config)
if not app_model_config:
raise ValueError("did not find app model config")

View File

@ -1,3 +1,4 @@
import json
from datetime import datetime
from unittest.mock import MagicMock, patch
@ -1056,6 +1057,117 @@ class TestMessageServiceSuggestedQuestions:
)
mock_model_manager.return_value.get_model_instance.assert_not_called()
@patch("services.message_service.db")
@patch("services.message_service.ModelManager.for_tenant")
@patch("services.message_service.TokenBufferMemory")
@patch("services.message_service.LLMGenerator")
@patch("services.message_service.TraceQueueManager")
@patch.object(MessageService, "get_message")
@patch("services.message_service.ConversationService")
def test_get_suggested_questions_chat_app_uses_compatible_override_model_config(
self,
mock_conversation_service,
mock_get_message,
mock_trace_manager,
mock_llm_gen,
mock_memory,
mock_model_manager,
mock_db,
factory,
):
"""Test legacy override configs are normalized before suggested questions reads them."""
app = factory.create_app_mock(mode=AppMode.CHAT)
app.tenant_id = "tenant-123"
user = factory.create_end_user_mock()
message = factory.create_message_mock()
mock_get_message.return_value = message
conversation = MagicMock()
conversation.override_model_configs = json.dumps(
{
"speech_to_text": {"enabled": False},
"text_to_speech": {"enabled": False},
"retriever_resource": {"enabled": False},
"model": {"provider": "openai", "name": "gpt-4o-mini", "mode": "chat"},
"user_input_form": [],
"dataset_query_variable": "",
"pre_prompt": "",
"agent_mode": {
"enabled": False,
"max_iteration": 5,
"strategy": "function_call",
"tools": [],
},
"prompt_type": "simple",
"chat_prompt_config": {},
"completion_prompt_config": {},
"dataset_configs": {"retrieval_model": "single", "datasets": {"datasets": []}},
"file_upload": {
"image": {
"detail": "high",
"enabled": False,
"number_limits": 3,
"transfer_methods": ["remote_url", "local_file"],
}
},
"suggested_questions_after_answer": {
"enabled": True,
"prompt": "legacy prompt",
},
}
)
conversation.model_config = {
"opening_statement": None,
"suggested_questions": [],
"suggested_questions_after_answer": {
"enabled": True,
"prompt": "legacy prompt",
},
"speech_to_text": {"enabled": False},
"text_to_speech": {"enabled": False},
"retriever_resource": {"enabled": False},
"annotation_reply": {"enabled": False},
"more_like_this": {"enabled": False},
"sensitive_word_avoidance": {"enabled": False, "type": "", "config": {}},
"external_data_tools": [],
"model": {"provider": "openai", "name": "gpt-4o-mini", "mode": "chat"},
"user_input_form": [],
"dataset_query_variable": "",
"pre_prompt": "",
"agent_mode": {"enabled": False, "strategy": "function_call", "tools": [], "prompt": None},
"prompt_type": "simple",
"chat_prompt_config": {},
"completion_prompt_config": {},
"dataset_configs": {"retrieval_model": "single", "datasets": {"datasets": []}},
"file_upload": {
"image": {
"detail": "high",
"enabled": False,
"number_limits": 3,
"transfer_methods": ["remote_url", "local_file"],
}
},
"model_id": None,
"provider": None,
}
mock_conversation_service.get_conversation.return_value = conversation
mock_memory.return_value.get_history_prompt_text.return_value = "histories"
mock_llm_gen.generate_suggested_questions_after_answer.return_value = ["Q1?"]
result = MessageService.get_suggested_questions_after_answer(
app_model=app, user=user, message_id="msg-123", invoke_from=MagicMock()
)
assert result == ["Q1?"]
mock_db.session.scalar.assert_not_called()
mock_llm_gen.generate_suggested_questions_after_answer.assert_called_once_with(
tenant_id="tenant-123",
histories="histories",
instruction_prompt="legacy prompt",
model_config=None,
)
# Test 30: get_suggested_questions_after_answer - Disabled Error
@patch("services.message_service.WorkflowService")
@patch("services.message_service.AdvancedChatAppConfigManager")