Feat: tenant llm provider (#14595)

### What problem does this PR solve?

Python implementation of the Go-based model_provider API suite.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: bill <yibie_jingnian@163.com>
This commit is contained in:
Lynn
2026-05-29 17:39:41 +08:00
committed by GitHub
parent b79f79d9b9
commit dc4b82523b
148 changed files with 6059 additions and 3075 deletions

View File

@@ -120,9 +120,8 @@ def _load_dify_retrieval(monkeypatch, *, kb, accessible, request_body, chunks=No
_stub(
monkeypatch,
"api.db.joint_services.tenant_model_service",
get_model_config_by_id=lambda *_a, **_k: {},
get_model_config_by_type_and_name=lambda *_a, **_k: {},
get_tenant_default_model_by_type=lambda *_a, **_k: {},
get_model_config_from_provider_instance=lambda *_a, **_k: {},
)
_stub(

View File

@@ -203,7 +203,7 @@ def test_async_ask_final_event_carries_decorated_answer(monkeypatch):
dialog_service.KnowledgebaseService, "get_by_ids", lambda _ids: [_KB]
)
monkeypatch.setattr(
dialog_service, "get_model_config_by_type_and_name",
dialog_service, "get_model_config_from_provider_instance",
lambda _tid, _type, _name: _LLM_CONFIG,
)
monkeypatch.setattr(dialog_service, "LLMBundle", lambda _tid, _cfg: chat_mdl)
@@ -257,7 +257,7 @@ def test_async_ask_delta_events_carry_incremental_text_only(monkeypatch):
dialog_service.KnowledgebaseService, "get_by_ids", lambda _ids: [_KB]
)
monkeypatch.setattr(
dialog_service, "get_model_config_by_type_and_name",
dialog_service, "get_model_config_from_provider_instance",
lambda _tid, _type, _name: _LLM_CONFIG,
)
monkeypatch.setattr(dialog_service, "LLMBundle", lambda _tid, _cfg: chat_mdl)
@@ -345,10 +345,11 @@ def test_async_chat_final_event_carries_decorated_answer(monkeypatch):
# Stub out the heavy service/model calls
monkeypatch.setattr(
dialog_service.TenantLLMService, "llm_id2llm_type", lambda _llm_id: "chat"
dialog_service, "get_model_type_by_name",
lambda _tid, _llm_id: ["chat"]
)
monkeypatch.setattr(
dialog_service.TenantLLMService, "get_model_config",
dialog_service, "get_model_config_from_provider_instance",
lambda _tid, _type, _llm_id: _LLM_CONFIG,
)
monkeypatch.setattr(
@@ -406,10 +407,11 @@ def test_async_chat_langfuse_uses_start_observation(monkeypatch):
retriever = _StubRetriever()
monkeypatch.setattr(
dialog_service.TenantLLMService, "llm_id2llm_type", lambda _llm_id: "chat"
dialog_service, "get_model_type_by_name",
lambda _tid, _llm_id: ["chat"]
)
monkeypatch.setattr(
dialog_service.TenantLLMService, "get_model_config",
dialog_service, "get_model_config_from_provider_instance",
lambda _tid, _type, _llm_id: _LLM_CONFIG,
)
monkeypatch.setattr(
@@ -475,10 +477,11 @@ def test_async_chat_continues_when_langfuse_observation_start_fails(monkeypatch)
retriever = _StubRetriever()
monkeypatch.setattr(
dialog_service.TenantLLMService, "llm_id2llm_type", lambda _llm_id: "chat"
dialog_service, "get_model_type_by_name",
lambda _tid, _llm_id: ["chat"]
)
monkeypatch.setattr(
dialog_service.TenantLLMService, "get_model_config",
dialog_service, "get_model_config_from_provider_instance",
lambda _tid, _type, _llm_id: _LLM_CONFIG,
)
monkeypatch.setattr(

View File

@@ -282,11 +282,14 @@ def test_async_chat_uses_all_docs_when_no_doc_ids_selected(monkeypatch):
)
monkeypatch.setattr(dialog_service.settings, "retriever", retriever, raising=False)
monkeypatch.setattr(dialog_service.TenantLLMService, "llm_id2llm_type", lambda _llm_id: "chat")
monkeypatch.setattr(
dialog_service.TenantLLMService,
"get_model_config",
lambda *_args, **_kwargs: {"llm_factory": "unit", "max_tokens": 4096},
dialog_service, "get_model_type_by_name",
lambda _tid, _llm_id: ["chat"]
)
monkeypatch.setattr(
dialog_service,
"get_model_config_from_provider_instance",
lambda *_args, **_kwargs: {"llm_factory": "unit", "max_tokens": 4096, "model_type": "chat"},
)
monkeypatch.setattr(dialog_service.TenantLangfuseService, "filter_by_tenant", lambda **_kwargs: None)
monkeypatch.setattr(

View File

@@ -312,7 +312,7 @@ def create_patch_embedding_model(vectors=None, vector_size=128):
mock_model.__exit__ = MagicMock(return_value=False)
return patch(
"rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name",
"rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance",
return_value=MagicMock(),
), patch(
"rag.svr.task_executor_refactor.task_handler.LLMBundle",

View File

@@ -56,7 +56,7 @@ class TestExtractKeywords:
{"content_with_weight": "This is test content two"},
]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -84,7 +84,7 @@ class TestExtractKeywords:
ctx.has_canceled_func = MagicMock(return_value=True)
docs = [{"content_with_weight": "This is test content"}]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -106,7 +106,7 @@ class TestExtractKeywords:
ctx = self._create_mock_context()
docs = []
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -146,7 +146,7 @@ class TestGenerateQuestions:
{"content_with_weight": "This is test content one"},
]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -174,7 +174,7 @@ class TestGenerateQuestions:
ctx.has_canceled_func = MagicMock(return_value=True)
docs = [{"content_with_weight": "This is test content"}]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -223,7 +223,7 @@ class TestGenerateMetadata:
{"content_with_weight": "This is test content", "metadata_obj": {"category": "test"}},
]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -256,7 +256,7 @@ class TestGenerateMetadata:
{"content_with_weight": "This is test content", "metadata_obj": {"category": "test"}},
]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -307,7 +307,7 @@ class TestApplyTags:
{"content_with_weight": "This is test content"},
]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:
@@ -337,7 +337,7 @@ class TestApplyTags:
{"content_with_weight": "This is test content"},
]
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_by_type_and_name") as mock_config:
with patch("rag.svr.task_executor_refactor.chunk_post_processor.get_model_config_from_provider_instance") as mock_config:
mock_config.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.chunk_post_processor.LLMBundle") as mock_llm:

