本篇文章主要讲解通过LmStudio利用本地gpu资源实现对OpenClaw的无限续杯解决方案及实现方式。 作者:任聪聪 日期:2026年3月9日
必要条件
必须是独显且,显卡基本超过GTX4090。
准备材料
lmStudio
下载地址:lmstudio.ai/
配置脚本:
#!/usr/bin/env python3
"""
LM Studio OpenClaw 配置助手
自动探测本地 LM Studio (http://localhost:1234) 的模型,并生成 OpenClaw 配置。
"""
import json
import os
import sys
import urllib.request
import urllib.error
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
# --- 配置常量 ---
DEFAULT_LMSTUDIO_URL = "http://localhost:1234/v1"
DEFAULT_CONTEXT_WINDOW = 32768 # 默认假设模型支持 32k
DEFAULT_MAX_TOKENS = 8192
OPENCLAW_MIN_CONTEXT = 16000 # OpenClaw 强制要求的最小上下文
def print_banner():
print("=" * 70)
print("🔧 LM Studio OpenClaw 配置助手")
print("=" * 70)
print()
def get_config_path() -> str:
possible_paths = [
os.path.expanduser("~/.openclaw/openclaw.json"),
os.path.expanduser("~/.moltbot/moltbot.json"),
]
env_path = os.environ.get("OPENCLAW_CONFIG_PATH")
if env_path:
return env_path
for path in possible_paths:
if os.path.exists(path):
return path
return possible_paths[0]
def load_config(path: str) -> Dict[str, Any]:
if not os.path.exists(path):
print(f"⚠️ 配置文件不存在: {path},将创建新配置...")
return {}
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
print(f"❌ 读取失败: {e}")
sys.exit(1)
def backup_config(path: str) -> str:
if not os.path.exists(path):
return ""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = f"{path}.backup.{timestamp}"
import shutil
shutil.copy2(path, backup_path)
print(f"✅ 已创建备份: {backup_path}")
return backup_path
def save_config(config: Dict, path: str) -> bool:
try:
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
json.dump(config, f, indent=2, ensure_ascii=False)
return True
except Exception as e:
print(f"❌ 保存失败: {e}")
return False
def is_embedding_model(model_id: str) -> bool:
model_id_lower = model_id.lower()
keywords = ["embed", "bge", "m3e", "text-embedding", "gte", "e5", "nomic"]
return any(k in model_id_lower for k in keywords)
def fetch_models(base_url: str) -> Tuple[List[Dict], Optional[str]]:
"""从 LM Studio 获取模型列表"""
models_url = f"{base_url.rstrip('/')}/models"
request = urllib.request.Request(models_url, method="GET")
try:
with urllib.request.urlopen(request, timeout=10) as response:
data = json.loads(response.read().decode("utf-8"))
models = data.get("data", []) if isinstance(data, dict) else data
return [{"id": m["id"]} for m in models if isinstance(m, dict) and "id" in m], None
except urllib.error.URLError as e:
return [], f"无法连接到 LM Studio ({base_url}): {e.reason}"
except Exception as e:
return [], str(e)
def build_model_config(model_id: str, context_window: int) -> Dict:
"""为单个模型构建 OpenClaw 配置片段"""
input_types = ["text"]
# 简单判断是否为视觉模型 (可以根据需要扩展)
if "vl" in model_id.lower() or "vision" in model_id.lower():
input_types.append("image")
config = {
"id": model_id,
"name": f"{model_id} (Local)",
"reasoning": False,
"input": input_types,
"cost": {"input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0},
"contextWindow": context_window,
"maxTokens": min(DEFAULT_MAX_TOKENS, context_window // 4),
"compat": {"supportsDeveloperRole": True}
}
return config
def main():
print_banner()
# 1. 探测 LM Studio
lmstudio_url = DEFAULT_LMSTUDIO_URL
print(f"🔄 正在探测本地 LM Studio ({lmstudio_url})...")
available_models, error = fetch_models(lmstudio_url)
if error:
print(f"❌ 错误: {error}")
print("\n请确保:")
print(" 1. LM Studio 已启动")
print(" 2. 'Local Server' 功能已开启 (端口 1234)")
print(" 3. 已加载至少一个模型")
sys.exit(1)
if not available_models:
print("❌ 错误: LM Studio 未返回任何模型。")
print(" 请在 LM Studio 中加载一个模型后再试。")
sys.exit(1)
print(f"✅ 成功获取 {len(available_models)} 个模型\n")
# 2. 分离 LLM 和 Embedding
llm_models = [m for m in available_models if not is_embedding_model(m["id"])]
embedding_models = [m for m in available_models if is_embedding_model(m["id"])]
if not llm_models:
print("❌ 错误: 未找到任何语言模型 (LLM)。")
print(" 请在 LM Studio 中加载一个 LLM (如 Qwen, Llama 等)。")
sys.exit(1)
# 3. 让用户选择主模型
default_model = llm_models[0]["id"]
print("📋 请选择主模型 (直接回车使用第一个):")
for i, m in enumerate(llm_models):
marker = " [默认]" if i == 0 else ""
print(f" [{i}] {m['id']}{marker}")
choice = input("\n您的选择: ").strip()
if not choice:
selected_llm = llm_models[0]
else:
try:
idx = int(choice)
if 0 <= idx < len(llm_models):
selected_llm = llm_models[idx]
else:
raise ValueError
except ValueError:
print("⚠️ 无效输入,使用默认模型。")
selected_llm = llm_models[0]
print(f"✅ 已选择主模型: {selected_llm['id']}")
# 4. 处理上下文窗口
print(f"\n🔍 检查上下文窗口...")
# 这里我们无法从 API 直接获取 LM Studio 的 Context Length 设置
# 所以我们让用户自己确认,并提供一个合理的默认值
print(f" 注意: OpenClaw 要求上下文窗口 >= {OPENCLAW_MIN_CONTEXT} tokens.")
print(f" 请确保您在 LM Studio 的 'Local Server' 设置中将 'Context Length' 设为 >= {OPENCLAW_MIN_CONTEXT} (推荐 32768).")
user_ctx = input(f"\n请输入您在 LM Studio 中设置的上下文长度 (直接回车默认 {DEFAULT_CONTEXT_WINDOW}): ").strip()
try:
context_window = int(user_ctx) if user_ctx else DEFAULT_CONTEXT_WINDOW
except ValueError:
print(f"⚠️ 无效输入,使用默认值 {DEFAULT_CONTEXT_WINDOW}.")
context_window = DEFAULT_CONTEXT_WINDOW
if context_window < OPENCLAW_MIN_CONTEXT:
print(f"\n⚠️ 警告: 您输入的上下文 ({context_window}) 小于 OpenClaw 要求的最小值 ({OPENCLAW_MIN_CONTEXT})!")
confirm = input(" 是否继续? (y/N): ").strip().lower()
if confirm != 'y':
print("操作已取消。")
sys.exit(0)
# 5. 构建配置
provider_id = "local-lmstudio"
config_path = get_config_path()
print(f"\n⚙️ 正在生成配置 (Provider: {provider_id})...")
# 加载现有配置并备份
config = load_config(config_path)
backup_config(config_path)
# 构建模型配置
all_models = llm_models + embedding_models
model_configs = [build_model_config(m["id"], context_window) for m in all_models]
# 更新主配置
config.setdefault("models", {}).setdefault("providers", {})[provider_id] = {
"baseUrl": lmstudio_url,
"apiKey": "lm-studio", # 任意值,LM Studio 不验证
"api": "openai-completions",
"models": model_configs
}
# 设置默认 Agent
agents_defaults = config.setdefault("agents", {}).setdefault("defaults", {})
agents_defaults["model"] = {"primary": f"{provider_id}/{selected_llm['id']}"}
# 清理旧的模型映射
models_map = agents_defaults.setdefault("models", {})
prefix = f"{provider_id}/"
keys_to_del = [k for k in models_map.keys() if k.startswith(prefix)]
for k in keys_to_del:
del models_map[k]
# 添加新的映射
for m in model_configs:
key = f"{provider_id}/{m['id']}"
models_map[key] = {"alias": provider_id} if m['id'] == selected_llm['id'] else {}
# 配置 Embedding
emb_id = embedding_models[0]["id"] if embedding_models else "text-embedding-ada-002"
agents_defaults["memorySearch"] = {
"enabled": len(embedding_models) > 0,
"provider": "openai",
"model": emb_id,
"remote": {
"baseUrl": lmstudio_url,
"apiKey": "lm-studio",
"batch": {"enabled": False}
}
}
# 6. 保存配置
if save_config(config, config_path):
print(f"\n✅ 配置已成功保存至: {config_path}")
else:
print("\n❌ 保存失败!")
return
# 7. 总结
print("\n" + "=" * 70)
print("📋 配置摘要")
print("=" * 70)
print(f"✓ Provider: {provider_id}")
print(f"✓ 主模型: {provider_id}/{selected_llm['id']}")
print(f"✓ 上下文窗口: {context_window}")
print(f"✓ Embedding: {'已配置' if embedding_models else '未检测到'}")
print(f"\n🚀 下一步操作:")
print(f" 1. 确保 LM Studio 的 'Context Length' 设置正确 (>= {OPENCLAW_MIN_CONTEXT})")
print(f" 2. 启动网关: openclaw gateway")
print(f" 3. 测试对话: openclaw agent --agent main -m \"你好\" --new")
print("=" * 70)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n❌ 用户取消操作")
sys.exit(1)
except Exception as e:
print(f"\n❌ 发生未捕获错误: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
本地模型配置
步骤一、打开lmstudio下载模型选择如下模型:
如果报错:
🥲 Failed to load the model
Failed to load model
error loading model: error loading model architecture: unknown model architecture: 'qwen35'
则本机显卡不适合,需要下载其他模型,或者更新现有的驱动固件(在lmstudio工具中有,设置菜单页中可以更新)。
我的配置信息如下,长文本模型记得配置最大长度支持。
步骤二、点击左侧绿色图标,开启本地模型服务
步骤三、将上述的配置安装脚本python执行
这里就不介绍了,傻瓜式的选择,选择完毕后,重启openclaw即可使用。