diff --git a/main/xiaozhi-server/core/providers/llm/homeassistant/homeassistant.py b/main/xiaozhi-server/core/providers/llm/homeassistant/homeassistant.py
index d875d0d0..1fe8a0d2 100644
--- a/main/xiaozhi-server/core/providers/llm/homeassistant/homeassistant.py
+++ b/main/xiaozhi-server/core/providers/llm/homeassistant/homeassistant.py
@@ -39,13 +39,12 @@ class LLMProvider(LLMProviderBase):
}
# 发起 POST 请求
- response = requests.post(self.api_url, json=payload, headers=headers)
+ with requests.post(self.api_url, json=payload, headers=headers) as response:
+ # 检查请求是否成功
+ response.raise_for_status()
- # 检查请求是否成功
- response.raise_for_status()
-
- # 解析返回数据
- data = response.json()
+ # 解析返回数据
+ data = response.json()
speech = (
data.get("response", {})
.get("speech", {})
diff --git a/main/xiaozhi-server/core/providers/llm/ollama/ollama.py b/main/xiaozhi-server/core/providers/llm/ollama/ollama.py
index c62a432d..ba7ceef8 100644
--- a/main/xiaozhi-server/core/providers/llm/ollama/ollama.py
+++ b/main/xiaozhi-server/core/providers/llm/ollama/ollama.py
@@ -50,43 +50,46 @@ class LLMProvider(LLMProviderBase):
# 用于处理跨chunk的标签
buffer = ""
- for chunk in responses:
- try:
- delta = (
- chunk.choices[0].delta
- if getattr(chunk, "choices", None)
- else None
- )
- content = delta.content if hasattr(delta, "content") else ""
+ try:
+ for chunk in responses:
+ try:
+ delta = (
+ chunk.choices[0].delta
+ if getattr(chunk, "choices", None)
+ else None
+ )
+ content = delta.content if hasattr(delta, "content") else ""
- if content:
- # 将内容添加到缓冲区
- buffer += content
+ if content:
+ # 将内容添加到缓冲区
+ buffer += content
- # 处理缓冲区中的标签
- while "" in buffer and "" in buffer:
- # 找到完整的标签并移除
- pre = buffer.split("", 1)[0]
- post = buffer.split("", 1)[1]
- buffer = pre + post
+ # 处理缓冲区中的标签
+ while "" in buffer and "" in buffer:
+ # 找到完整的标签并移除
+ pre = buffer.split("", 1)[0]
+ post = buffer.split("", 1)[1]
+ buffer = pre + post
- # 处理只有开始标签的情况
- if "" in buffer:
- is_active = False
- buffer = buffer.split("", 1)[0]
+ # 处理只有开始标签的情况
+ if "" in buffer:
+ is_active = False
+ buffer = buffer.split("", 1)[0]
- # 处理只有结束标签的情况
- if "" in buffer:
- is_active = True
- buffer = buffer.split("", 1)[1]
+ # 处理只有结束标签的情况
+ if "" in buffer:
+ is_active = True
+ buffer = buffer.split("", 1)[1]
- # 如果当前处于活动状态且缓冲区有内容,则输出
- if is_active and buffer:
- yield buffer
- buffer = "" # 清空缓冲区
+ # 如果当前处于活动状态且缓冲区有内容,则输出
+ if is_active and buffer:
+ yield buffer
+ buffer = "" # 清空缓冲区
- except Exception as e:
- logger.bind(tag=TAG).error(f"Error processing chunk: {e}")
+ except Exception as e:
+ logger.bind(tag=TAG).error(f"Error processing chunk: {e}")
+ finally:
+ responses.close()
def response_with_functions(self, session_id, dialogue, functions=None):
# 如果是qwen3模型,在用户最后一条消息中添加/no_think指令
@@ -117,49 +120,52 @@ class LLMProvider(LLMProviderBase):
is_active = True
buffer = ""
- for chunk in stream:
- try:
- delta = (
- chunk.choices[0].delta
- if getattr(chunk, "choices", None)
- else None
- )
- content = delta.content if hasattr(delta, "content") else None
- tool_calls = (
- delta.tool_calls if hasattr(delta, "tool_calls") else None
- )
+ try:
+ for chunk in stream:
+ try:
+ delta = (
+ chunk.choices[0].delta
+ if getattr(chunk, "choices", None)
+ else None
+ )
+ content = delta.content if hasattr(delta, "content") else None
+ tool_calls = (
+ delta.tool_calls if hasattr(delta, "tool_calls") else None
+ )
- # 如果是工具调用,直接传递
- if tool_calls:
- yield None, tool_calls
+ # 如果是工具调用,直接传递
+ if tool_calls:
+ yield None, tool_calls
+ continue
+
+ # 处理文本内容
+ if content:
+ # 将内容添加到缓冲区
+ buffer += content
+
+ # 处理缓冲区中的标签
+ while "" in buffer and "" in buffer:
+ # 找到完整的标签并移除
+ pre = buffer.split("", 1)[0]
+ post = buffer.split("", 1)[1]
+ buffer = pre + post
+
+ # 处理只有开始标签的情况
+ if "" in buffer:
+ is_active = False
+ buffer = buffer.split("", 1)[0]
+
+ # 处理只有结束标签的情况
+ if "" in buffer:
+ is_active = True
+ buffer = buffer.split("", 1)[1]
+
+ # 如果当前处于活动状态且缓冲区有内容,则输出
+ if is_active and buffer:
+ yield buffer, None
+ buffer = "" # 清空缓冲区
+ except Exception as e:
+ logger.bind(tag=TAG).error(f"Error processing function chunk: {e}")
continue
-
- # 处理文本内容
- if content:
- # 将内容添加到缓冲区
- buffer += content
-
- # 处理缓冲区中的标签
- while "" in buffer and "" in buffer:
- # 找到完整的标签并移除
- pre = buffer.split("", 1)[0]
- post = buffer.split("", 1)[1]
- buffer = pre + post
-
- # 处理只有开始标签的情况
- if "" in buffer:
- is_active = False
- buffer = buffer.split("", 1)[0]
-
- # 处理只有结束标签的情况
- if "" in buffer:
- is_active = True
- buffer = buffer.split("", 1)[1]
-
- # 如果当前处于活动状态且缓冲区有内容,则输出
- if is_active and buffer:
- yield buffer, None
- buffer = "" # 清空缓冲区
- except Exception as e:
- logger.bind(tag=TAG).error(f"Error processing function chunk: {e}")
- continue
+ finally:
+ stream.close()
diff --git a/main/xiaozhi-server/core/providers/llm/openai/openai.py b/main/xiaozhi-server/core/providers/llm/openai/openai.py
index ba0498e5..ed0b5e97 100644
--- a/main/xiaozhi-server/core/providers/llm/openai/openai.py
+++ b/main/xiaozhi-server/core/providers/llm/openai/openai.py
@@ -115,21 +115,24 @@ class LLMProvider(LLMProviderBase):
responses = self.client.chat.completions.create(**request_params)
is_active = True
- for chunk in responses:
- try:
- delta = chunk.choices[0].delta if getattr(chunk, "choices", None) else None
- content = getattr(delta, "content", "") if delta else ""
- except IndexError:
- content = ""
- if content:
- if "" in content:
- is_active = False
- content = content.split("")[0]
- if "" in content:
- is_active = True
- content = content.split("")[-1]
- if is_active:
- yield content
+ try:
+ for chunk in responses:
+ try:
+ delta = chunk.choices[0].delta if getattr(chunk, "choices", None) else None
+ content = getattr(delta, "content", "") if delta else ""
+ except IndexError:
+ content = ""
+ if content:
+ if "" in content:
+ is_active = False
+ content = content.split("")[0]
+ if "" in content:
+ is_active = True
+ content = content.split("")[-1]
+ if is_active:
+ yield content
+ finally:
+ responses.close()
def response_with_functions(self, session_id, dialogue, functions=None, **kwargs):
dialogue = self.normalize_dialogue(dialogue)
@@ -157,16 +160,19 @@ class LLMProvider(LLMProviderBase):
stream = self.client.chat.completions.create(**request_params)
- for chunk in stream:
- if getattr(chunk, "choices", None):
- delta = chunk.choices[0].delta
- content = getattr(delta, "content", "")
- tool_calls = getattr(delta, "tool_calls", None)
- yield content, tool_calls
- elif isinstance(getattr(chunk, "usage", None), CompletionUsage):
- usage_info = getattr(chunk, "usage", None)
- logger.bind(tag=TAG).info(
- f"Token 消耗:输入 {getattr(usage_info, 'prompt_tokens', '未知')},"
- f"输出 {getattr(usage_info, 'completion_tokens', '未知')},"
- f"共计 {getattr(usage_info, 'total_tokens', '未知')}"
- )
+ try:
+ for chunk in stream:
+ if getattr(chunk, "choices", None):
+ delta = chunk.choices[0].delta
+ content = getattr(delta, "content", "")
+ tool_calls = getattr(delta, "tool_calls", None)
+ yield content, tool_calls
+ elif isinstance(getattr(chunk, "usage", None), CompletionUsage):
+ usage_info = getattr(chunk, "usage", None)
+ logger.bind(tag=TAG).info(
+ f"Token 消耗:输入 {getattr(usage_info, 'prompt_tokens', '未知')},"
+ f"输出 {getattr(usage_info, 'completion_tokens', '未知')},"
+ f"共计 {getattr(usage_info, 'total_tokens', '未知')}"
+ )
+ finally:
+ stream.close()
diff --git a/main/xiaozhi-server/core/providers/llm/xinference/xinference.py b/main/xiaozhi-server/core/providers/llm/xinference/xinference.py
index f6f71455..b44ce023 100644
--- a/main/xiaozhi-server/core/providers/llm/xinference/xinference.py
+++ b/main/xiaozhi-server/core/providers/llm/xinference/xinference.py
@@ -74,12 +74,15 @@ class LLMProvider(LLMProviderBase):
tools=functions,
)
- for chunk in stream:
- delta = chunk.choices[0].delta
- content = delta.content
- tool_calls = delta.tool_calls
+ try:
+ for chunk in stream:
+ delta = chunk.choices[0].delta
+ content = delta.content
+ tool_calls = delta.tool_calls
- if content:
- yield content, tool_calls
- elif tool_calls:
- yield None, tool_calls
+ if content:
+ yield content, tool_calls
+ elif tool_calls:
+ yield None, tool_calls
+ finally:
+ stream.close()