diff --git a/main/xiaozhi-server/config.yaml b/main/xiaozhi-server/config.yaml index b0a94832..27a2f6c1 100644 --- a/main/xiaozhi-server/config.yaml +++ b/main/xiaozhi-server/config.yaml @@ -142,6 +142,7 @@ VAD: min_silence_duration_ms: 700 # 如果说话停顿比较长,可以把这个值设置大一些 LLM: + # 所有openai类型均可以修改超参,以AliLLM为例 # 当前支持的type为openai、dify、ollama,可自行适配 AliLLM: # 定义LLM API类型 @@ -150,6 +151,11 @@ LLM: base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 model_name: qwen-turbo api_key: 你的deepseek web key + temperature: 0.7 # 温度值 + max_tokens: 500 # 最大生成token数 + top_p: 1 + top_k: 50 + frequency_penalty: 0 # 频率惩罚 DoubaoLLM: # 定义LLM API类型 type: openai @@ -198,7 +204,9 @@ LLM: # token申请地址: https://aistudio.google.com/apikey # 若部署地无法访问接口,需要开启科学上网 api_key: 你的gemini web key - model_name: "gemini-1.5-pro" # gemini-1.5-pro 是免费的 + model_name: "gemini-2.0-flash" + http_proxy: "" #"http://127.0.0.1:10808" + https_proxy: "" #http://127.0.0.1:10808" CozeLLM: # 定义LLM API类型 type: coze diff --git a/main/xiaozhi-server/core/providers/llm/gemini/gemini.py b/main/xiaozhi-server/core/providers/llm/gemini/gemini.py index f753ac3e..93c7dcb5 100644 --- a/main/xiaozhi-server/core/providers/llm/gemini/gemini.py +++ b/main/xiaozhi-server/core/providers/llm/gemini/gemini.py @@ -1,14 +1,19 @@ import google.generativeai as genai from core.utils.util import check_model_key from core.providers.llm.base import LLMProviderBase - +from config.logger import setup_logging +import requests +import json +TAG = __name__ +logger = setup_logging() class LLMProvider(LLMProviderBase): def __init__(self, config): """初始化Gemini LLM Provider""" self.model_name = config.get("model_name", "gemini-1.5-pro") self.api_key = config.get("api_key") - + self.http_proxy=config.get("http_proxy") + self.https_proxy = config.get("https_proxy") have_key = check_model_key("LLM", self.api_key) if not have_key: @@ -16,6 +21,19 @@ class LLMProvider(LLMProviderBase): try: # 初始化Gemini客户端 + # 配置代理(如果提供了代理配置) + self.proxies=None + if self.http_proxy is not "" or self.https_proxy is not "": + + self.proxies = { + "http": self.http_proxy, + "https": self.https_proxy, + } + logger.bind(tag=TAG).info(f"Gemini set proxys:{self.proxies}") + # 使用猴子补丁修改 google-generativeai 库的请求会话 + + # 使用 session 对象配置 genai + genai.configure(api_key=self.api_key) self.model = genai.GenerativeModel(self.model_name) @@ -46,26 +64,54 @@ class LLMProvider(LLMProviderBase): if content: chat_history.append({ "role": role, - "parts": [content] + "parts": [{"text":content}] + }) # 获取当前消息 current_msg = dialogue[-1]["content"] - # 创建新的聊天会话 - chat = self.model.start_chat(history=chat_history) + # 构建请求体 + request_body = { + "contents": chat_history + [{"role": "user", "parts": [{"text":current_msg}]}], + "generationConfig": self.generation_config + } - # 发送消息并获取流式响应 - response = chat.send_message( - current_msg, - stream=True, - generation_config=self.generation_config - ) + # 构建请求URL + url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.model_name}:generateContent?key={self.api_key}" - # 处理流式响应 - for chunk in response: - if hasattr(chunk, 'text') and chunk.text: - yield chunk.text + # 构建请求头 + headers = { + "Content-Type": "application/json", + } + + # 发送POST请求,经测试手动 request 无法使用 stream 模式 + if self.proxies: + response = requests.post(url, headers=headers, json=request_body, stream=False, proxies=self.proxies) + try: + data = response.json() # 直接解析JSON + if 'candidates' in data and data['candidates']: + yield data['candidates'][0]['content']['parts'][0]['text'] + else: + yield "未找到候选回复。" + except json.JSONDecodeError as e: + yield f"JSON解码错误:{e}" + except Exception as e: + yield f"发生错误:{e}" + else: + logger.bind(tag=TAG).info(f"Gemini stream mode ") + chat = self.model.start_chat(history=chat_history) + + # 发送消息并获取流式响应 + response = chat.send_message( + current_msg, + stream=True, + generation_config=self.generation_config + ) + # 处理流式响应 + for chunk in response: + if hasattr(chunk, 'text') and chunk.text: + yield chunk.text except Exception as e: error_msg = str(e) @@ -78,3 +124,13 @@ class LLMProvider(LLMProviderBase): yield "【Gemini API key无效】" else: yield f"【Gemini服务响应异常: {error_msg}】" + + + + + except requests.exceptions.RequestException as e: + yield f"请求失败:{e}" + except json.JSONDecodeError as e: + yield f"JSON解码错误:{e}" + except Exception as e: + yield f"发生错误:{e}" diff --git a/main/xiaozhi-server/core/providers/llm/openai/openai.py b/main/xiaozhi-server/core/providers/llm/openai/openai.py index 95cd85f9..b1a9a24e 100644 --- a/main/xiaozhi-server/core/providers/llm/openai/openai.py +++ b/main/xiaozhi-server/core/providers/llm/openai/openai.py @@ -1,7 +1,11 @@ import openai +from config.logger import setup_logging from core.utils.util import check_model_key from core.providers.llm.base import LLMProviderBase +TAG = __name__ +logger = setup_logging() + class LLMProvider(LLMProviderBase): def __init__(self, config): @@ -11,6 +15,8 @@ class LLMProvider(LLMProviderBase): self.base_url = config.get("base_url") else: self.base_url = config.get("url") + self.max_tokens = config.get("max_tokens", 500) + check_model_key("LLM", self.api_key) self.client = openai.OpenAI(api_key=self.api_key, base_url=self.base_url) @@ -19,9 +25,10 @@ class LLMProvider(LLMProviderBase): responses = self.client.chat.completions.create( model=self.model_name, messages=dialogue, - stream=True + stream=True, + max_tokens=self.max_tokens, ) - + is_active = True for chunk in responses: try: @@ -50,12 +57,12 @@ class LLMProvider(LLMProviderBase): model=self.model_name, messages=dialogue, stream=True, - tools=functions, + tools=functions ) - + for chunk in stream: yield chunk.choices[0].delta.content, chunk.choices[0].delta.tool_calls - + except Exception as e: self.logger.bind(tag=TAG).error(f"Error in function call streaming: {e}") - yield {"type": "content", "content": f"【OpenAI服务响应异常: {e}】"} \ No newline at end of file + yield {"type": "content", "content": f"【OpenAI服务响应异常: {e}】"}