66 Optimum 格式 (optimum-intel OVModelForVisualCausalLM): Gemma-4 等
77"""
88
9- import os , sys , time , json , signal , threading
9+ import os , sys , time , json , re , signal , threading
1010import openvino as ov
1111import openvino_genai as ov_genai
1212from wcwidth import wcwidth , wcswidth
@@ -228,6 +228,8 @@ def run_pipe(ctx, reasoning=True, max_tokens=1024, temperature=0.7):
228228
229229 elapsed = time .time () - t0
230230 resp = str (result ).strip ()
231+ if not reasoning :
232+ resp = re .sub (r'</?think>' , '' , resp ).strip ()
231233 print (_json .dumps ({"text" : resp , "time" : round (elapsed , 1 )}, ensure_ascii = False ), flush = True )
232234 except KeyboardInterrupt :
233235 pass
@@ -295,6 +297,8 @@ def _count_tokens(ctx, text):
295297
296298
297299def _char_width (ch ):
300+ if ch == "\n " :
301+ return 0
298302 return max (wcwidth (ch ), 1 )
299303
300304
@@ -303,7 +307,11 @@ def _total_width(chars, start=0, end=None):
303307 end = len (chars )
304308 if start >= end :
305309 return 0
306- return wcswidth ("" .join (chars [start :end ]))
310+ # 只计算当前行(最后一个 \n 之后)的宽度
311+ s = "" .join (chars [start :end ])
312+ if "\n " in s :
313+ s = s .rsplit ("\n " , 1 )[1 ]
314+ return wcswidth (s )
307315
308316
309317def _move_cursor (delta ):
@@ -356,6 +364,17 @@ def readline():
356364 if b == 4 :
357365 break
358366 if b in (13 , 10 ):
367+ # 取当前行(光标所在行,从上一个 \n 到光标)的内容
368+ before = "" .join (buf [:char_pos ])
369+ cur_line = before .rsplit ("\n " , 1 )[1 ] if "\n " in before else before
370+ if cur_line : # 当前行有内容 → 换行继续输入
371+ buf .insert (char_pos , "\n " )
372+ widths .insert (char_pos , 0 )
373+ char_pos += 1
374+ _sys .stdout .write ("\r \n " )
375+ _sys .stdout .flush ()
376+ continue
377+ # 当前行无内容 → 提交
359378 _sys .stdout .write ("\r \n " )
360379 _sys .stdout .flush ()
361380 break
@@ -413,13 +432,24 @@ def readline():
413432 if b in (127 , 8 ):
414433 if char_pos > 0 :
415434 dw = _char_width (buf [char_pos - 1 ])
435+ is_nl = buf [char_pos - 1 ] == "\n "
416436 del buf [char_pos - 1 ]
417437 del widths [char_pos - 1 ]
418438 char_pos -= 1
419- _move_cursor (- dw )
420- tail = "" .join (buf [char_pos :])
421- _sys .stdout .write (tail + " " )
422- _move_cursor (- _total_width (buf [char_pos :]) - 1 )
439+ if is_nl :
440+ _sys .stdout .write ("\033 [A" ) # 光标上移一行
441+ # 清除当前行并重新绘制后续文本
442+ import shutil
443+ cols = shutil .get_terminal_size ().columns
444+ _sys .stdout .write ("\r \033 [K" )
445+ tail = "" .join (buf [char_pos :])
446+ _sys .stdout .write (tail )
447+ _move_cursor (- _total_width (buf [char_pos :]))
448+ else :
449+ _move_cursor (- dw )
450+ tail = "" .join (buf [char_pos :])
451+ _sys .stdout .write (tail + " " )
452+ _move_cursor (- _total_width (buf [char_pos :]) - 1 )
423453 _sys .stdout .flush ()
424454 continue
425455
@@ -644,6 +674,9 @@ def _prog():
644674
645675 reply_text = "" .join (reply_parts )
646676
677+ if not reasoning :
678+ reply_text = re .sub (r'</?think>' , '' , reply_text ).strip ()
679+
647680 # 输出统计
648681 elapsed = time .time () - t0
649682 char_count = len (reply_text .replace (" " , "" ))
@@ -1138,7 +1171,7 @@ def _show_progress():
11381171 thread .start ()
11391172
11401173 thinking_filter = not reasoning
1141- in_think = [thinking_filter ]
1174+ in_think = [False ] # 初始不在 think 块内,由 <think> 标签触发
11421175 reply_parts = []
11431176 _opt_first = [True ]
11441177 try :
@@ -1178,6 +1211,15 @@ def _show_progress():
11781211 else :
11791212 in_think [0 ] = True
11801213 continue
1214+ # 过滤孤立的 </think>(没有配对的 <think>)
1215+ if '</think>' in t :
1216+ idx = t .index ('</think>' )
1217+ after = t [idx + 8 :]
1218+ if after :
1219+ reply_parts .append (after )
1220+ sys .stdout .write (after )
1221+ sys .stdout .flush ()
1222+ continue
11811223 sys .stdout .write (t )
11821224 sys .stdout .flush ()
11831225 reply_parts .append (t )
0 commit comments