diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index ba56b0c24..f9b5e6658 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -9,6 +9,8 @@ on: tags: - "v*.*.*" - "v*" + - "*.*.*" + - "*.*.*-*" jobs: build-amd64: @@ -47,6 +49,7 @@ jobs: tags: | type=ref,event=branch type=ref,event=tag + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} @@ -109,6 +112,7 @@ jobs: tags: | type=ref,event=branch type=ref,event=tag + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} @@ -153,6 +157,7 @@ jobs: tags: | type=ref,event=branch type=ref,event=tag + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} diff --git a/src/chat/knowledge/src/ie_process.py b/src/chat/knowledge/src/ie_process.py index 0bbe21698..ddc5eb023 100644 --- a/src/chat/knowledge/src/ie_process.py +++ b/src/chat/knowledge/src/ie_process.py @@ -6,7 +6,7 @@ from .global_logger import logger from . import prompt_template from .lpmmconfig import global_config, INVALID_ENTITY from .llm_client import LLMClient -from .utils.json_fix import fix_broken_generated_json +from .utils.json_fix import new_fix_broken_generated_json def _entity_extract(llm_client: LLMClient, paragraph: str) -> List[str]: @@ -24,7 +24,7 @@ def _entity_extract(llm_client: LLMClient, paragraph: str) -> List[str]: if "]" in request_result: request_result = request_result[: request_result.rindex("]") + 1] - entity_extract_result = json.loads(fix_broken_generated_json(request_result)) + entity_extract_result = json.loads(new_fix_broken_generated_json(request_result)) entity_extract_result = [ entity @@ -53,7 +53,7 @@ def _rdf_triple_extract(llm_client: LLMClient, paragraph: str, entities: list) - if "]" in request_result: request_result = request_result[: request_result.rindex("]") + 1] - entity_extract_result = json.loads(fix_broken_generated_json(request_result)) + entity_extract_result = json.loads(new_fix_broken_generated_json(request_result)) for triple in entity_extract_result: if len(triple) != 3 or (triple[0] is None or triple[1] is None or triple[2] is None) or "" in triple: diff --git a/src/chat/knowledge/src/utils/json_fix.py b/src/chat/knowledge/src/utils/json_fix.py index a83eb4914..53fa8f36f 100644 --- a/src/chat/knowledge/src/utils/json_fix.py +++ b/src/chat/knowledge/src/utils/json_fix.py @@ -1,4 +1,5 @@ import json +from json_repair import repair_json def _find_unclosed(json_str): @@ -74,3 +75,24 @@ def fix_broken_generated_json(json_str: str) -> str: json_str += closing_map[open_char] return json_str + + +def new_fix_broken_generated_json(json_str: str) -> str: + """ + 使用 json-repair 库修复格式错误的 JSON 字符串。 + + 如果原始 json_str 字符串可以被 json.loads() 成功加载,则直接返回而不进行任何修改。 + + 参数: + json_str (str): 需要修复的格式错误的 JSON 字符串。 + + 返回: + str: 修复后的 JSON 字符串。 + """ + try: + # 尝试加载 JSON 以查看其是否有效 + json.loads(json_str) + return json_str # 如果有效则按原样返回 + except json.JSONDecodeError: + # 如果无效,则尝试修复它 + return repair_json(json_str) diff --git a/src/common/remote.py b/src/common/remote.py index 4b12e26ce..5ffc5ebc1 100644 --- a/src/common/remote.py +++ b/src/common/remote.py @@ -68,30 +68,30 @@ class TelemetryHeartBeatTask(AsyncTask): response = requests.post( f"{TELEMETRY_SERVER_URL}/stat/reg_client", json={"deploy_time": local_storage["deploy_time"]}, + timeout=5, # 设置超时时间为5秒 ) - - logger.debug(f"{TELEMETRY_SERVER_URL}/stat/reg_client") - - logger.debug(local_storage["deploy_time"]) - - logger.debug(response) - - if response.status_code == 200: - data = response.json() - client_id = data.get("mmc_uuid") - if client_id: - # 将UUID存储到本地 - local_storage["mmc_uuid"] = client_id - self.client_uuid = client_id - logger.info(f"成功获取UUID: {self.client_uuid}") - return True # 成功获取UUID,返回True - else: - logger.error("无效的服务端响应") - else: - logger.error(f"请求UUID失败,状态码: {response.status_code}, 响应内容: {response.text}") - except requests.RequestException as e: + except Exception as e: logger.error(f"请求UUID时出错: {e}") # 可能是网络问题 + logger.debug(f"{TELEMETRY_SERVER_URL}/stat/reg_client") + + logger.debug(local_storage["deploy_time"]) + + logger.debug(response) + + if response.status_code == 200: + data = response.json() + if client_id := data.get("mmc_uuid"): + # 将UUID存储到本地 + local_storage["mmc_uuid"] = client_id + self.client_uuid = client_id + logger.info(f"成功获取UUID: {self.client_uuid}") + return True # 成功获取UUID,返回True + else: + logger.error("无效的服务端响应") + else: + logger.error(f"请求UUID失败,状态码: {response.status_code}, 响应内容: {response.text}") + # 请求失败,重试次数+1 try_count += 1 if try_count > 3: @@ -100,47 +100,48 @@ class TelemetryHeartBeatTask(AsyncTask): return False else: # 如果可以重试,等待后继续(指数退避) + logger.info(f"获取UUID失败,将于 {4**try_count} 秒后重试...") await asyncio.sleep(4**try_count) async def _send_heartbeat(self): """向服务器发送心跳""" + headers = { + "Client-UUID": self.client_uuid, + "User-Agent": f"HeartbeatClient/{self.client_uuid[:8]}", + } + + logger.debug(f"正在发送心跳到服务器: {self.server_url}") + + logger.debug(headers) + try: - headers = { - "Client-UUID": self.client_uuid, - "User-Agent": f"HeartbeatClient/{self.client_uuid[:8]}", - } - - logger.debug(f"正在发送心跳到服务器: {self.server_url}") - - logger.debug(headers) - response = requests.post( f"{self.server_url}/stat/client_heartbeat", headers=headers, json=self.info_dict, + timeout=5, # 设置超时时间为5秒 ) - - logger.debug(response) - - # 处理响应 - if 200 <= response.status_code < 300: - # 成功 - logger.debug(f"心跳发送成功,状态码: {response.status_code}") - elif response.status_code == 403: - # 403 Forbidden - logger.error( - "心跳发送失败,403 Forbidden: 可能是UUID无效或未注册。" - "处理措施:重置UUID,下次发送心跳时将尝试重新注册。" - ) - self.client_uuid = None - del local_storage["mmc_uuid"] # 删除本地存储的UUID - else: - # 其他错误 - logger.error(f"心跳发送失败,状态码: {response.status_code}, 响应内容: {response.text}") - - except requests.RequestException as e: + except Exception as e: logger.error(f"心跳发送失败: {e}") + logger.debug(response) + + # 处理响应 + if 200 <= response.status_code < 300: + # 成功 + logger.debug(f"心跳发送成功,状态码: {response.status_code}") + elif response.status_code == 403: + # 403 Forbidden + logger.error( + "心跳发送失败,403 Forbidden: 可能是UUID无效或未注册。" + "处理措施:重置UUID,下次发送心跳时将尝试重新注册。" + ) + self.client_uuid = None + del local_storage["mmc_uuid"] # 删除本地存储的UUID + else: + # 其他错误 + logger.error(f"心跳发送失败,状态码: {response.status_code}, 响应内容: {response.text}") + async def run(self): # 发送心跳 if global_config.telemetry.enable: diff --git a/src/individuality/identity.py b/src/individuality/identity.py index fd0d70f38..f79da547a 100644 --- a/src/individuality/identity.py +++ b/src/individuality/identity.py @@ -8,7 +8,7 @@ class Identity: identity_detail: List[str] # 身份细节描述 height: int # 身高(厘米) - weight: int # 体重(千克) + weight: float # 体重(千克) age: int # 年龄 gender: str # 性别 appearance: str # 外貌特征 @@ -24,7 +24,7 @@ class Identity: self, identity_detail: List[str] = None, height: int = 0, - weight: int = 0, + weight: float = 0, age: int = 0, gender: str = "", appearance: str = "", @@ -61,7 +61,7 @@ class Identity: @classmethod def initialize( - cls, identity_detail: List[str], height: int, weight: int, age: int, gender: str, appearance: str + cls, identity_detail: List[str], height: int, weight: float, age: int, gender: str, appearance: str ) -> "Identity": """初始化身份特征 diff --git a/src/manager/local_store_manager.py b/src/manager/local_store_manager.py index f172d8890..33a30cec7 100644 --- a/src/manager/local_store_manager.py +++ b/src/manager/local_store_manager.py @@ -22,13 +22,21 @@ class LocalStoreManager: def __getitem__(self, item: str) -> str | list | dict | int | float | bool | None: """获取本地存储数据""" - return self.store.get(item, None) + return self.store.get(item) def __setitem__(self, key: str, value: str | list | dict | int | float | bool): """设置本地存储数据""" self.store[key] = value self.save_local_store() + def __delitem__(self, key: str): + """删除本地存储数据""" + if key in self.store: + del self.store[key] + self.save_local_store() + else: + logger.warning(f"尝试删除不存在的键: {key}") + def __contains__(self, item: str) -> bool: """检查本地存储数据是否存在""" return item in self.store