@@ -66,7 +66,7 @@ def __init__(self):
6666 self .default_user_tags = {"favorites" : []}
6767
6868 # 默认标签选择
69- self .default_tags_selection = {"selected_file" : "default .csv" }
69+ self .default_tags_selection = {"selected_file" : "用户标签 .csv" }
7070
7171
7272
@@ -358,28 +358,37 @@ def load_tags_csv(self, filename: str) -> dict:
358358 return {} # 空文件
359359
360360 for row in reader :
361- if len (row ) < 3 :
361+ # 过滤无效行
362+ if not row or not any (cell .strip () for cell in row ):
363+ continue
364+
365+ # 至少需要两列:标签名, 标签值
366+ if len (row ) < 2 :
362367 continue
363368
364369 tag_name = row [0 ].strip ()
365370 tag_value = row [1 ].strip ()
366- # 分类路径:从第3列开始,过滤空值
367- categories = [c .strip () for c in row [2 :] if c .strip ()]
368371
369- if not tag_name or not categories :
372+ if not tag_name :
370373 continue
374+
375+ # 分类路径:从第3列开始,过滤空值
376+ categories = [c .strip () for c in row [2 :] if c .strip ()]
371377
372378 # 构建嵌套结构
373379 current = result
374380 for cat in categories :
375- if cat not in current :
381+ if cat not in current or not isinstance ( current [ cat ], dict ) :
376382 current [cat ] = {}
377383 current = current [cat ]
378384
385+ # 处理空分类占位符:只创建分类结构,不添加标签
386+ if tag_name == "__empty__" or tag_name == "__placeholder__" :
387+ continue
388+
379389 # 添加标签
380390 current [tag_name ] = tag_value
381391
382- # self._log(f"成功加载CSV文件: {filename} (编码: {encoding})")
383392 return result
384393 except UnicodeDecodeError :
385394 continue
@@ -396,25 +405,57 @@ def save_tags_csv(self, filename: str, tags: dict) -> bool:
396405
397406 try :
398407 rows = []
408+ max_depth = 0
399409
400410 def extract_tags (obj , path : list ):
411+ nonlocal max_depth
412+ # 确保 obj 是字典类型
413+ if not isinstance (obj , dict ):
414+ return
415+
416+ # 如果是空分类(空字典),添加占位行
417+ if len (obj ) == 0 and path :
418+ # 使用 __empty__ 作为占位符标记空分类
419+ rows .append (["__empty__" , "" ] + path )
420+ max_depth = max (max_depth , len (path ))
421+ return
422+
401423 for key , value in obj .items ():
402424 if isinstance (value , str ):
403425 rows .append ([key , value ] + path )
426+ max_depth = max (max_depth , len (path ))
404427 elif isinstance (value , dict ):
405428 extract_tags (value , path + [key ])
406429
407- for level1_name , level1_content in tags .items ():
408- if isinstance (level1_content , dict ):
409- extract_tags (level1_content , [level1_name ])
430+ # 提取所有标签
431+ extract_tags (tags , [])
432+
433+ if not rows :
434+ self ._log (f"保存CSV标签: 数据为空" )
435+ # 如果数据为空,写入只含表头的文件或保持现状?
436+ # 通常为了防止误删,如果 tags 为空暂不操作或清空文件。
437+ # 这里选择写入表头:
438+ with open (csv_path , "w" , encoding = "utf-8-sig" , newline = "" ) as f :
439+ writer = csv .writer (f )
440+ writer .writerow (["标签名" , "标签值" ])
441+ return True
442+
443+ # 动态构建表头
444+ header = ["标签名" , "标签值" ]
445+ for i in range (max_depth ):
446+ num_zh = ["一" , "二" , "三" , "四" , "五" , "六" , "七" , "八" , "九" , "十" ]
447+ suffix = num_zh [i ] if i < len (num_zh ) else str (i + 1 )
448+ header .append (f"{ suffix } 级分类" )
410449
411450 with open (csv_path , "w" , encoding = "utf-8-sig" , newline = "" ) as f :
412451 writer = csv .writer (f )
413- writer .writerow ([ "标签名" , "标签值" , "一级分类" , "二级分类" , "三级分类" , "四级分类" ] )
452+ writer .writerow (header )
414453 for row in rows :
415- while len (row ) < 6 :
454+ # 补齐长度以匹配表头
455+ while len (row ) < len (header ):
416456 row .append ("" )
417- writer .writerow (row [:6 ])
457+ # 确保 row 长度不超过表头(防御性)
458+ writer .writerow (row [:len (header )])
418459
419460 return True
420461 except Exception as e :
@@ -732,7 +773,7 @@ def get_vision_config(self):
732773 "base_url" : service .get ('base_url' , '' ),
733774 "api_key" : api_key ,
734775 "temperature" : target_model .get ('temperature' , 0.7 ),
735- "max_tokens" : target_model .get ('max_tokens' , 500 ),
776+ "max_tokens" : target_model .get ('max_tokens' , 1024 ),
736777 "top_p" : target_model .get ('top_p' , 0.9 ),
737778 "auto_unload" : service .get ('auto_unload' , True ) if service .get ('type' ) == 'ollama' else None ,
738779 "providers" : {} # v2.0中不再使用此字段
@@ -746,7 +787,7 @@ def _get_empty_vision_config(self):
746787 "base_url" : "" ,
747788 "api_key" : "" ,
748789 "temperature" : 0.7 ,
749- "max_tokens" : 500 ,
790+ "max_tokens" : 1024 ,
750791 "top_p" : 0.9 ,
751792 "providers" : {}
752793 }
@@ -1558,7 +1599,7 @@ def set_current_service(self, service_type: str, service_id: str, model_name: st
15581599 # --- 模型管理方法 ---
15591600
15601601 def add_model_to_service (self , service_id : str , model_type : str , model_name : str ,
1561- temperature : float = 0.7 , top_p : float = 0.9 , max_tokens : int = 512 ):
1602+ temperature : float = 0.7 , top_p : float = 0.9 , max_tokens : int = 1024 ):
15621603 """添加模型到服务商"""
15631604 try :
15641605 config = self .load_config ()
0 commit comments