Feat: v0.27.0 model provider (#16604)

This commit is contained in:
Lynn
2026-07-08 09:47:29 +08:00
committed by GitHub
parent cb93883f3f
commit 0ae5961e1c
94 changed files with 7539 additions and 3044 deletions

View File

@@ -808,7 +808,7 @@ def test_dataset_update_embedding_model_invalid_and_none_contract(rest_client, c
dataset_id = create_payload["data"]["id"]
invalid_cases = [
("unknown@ZHIPU-AI", "Instance default not found for model unknown@ZHIPU-AI."),
("unknown@ZHIPU-AI", "Model unknown@ZHIPU-AI not found for model embedding"),
("embedding-3@unknown", "Provider unknown not found for model embedding-3@unknown."),
("text-embedding-v3@Tongyi-Qianwen", "Provider Tongyi-Qianwen not found for model text-embedding-v3@Tongyi-Qianwen."),
("text-embedding-3-small@OpenAI", "Provider OpenAI not found for model text-embedding-3-small@OpenAI."),
@@ -1163,7 +1163,7 @@ def test_dataset_create_permission_contract(rest_client, clear_datasets, name, p
("tenant_zhipu", "embedding-3@CI@ZHIPU-AI", 0, "embedding-3@CI@ZHIPU-AI", None, True),
("embedding_model_unset", "__UNSET__", 0, "BAAI/bge-small-en-v1.5@Local@Builtin", None, False),
("embedding_model_none", None, 0, "BAAI/bge-small-en-v1.5@Local@Builtin", None, False),
("unknown_llm_name", "unknown@ZHIPU-AI", 102, None, "Instance default not found for model unknown@ZHIPU-AI.", False),
("unknown_llm_name", "unknown@ZHIPU-AI", 102, None, "Model unknown@ZHIPU-AI not found for model embedding", False),
("unknown_llm_factory", "embedding-3@unknown", 102, None, "Provider unknown not found for model embedding-3@unknown.", False),
(
"tenant_no_auth_default_tenant_llm",

View File

@@ -45,7 +45,7 @@ class _AwaitableValue:
class _DummyKB:
def __init__(self, tenant_id="tenant-1", embd_id="embd-1", tenant_embd_id=1):
def __init__(self, tenant_id="tenant-1", embd_id="embd-1", tenant_embd_id="tm-embd-1"):
self.tenant_id = tenant_id
self.embd_id = embd_id
self.tenant_embd_id = tenant_embd_id
@@ -212,7 +212,7 @@ def _load_dify_retrieval_module(monkeypatch):
"id": self.id,
}
def _get_model_config_by_id(tenant_model_id: int, allowed_tenant_ids=None, requester_tenant_id=None) -> dict:
def _get_model_config_by_id(tenant_model_id: str, allowed_tenant_ids=None, requester_tenant_id=None) -> dict:
mock_tenant_id = "tenant-1"
if allowed_tenant_ids is not None:
if isinstance(allowed_tenant_ids, str):

View File

@@ -45,7 +45,7 @@ class _AwaitableValue:
class _DummyKB:
def __init__(self, tenant_id="tenant-1", embd_id="embd-1", tenant_embd_id=1):
def __init__(self, tenant_id="tenant-1", embd_id="embd-1", tenant_embd_id="tm-embd-1"):
self.tenant_id = tenant_id
self.embd_id = embd_id
self.tenant_embd_id = tenant_embd_id
@@ -221,7 +221,7 @@ def _load_dify_retrieval_module(monkeypatch):
}
def _get_model_config_by_id(
tenant_model_id: int,
tenant_model_id: str,
allowed_tenant_ids=None,
requester_tenant_id=None,
) -> dict:

View File

@@ -447,7 +447,7 @@ def _load_doc_module(monkeypatch, module_basename="chunk_api"):
}
def _get_model_config_by_id(
tenant_model_id: int,
tenant_model_id: str,
allowed_tenant_ids=None,
requester_tenant_id=None,
) -> dict:
@@ -989,7 +989,7 @@ class TestDocRoutesUnit:
monkeypatch.setattr(module.rag_tokenizer, "fine_grained_tokenize", lambda text: text or "")
monkeypatch.setattr(module.rag_tokenizer, "is_chinese", lambda _text: False)
monkeypatch.setattr(module.DocumentService, "get_embd_id", lambda _doc_id: "embd")
monkeypatch.setattr(module.DocumentService, "get_tenant_embd_id", lambda _doc_id: 1)
monkeypatch.setattr(module.DocumentService, "get_tenant_embd_id", lambda _doc_id: "tm-embd-1")
class _EmbedModel:
def encode(self, _texts):
@@ -1079,8 +1079,8 @@ class TestDocRoutesUnit:
"get_request_json",
lambda: _AwaitableValue({"dataset_ids": ["ds-1"], "question": "q", "highlight": "True"}),
)
monkeypatch.setattr(module.KnowledgebaseService, "get_by_ids", lambda _ids: [SimpleNamespace(embd_id="m1", tenant_id="tenant-1", tenant_embd_id=1)])
monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _id: (True, SimpleNamespace(tenant_id="tenant-1", embd_id="m1", tenant_embd_id=1)))
monkeypatch.setattr(module.KnowledgebaseService, "get_by_ids", lambda _ids: [SimpleNamespace(embd_id="m1", tenant_id="tenant-1", tenant_embd_id="tm-embd-1")])
monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _id: (True, SimpleNamespace(tenant_id="tenant-1", embd_id="m1", tenant_embd_id="tm-embd-1")))
class _Retriever:
async def retrieval(self, *_args, **_kwargs):
@@ -1203,7 +1203,7 @@ class TestDocRoutesUnit:
}
),
)
monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _id: (True, SimpleNamespace(tenant_id="tenant-1", embd_id="m1", tenant_embd_id=1)))
monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _id: (True, SimpleNamespace(tenant_id="tenant-1", embd_id="m1", tenant_embd_id="tm-embd-1")))
monkeypatch.setattr(module, "cross_languages", _cross_languages)
monkeypatch.setattr(module, "keyword_extraction", _keyword_extraction)
monkeypatch.setattr(module.settings, "retriever", _FeatureRetriever())

