调整相关逻辑

This commit is contained in:
Sakura-RanChen committed 2026-11-03 11:53:21 +08:00
1 parent 7f0d416e66
commit e09df59c13
5 files changed
+47 -9

No files matched your search

@@ -64,6 +64,27 @@ public class OpenAIStyleLLMServiceImpl implements LLMService {
private static final String DEFAULT_TITLE_PROMPT = "请根据以下对话内容,生成一个简洁的会话标题(约15字以内),只返回标题,不要包含任何解释或标点符号:\n{conversation}";
/**
* Ollama的OpenAI兼容端点位于{base_url}/v1下,与xiaozhi-server侧ollama provider逻辑保持一致:
* 剥离用户误填的完整端点后缀后,仅对不含路径的纯主机地址补/v1
*/
private static String normalizeOllamaBaseUrl(String baseUrl) {
if (baseUrl == null) {
return null;
}
String url = baseUrl.trim();
if (url.endsWith("/chat/completions")) {
url = url.substring(0, url.length() - "/chat/completions".length());
}
while (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
if (url.replaceFirst("^https?://[^/]+", "").isEmpty()) {
url = url + "/v1";
}
return url;
}
@Override
public String generateSummary(String conversation) {
return generateSummary(conversation, null, null);
@@ -101,6 +122,9 @@ public class OpenAIStyleLLMServiceImpl implements LLMService {
String baseUrl = configJson.getStr("base_url");
String model = configJson.getStr("model_name");
String apiKey = configJson.getStr("api_key");
if ("ollama".equalsIgnoreCase(configJson.getStr("type"))) {
baseUrl = normalizeOllamaBaseUrl(baseUrl);
}
Double temperature = configJson.getDouble("temperature");
Integer maxTokens = configJson.getInt("max_tokens");
@@ -196,6 +220,9 @@ public class OpenAIStyleLLMServiceImpl implements LLMService {
String baseUrl = configJson.getStr("base_url");
String model = configJson.getStr("model_name");
String apiKey = configJson.getStr("api_key");
if ("ollama".equalsIgnoreCase(configJson.getStr("type"))) {
baseUrl = normalizeOllamaBaseUrl(baseUrl);
}
if (StringUtils.isBlank(baseUrl) || StringUtils.isBlank(apiKey)) {
log.error("LLM配置不完整,baseUrl或apiKey为空");
@@ -354,6 +381,9 @@ public class OpenAIStyleLLMServiceImpl implements LLMService {
String baseUrl = configJson.getStr("base_url");
String model = configJson.getStr("model_name");
String apiKey = configJson.getStr("api_key");
if ("ollama".equalsIgnoreCase(configJson.getStr("type"))) {
baseUrl = normalizeOllamaBaseUrl(baseUrl);
}
if (StringUtils.isBlank(baseUrl) || StringUtils.isBlank(apiKey)) {
log.error("LLM配置不完整,baseUrl或apiKey为空");
@@ -1,5 +1,6 @@
from config.logger import setup_logging
from openai import OpenAI
from urllib.parse import urlsplit
import json
from core.providers.llm.base import LLMProviderBase
@@ -10,13 +11,15 @@ logger = setup_logging()
class LLMProvider(LLMProviderBase):
def __init__(self, config):
self.model_name = config.get("model_name")
self.base_url = (config.get("base_url") or "http://localhost:11434").strip().rstrip("/")
self.base_url = (
str(config.get("base_url") or "").strip() or "http://localhost:11434"
).rstrip("/")
# 兼容处理用户输入完整端点的情况
if self.base_url.endswith("/chat/completions"):
self.base_url = self.base_url[:-len("/chat/completions")].rstrip("/")
# Initialize OpenAI client with Ollama base URL
# 如果没有v1,增加v1
if not self.base_url.endswith("/v1"):
# 纯主机地址补/v1(Ollama默认约定);带路径的地址尊重用户输入,不再改写
if not urlsplit(self.base_url).path.strip("/"):
self.base_url = f"{self.base_url}/v1"
self.client = OpenAI(
@@ -119,7 +119,12 @@ class LLMPerformanceTester:
return chunks, first_token_time
async def _check_ollama_service(self, base_url: str, model_name: str) -> bool:
"""异步检查 Ollama 服务状态"""
"""异步检查 Ollama 服务状态(兼容带/v1或完整端点的base_url写法)"""
base_url = base_url.strip().rstrip("/")
if base_url.endswith("/chat/completions"):
base_url = base_url[: -len("/chat/completions")].rstrip("/")
if base_url.endswith("/v1"):
base_url = base_url[: -len("/v1")].rstrip("/")
async with aiohttp.ClientSession() as session:
try:
async with session.get(f"{base_url}/api/version") as response:
@@ -230,7 +235,7 @@ class LLMPerformanceTester:
"""异步测试单个 LLM 性能"""
try:
# 对于 Ollama,跳过 api_key 检查并进行特殊处理
if llm_name == "Ollama":
if llm_name == "OllamaLLM" or str(config.get("type", "")).lower() == "ollama":
base_url = config.get("base_url", "http://localhost:11434")
model_name = config.get("model_name")
if not model_name:
@@ -474,7 +479,7 @@ class LLMPerformanceTester:
continue
# 对于 Ollama,先检查服务状态
if llm_name == "Ollama":
if llm_name == "OllamaLLM" or str(config.get("type", "")).lower() == "ollama":
base_url = config.get("base_url", "http://localhost:11434")
model_name = config.get("model_name")
if not model_name:
+3
View File
@@ -391,6 +391,9 @@ def _check_modules_ready() -> None:
f"{module}.{provider_name} 配置缺失(CFG 字典里没这个 provider)"
)
continue
# Ollama免鉴权供应器无需真实key,跳过占位符检查
if str(cfg.get("type", "")).lower() == "ollama":
continue
secret_keys_present = [k for k in _SECRET_FIELDS if k in cfg]
if secret_keys_present and not any(
has_real_key(cfg, k) for k in secret_keys_present
-3
View File
@@ -50,9 +50,6 @@ def _build_provider():
x in cfg.get("user_id", "") for x in ["你的"]
):
pytest.skip("LLM 'CozeLLM' 的 bot_id/user_id 未配置")
elif name == "Ollama":
if not cfg.get("model_name"):
pytest.skip("LLM 'Ollama' 的 model_name 未配置")
elif not has_real_key(cfg, "api_key"):
if LIVE_API_TESTS:
pytest.skip(f"LLM '{name}' 的 api_key 未配置")