Skip to content

Commit 44d64f8

Browse files
committed
refactor: enhance model management with credential caching and retrieval methods
1 parent 4d62575 commit 44d64f8

3 files changed

Lines changed: 49 additions & 16 deletions

File tree

‎apps/common/config/embedding_config.py‎

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,49 @@
11
# coding=utf-8
22
"""
3-
@project: maxkb
4-
@Author:虎
5-
@file: embedding_config.py
6-
@date:2023/10/23 16:03
7-
@desc:
3+
@project: maxkb
4+
@Author:虎
5+
@file: embedding_config.py
6+
@date:2023/10/23 16:03
7+
@desc:
88
"""
99

1010
import threading
1111
import time
12+
import json
1213

1314
from common.cache.mem_cache import MemCache
15+
from common.utils.rsa_util import rsa_long_decrypt
1416

1517
_lock = threading.Lock()
1618
locks = {}
1719

1820

1921
class ModelManage:
20-
cache = MemCache('model', {})
22+
cache = MemCache("model", {})
23+
# 按 model_id 缓存的解密凭据与模型行,避免每次调用重复 RSA 解密 / 重复查库。
24+
# 二者在模型更新/删除时通过 delete_key(_id) 一并失效,保证改 key 立即生效。
25+
credential_cache = MemCache("model_credential", {})
26+
model_cache = MemCache("model_row", {})
2127
up_clear_time = time.time()
2228

29+
@staticmethod
30+
def get_decrypted_credential(model_id, credential):
31+
"""返回解密后的凭据 dict;结果按 model_id 缓存,改 key 时由 delete_key 清除。"""
32+
cached = ModelManage.credential_cache.get(model_id)
33+
if cached is not None:
34+
return cached
35+
decrypted = json.loads(rsa_long_decrypt(credential))
36+
ModelManage.credential_cache.set(model_id, decrypted, timeout=60 * 60 * 8)
37+
return decrypted
38+
39+
@staticmethod
40+
def get_model_row(_id):
41+
return ModelManage.model_cache.get(_id)
42+
43+
@staticmethod
44+
def set_model_row(_id, model):
45+
ModelManage.model_cache.set(_id, model, timeout=60 * 60 * 8)
46+
2347
@staticmethod
2448
def _get_lock(_id):
2549
lock = locks.get(_id)
@@ -59,24 +83,27 @@ def clear_timeout_cache():
5983

6084
@staticmethod
6185
def delete_key(_id):
62-
if ModelManage.cache.has_key(_id):
63-
ModelManage.cache.delete(_id)
86+
for cache in (ModelManage.cache, ModelManage.credential_cache, ModelManage.model_cache):
87+
if cache.has_key(_id):
88+
cache.delete(_id)
6489

6590

6691
class VectorStore:
6792
from knowledge.vector.pg_vector import PGVector
6893
from knowledge.vector.base_vector import BaseVectorStore
94+
6995
instance_map = {
70-
'pg_vector': PGVector,
96+
"pg_vector": PGVector,
7197
}
7298
instance = None
7399

74100
@staticmethod
75101
def get_embedding_vector() -> BaseVectorStore:
76102
from knowledge.vector.pg_vector import PGVector
103+
77104
if VectorStore.instance is None:
78105
from maxkb.const import CONFIG
79-
vector_store_class = VectorStore.instance_map.get(CONFIG.get("VECTOR_STORE_NAME"),
80-
PGVector)
106+
107+
vector_store_class = VectorStore.instance_map.get(CONFIG.get("VECTOR_STORE_NAME"), PGVector)
81108
VectorStore.instance = vector_store_class()
82109
return VectorStore.instance

‎apps/models_provider/tests.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def test_every_registered_embedding_provider_declares_image_capability(self):
3737
embedding_classes = {
3838
model_info.model_class
3939
for provider in ModelProvideConstants
40-
for model_info in provider.value.get_model_info_manage().model_list
40+
for model_info in ModelProvideConstants[provider].get_model_info_manage().model_list
4141
if model_info.model_type == ModelTypeConst.EMBEDDING.name
4242
}
4343

‎apps/models_provider/tools.py‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77
@desc:
88
"""
99

10-
import json
1110
from typing import Dict
1211

1312
from common.config.embedding_config import ModelManage
1413
from common.database_model_manage.database_model_manage import DatabaseModelManage
15-
from common.utils.rsa_util import rsa_long_decrypt
1614
from django.db import connection
1715
from django.db.models import QuerySet
1816
from django.utils.translation import gettext_lazy as _
@@ -35,7 +33,7 @@ def get_model_(provider, model_type, model_name, credential, model_id, use_local
3533
model = get_provider(provider).get_model(
3634
model_type,
3735
model_name,
38-
json.loads(rsa_long_decrypt(credential)),
36+
ModelManage.get_decrypted_credential(model_id, credential),
3937
model_id=model_id,
4038
use_local=use_local,
4139
streaming=True,
@@ -110,14 +108,22 @@ def is_valid_credential(
110108

111109

112110
def get_model_by_id(_id, workspace_id):
111+
# 同一工作空间读取模型行是高频路径,命中缓存可省一次 DB 查询。
112+
# 跨工作空间的授权读取不走缓存,始终保持走权限校验,避免越权风险。
113+
cached = ModelManage.get_model_row(_id)
114+
if cached is not None and cached.workspace_id == workspace_id:
115+
return cached
113116
model = QuerySet(Model).filter(id=_id).first()
114117
# 归还链接到连接池
115118
connection.close()
116119
get_authorized_model = DatabaseModelManage.get_model("get_authorized_model")
117-
if model and model.workspace_id != workspace_id and get_authorized_model is not None:
120+
authorized = model is not None and model.workspace_id != workspace_id and get_authorized_model is not None
121+
if authorized:
118122
model = get_authorized_model(QuerySet(Model).filter(id=_id), workspace_id).first()
119123
if model is None:
120124
raise Exception(_("Model does not exist"))
125+
if not authorized:
126+
ModelManage.set_model_row(_id, model)
121127
return model
122128

123129

0 commit comments

Comments
 (0)