View File

@@ -455,7 +455,7 @@ def _load_session_module(monkeypatch):
}
def _get_model_config_by_id(
tenant_model_id: int,
tenant_model_id: str,
allowed_tenant_ids=None,
requester_tenant_id=None,
) -> dict:

View File

@@ -345,7 +345,7 @@ def _load_chunk_module(monkeypatch):
@staticmethod
def get_tenant_embd_id(_doc_id):
return 1
return "tm-embd-1"
@staticmethod
def decrement_chunk_num(*args):
@@ -377,7 +377,7 @@ def _load_chunk_module(monkeypatch):
@staticmethod
def get_by_id(_kb_id):
return True, SimpleNamespace(pagerank=0.6, tenant_id="tenant-1", tenant_embd_id=2, tenant_llm_id=1)
return True, SimpleNamespace(pagerank=0.6, tenant_id="tenant-1", tenant_embd_id="tm-embd-2", tenant_llm_id="tm-llm-1")
kb_service_mod.KnowledgebaseService = _KnowledgebaseService
monkeypatch.setitem(sys.modules, "api.db.services.knowledgebase_service", kb_service_mod)
@@ -451,9 +451,9 @@ def _load_chunk_module(monkeypatch):
def get_by_id(tenant_id):
return True, SimpleNamespace(
llm_id="gpt-3.5-turbo",
tenant_llm_id=1,
tenant_llm_id="tm-llm-1",
embd_id="text-embedding-ada-002",
tenant_embd_id=2,
tenant_embd_id="tm-embd-2",
asr_id="whisper-1",
img2txt_id="gpt-4-vision-preview",
rerank_id="bge-reranker",

View File

@@ -24,6 +24,7 @@ import importlib.util
import logging
import sys
from pathlib import Path
from enum import IntEnum
from types import ModuleType, SimpleNamespace
from unittest.mock import MagicMock
@@ -32,6 +33,20 @@ import pytest
pytestmark = pytest.mark.p2
class _StubModelTypeBinary(IntEnum):
"""Mimics common.constants.ModelTypeBinary for the stubbed environment."""
CHAT = 1
EMBEDDING = 2
SPEECH2TEXT = 4
IMAGE2TEXT = 8
RERANK = 16
TTS = 32
OCR = 64
_MODEL_TYPE_TO_BIN = {mt.name.lower(): mt.value for mt in _StubModelTypeBinary}
def _stub(monkeypatch, name, **attrs):
"""Register a stub module in `sys.modules` with the given attributes.
@@ -120,6 +135,9 @@ def _load_module(monkeypatch, *, tenant_model_records, factory_llm_infos=None):
get_by_provider_id_and_instance_id_and_model_type_and_model_name=lambda *args: SimpleNamespace(
status=1
),
get_by_provider_id_and_instance_id_and_model_name=lambda *args: SimpleNamespace(
status=1
),
),
)
@@ -143,6 +161,7 @@ def _load_module(monkeypatch, *, tenant_model_records, factory_llm_infos=None):
"common.constants",
ActiveStatusEnum=SimpleNamespace(ACTIVE=SimpleNamespace(value=1), INACTIVE=SimpleNamespace(value=0), UNSUPPORTED=SimpleNamespace(value=2)),
LLMType=SimpleNamespace(EMBEDDING="embedding"),
ModelTypeBinary=_StubModelTypeBinary,
)
_stub(
monkeypatch,
@@ -183,18 +202,21 @@ def _make_model_record(model_name, model_type="embedding", status=1):
Args:
model_name: Model name; may contain `@` characters.
model_type: Model type filter (default `embedding`).
status: `ActiveStatusEnum` value (default `1` = ACTIVE).
model_type: Model type string (default `embedding`) or int bitmask.
String values are automatically converted to the corresponding
bitmask so that `record.model_type & filter_bin` works.
status: `ActiveStatusEnum` value (default `1` = ACTIVE in stub).
Returns:
A `SimpleNamespace` with the fields read by
`list_tenant_added_models`.
"""
model_type_bin = _MODEL_TYPE_TO_BIN.get(model_type, model_type) if isinstance(model_type, str) else model_type
return SimpleNamespace(
provider_id="provider-1",
instance_id="instance-1",
model_name=model_name,
model_type=model_type,
model_type=model_type_bin,
status=status,
)

View File

@@ -381,6 +381,7 @@ def _make_dialog(chat_mdl_stub):
top_n=6,
top_k=1024,
rerank_id="",
tenant_rerank_id=None
)

View File

@@ -295,6 +295,7 @@ def test_async_chat_uses_all_docs_when_no_doc_ids_selected(monkeypatch):
dialog = SimpleNamespace(
kb_ids=["kb-1"],
llm_id="chat-model",
tenant_llm_id="",
tenant_id="tenant-id",
llm_setting={},
similarity_threshold=0.1,