View File

@@ -247,7 +247,7 @@ class TestTaskHandlerBuildToc:
coro.close()
return []
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_cfg:
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_cfg:
mock_cfg.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle:
mock_msg = MagicMock()
@@ -271,7 +271,7 @@ class TestTaskHandlerBuildToc:
coro.close()
return toc_result
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_cfg:
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_cfg:
mock_cfg.return_value = MagicMock()
with patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle:
mock_msg = MagicMock()

View File

@@ -132,7 +132,7 @@ class TestStandardChunkingPipelineIntegration:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -177,7 +177,7 @@ class TestStandardChunkingPipelineIntegration:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -223,7 +223,7 @@ class TestStandardChunkingPipelineIntegration:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -271,7 +271,7 @@ class TestStandardChunkingPipelineIntegration:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -320,7 +320,7 @@ class TestStandardChunkingPipelineIntegration:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -457,7 +457,7 @@ class TestTaskCancellationCleanupIntegration:
with patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.search.index_name") as mock_index_name, \
patch("rag.svr.task_executor_refactor.task_handler.thread_pool_exec") as mock_thread_exec, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default:
@@ -514,7 +514,7 @@ class TestRaptorPipelineIntegration:
with patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.search.index_name") as mock_index_name, \
@@ -559,7 +559,7 @@ class TestRaptorPipelineIntegration:
with patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.search.index_name") as mock_index_name, \
@@ -625,7 +625,7 @@ class TestEmbeddingModelBindingFailureIntegration:
task_dict = self._create_standard_task_dict()
ctx = create_task_context(task_dict)
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default:
mock_get_config.side_effect = Exception("Model not found")
@@ -642,7 +642,7 @@ class TestEmbeddingModelBindingFailureIntegration:
task_dict = self._create_standard_task_dict()
ctx = create_task_context(task_dict)
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
with patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default:
mock_get_config.side_effect = Exception("Model not found")
@@ -755,7 +755,7 @@ class TestTocAsyncFlowIntegration:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -821,7 +821,7 @@ class TestTocAsyncFlowIntegration:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -910,7 +910,7 @@ class TestRecordingContextDataFlowAssertions:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \
@@ -956,7 +956,7 @@ class TestRecordingContextDataFlowAssertions:
with patch_get_storage_binary(), \
patch_task_handler_settings(mock_settings), \
patch("rag.svr.task_executor_refactor.chunk_service.settings", mock_settings), \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_by_type_and_name") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.get_model_config_from_provider_instance") as mock_get_config, \
patch("rag.svr.task_executor_refactor.task_handler.LLMBundle") as mock_bundle, \
patch("rag.svr.task_executor_refactor.task_handler.get_tenant_default_model_by_type") as mock_get_default, \
patch("rag.svr.task_executor_refactor.task_handler.File2DocumentService") as mock_file_service, \