Merge pull request #2826 from zhayujie/feat-multi-model

feat: multi-provider model console
This commit is contained in:
zhayujie
2026-05-22 11:08:13 +08:00
committed by GitHub
78 changed files with 6067 additions and 673 deletions

View File

@@ -1056,6 +1056,38 @@ class CowCliPlugin(Plugin):
logger.warning(f"[CowCli] /memory dream sync failed: {e}")
return f"❌ 记忆蒸馏失败: {e}"
@staticmethod
def _resolve_active_embedding():
"""
Resolve (provider_label, model, dim) from the LATEST config, not the
possibly-stale provider instance cached on a running agent. Used by
/memory status and rebuild-index hints so they reflect what a rebuild
will actually run as after the user changes embedding_provider.
Returns (label, model, dim) where any field may be None when unknown.
"""
from agent.memory.embedding import EMBEDDING_VENDORS
from config import conf
provider_key = (conf().get("embedding_provider") or "").strip().lower()
cfg_model = (conf().get("embedding_model") or "").strip()
try:
cfg_dim = int(conf().get("embedding_dimensions") or 0)
except (TypeError, ValueError):
cfg_dim = 0
if not provider_key:
# Legacy auto path: openai -> linkai, both default to text-embedding-3-small (1536).
if (conf().get("open_ai_api_key") or "").strip():
return "openai (legacy)", "text-embedding-3-small", 1536
if (conf().get("linkai_api_key") or "").strip():
return "linkai (legacy)", "text-embedding-3-small", 1536
return "(legacy)", None, None
meta = EMBEDDING_VENDORS.get(provider_key) or {}
model = cfg_model or meta.get("default_model")
dim = cfg_dim if cfg_dim > 0 else meta.get("default_dimensions")
return provider_key, model, dim
def _memory_status(self) -> str:
"""Show current memory index status."""
from agent.memory.embedding import detect_index_dim
@@ -1078,15 +1110,14 @@ class CowCliPlugin(Plugin):
lines.append(f" Chunks : {chunks} (embedded: {embedded})")
lines.append("")
# Active provider (from running config + provider instance).
# Resolve from the latest config so users see what /memory rebuild-index
# will actually run as — not what the cached agent was initialized with.
cfg_provider, cfg_model, cfg_dim = self._resolve_active_embedding()
provider_obj = memory_manager.embedding_provider
cfg_provider = (conf().get("embedding_provider") or "").strip().lower() or "(legacy)"
if provider_obj is not None:
cfg_model = getattr(provider_obj, "model", "?")
cfg_dim = getattr(provider_obj, "_dimensions", None) or "?"
if cfg_model:
lines.append(f" Provider : {cfg_provider}")
lines.append(f" Model : {cfg_model}")
lines.append(f" Dim : {cfg_dim}")
lines.append(f" Dim : {cfg_dim if cfg_dim else '?'}")
else:
lines.append(" Provider : (未初始化, keyword-only)")
@@ -1105,7 +1136,6 @@ class CowCliPlugin(Plugin):
)
index_dim = detect_index_dim(memory_manager.storage)
cfg_dim = getattr(provider_obj, "_dimensions", None)
if index_dim is not None and cfg_dim and index_dim != cfg_dim:
warnings.append(
f" ⚠️ 索引中存量向量为 {index_dim} 维,与当前配置 {cfg_dim} 维不一致;"
@@ -1129,15 +1159,27 @@ class CowCliPlugin(Plugin):
)
memory_manager = agent.memory_manager
if memory_manager.embedding_provider is None:
# Rebuild against the LATEST config: build a fresh provider from
# config.json and swap it onto memory_manager. The agent's
# conversation_history and other state are untouched.
try:
from bridge.agent_initializer import AgentInitializer
fresh_provider = AgentInitializer(bridge=None, agent_bridge=None) \
._init_embedding_provider(memory_manager.config, session_id=session_id)
except Exception as e:
logger.exception("[CowCli] /memory rebuild-index: build provider failed")
return f"⚠️ 无法根据当前配置构造 embedding provider: {e}"
if fresh_provider is None:
return (
"⚠️ 当前没有可用的 embedding provider。\n"
"请检查 config.json 中的 embedding 相关配置 (provider / api key)。"
)
memory_manager.embedding_provider = fresh_provider
provider_obj = memory_manager.embedding_provider
model_label = getattr(provider_obj, "model", "?")
dim_label = getattr(provider_obj, "dimensions", "?")
model_label = getattr(fresh_provider, "model", "?")
dim_label = getattr(fresh_provider, "dimensions", "?")
# SaaS (e_context is None): run synchronously, return final result
if e_context is None:
@@ -1168,7 +1210,7 @@ class CowCliPlugin(Plugin):
threading.Thread(target=_run, daemon=True).start()
return (
f"🔧 索引重建已启动 (model={model_label}, dim={dim_label})\n\n"
f"清空现有 chunks 并重新 embed 所有记忆文件,完成后会通知你。"
f"重新向量化所有记忆和知识文件,完成后会通知你。"
)
@staticmethod