Skip to content

Commit 27dd90c

Browse files
committed
feat: enhance token management and normalize content handling in chat model
1 parent 7d3f92b commit 27dd90c

File tree

4 files changed

+62
-10
lines changed

4 files changed

+62
-10
lines changed

apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ def event_content(response,
9393
reasoning_content_chunk = chunk.additional_kwargs.get('reasoning_content', '')
9494
else:
9595
reasoning_content_chunk = reasoning_chunk.get('reasoning_content')
96+
content_chunk = reasoning._normalize_content(content_chunk)
9697
all_text += content_chunk
9798
if reasoning_content_chunk is None:
9899
reasoning_content_chunk = ''
@@ -191,13 +192,15 @@ def execute(self, message_list: List[BaseMessage],
191192
manage, padding_problem_text, chat_user_id, chat_user_type,
192193
no_references_setting,
193194
model_setting,
194-
mcp_enable, mcp_tool_ids, mcp_servers, mcp_source, tool_enable, tool_ids, mcp_output_enable)
195+
mcp_enable, mcp_tool_ids, mcp_servers, mcp_source, tool_enable, tool_ids,
196+
mcp_output_enable)
195197
else:
196198
return self.execute_block(message_list, chat_id, problem_text, post_response_handler, chat_model,
197199
paragraph_list,
198200
manage, padding_problem_text, chat_user_id, chat_user_type, no_references_setting,
199201
model_setting,
200-
mcp_enable, mcp_tool_ids, mcp_servers, mcp_source, tool_enable, tool_ids, mcp_output_enable)
202+
mcp_enable, mcp_tool_ids, mcp_servers, mcp_source, tool_enable, tool_ids,
203+
mcp_output_enable)
201204

202205
def get_details(self, manage, **kwargs):
203206
return {
@@ -264,7 +267,6 @@ def _handle_mcp_request(self, mcp_enable, tool_enable, mcp_source, mcp_servers,
264267

265268
return None
266269

267-
268270
def get_stream_result(self, message_list: List[BaseMessage],
269271
chat_model: BaseChatModel = None,
270272
paragraph_list=None,
@@ -294,7 +296,8 @@ def get_stream_result(self, message_list: List[BaseMessage],
294296
else:
295297
# 处理 MCP 请求
296298
mcp_result = self._handle_mcp_request(
297-
mcp_enable, tool_enable, mcp_source, mcp_servers, mcp_tool_ids, tool_ids, mcp_output_enable, chat_model, message_list,
299+
mcp_enable, tool_enable, mcp_source, mcp_servers, mcp_tool_ids, tool_ids, mcp_output_enable, chat_model,
300+
message_list,
298301
)
299302
if mcp_result:
300303
return mcp_result, True
@@ -319,7 +322,8 @@ def execute_stream(self, message_list: List[BaseMessage],
319322
tool_ids=None,
320323
mcp_output_enable=True):
321324
chat_result, is_ai_chat = self.get_stream_result(message_list, chat_model, paragraph_list,
322-
no_references_setting, problem_text, mcp_enable, mcp_tool_ids, mcp_servers, mcp_source, tool_enable, tool_ids,
325+
no_references_setting, problem_text, mcp_enable, mcp_tool_ids,
326+
mcp_servers, mcp_source, tool_enable, tool_ids,
323327
mcp_output_enable)
324328
chat_record_id = uuid.uuid7()
325329
r = StreamingHttpResponse(
@@ -394,7 +398,9 @@ def execute_block(self, message_list: List[BaseMessage],
394398
# 调用模型
395399
try:
396400
chat_result, is_ai_chat = self.get_block_result(message_list, chat_model, paragraph_list,
397-
no_references_setting, problem_text, mcp_enable, mcp_tool_ids, mcp_servers, mcp_source, tool_enable, tool_ids, mcp_output_enable)
401+
no_references_setting, problem_text, mcp_enable,
402+
mcp_tool_ids, mcp_servers, mcp_source, tool_enable,
403+
tool_ids, mcp_output_enable)
398404
if is_ai_chat:
399405
request_token = chat_model.get_num_tokens_from_messages(message_list)
400406
response_token = chat_model.get_num_tokens(chat_result.content)

apps/application/flow/tools.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ def get_end_reasoning_content(self):
4848
return r
4949
return {'content': '', 'reasoning_content': ''}
5050

51+
def _normalize_content(self, content):
52+
"""将不同类型的内容统一转换为字符串"""
53+
if isinstance(content, str):
54+
return content
55+
elif isinstance(content, list):
56+
# 处理包含多种内容类型的列表
57+
normalized_parts = []
58+
for item in content:
59+
if isinstance(item, dict):
60+
if item.get('type') == 'text':
61+
normalized_parts.append(item.get('text', ''))
62+
return ''.join(normalized_parts)
63+
else:
64+
return str(content)
65+
5166
def get_reasoning_content(self, chunk):
5267
# 如果没有开始思考过程标签那么就全是结果
5368
if self.reasoning_content_start_tag is None or len(self.reasoning_content_start_tag) == 0:
@@ -56,6 +71,7 @@ def get_reasoning_content(self, chunk):
5671
# 如果没有结束思考过程标签那么就全部是思考过程
5772
if self.reasoning_content_end_tag is None or len(self.reasoning_content_end_tag) == 0:
5873
return {'content': '', 'reasoning_content': chunk.content}
74+
chunk.content = self._normalize_content(chunk.content)
5975
self.all_content += chunk.content
6076
if not self.reasoning_content_is_start and len(self.all_content) >= self.reasoning_content_start_tag_len:
6177
if self.all_content.startswith(self.reasoning_content_start_tag):
@@ -202,6 +218,7 @@ def to_stream_response_simple(stream_event):
202218
r['Cache-Control'] = 'no-cache'
203219
return r
204220

221+
205222
tool_message_json_template = """
206223
```json
207224
%s

apps/models_provider/impl/azure_model_provider/credential/llm.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ def is_valid(self, model_type: str, model_name, model_credential: Dict[str, obje
6666
return False
6767
try:
6868
model = provider.get_model(model_type, model_name, model_credential, **model_params)
69-
model.invoke([HumanMessage(content=gettext('Hello'))])
69+
res = model.invoke([HumanMessage(content=gettext('Hello'))])
70+
print( res)
7071
except Exception as e:
7172
traceback.print_exc()
7273
if isinstance(e, AppApiException) or isinstance(e, BadRequestError):

apps/models_provider/impl/azure_model_provider/model/azure_chat_model.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
@desc:
88
"""
99

10-
from typing import List, Dict
10+
from typing import List, Dict, Optional, Any
1111

12+
from langchain_core.language_models import LanguageModelInput
1213
from langchain_core.messages import BaseMessage, get_buffer_string
14+
from langchain_core.runnables import RunnableConfig
1315
from langchain_openai import AzureChatOpenAI
1416

1517
from common.config.tokenizer_manage_config import TokenizerManage
@@ -36,16 +38,42 @@ def new_instance(model_type, model_name, model_credential: Dict[str, object], **
3638
streaming=True,
3739
)
3840

41+
def get_last_generation_info(self) -> Optional[Dict[str, Any]]:
42+
return self.__dict__.get('_last_generation_info')
43+
3944
def get_num_tokens_from_messages(self, messages: List[BaseMessage]) -> int:
4045
try:
41-
return super().get_num_tokens_from_messages(messages)
46+
return self.get_last_generation_info().get('input_tokens', 0)
4247
except Exception as e:
4348
tokenizer = TokenizerManage.get_tokenizer()
4449
return sum([len(tokenizer.encode(get_buffer_string([m]))) for m in messages])
4550

4651
def get_num_tokens(self, text: str) -> int:
4752
try:
48-
return super().get_num_tokens(text)
53+
return self.get_last_generation_info().get('output_tokens', 0)
4954
except Exception as e:
5055
tokenizer = TokenizerManage.get_tokenizer()
5156
return len(tokenizer.encode(text))
57+
58+
def invoke(
59+
self,
60+
input: LanguageModelInput,
61+
config: Optional[RunnableConfig] = None,
62+
*,
63+
stop: Optional[list[str]] = None,
64+
**kwargs: Any,
65+
) -> BaseMessage:
66+
message = super().invoke(input, config, stop=stop, **kwargs)
67+
if isinstance(message.content, str):
68+
return message
69+
elif isinstance(message.content, list):
70+
# 构造新的响应消息返回
71+
content = message.content
72+
normalized_parts = []
73+
for item in content:
74+
if isinstance(item, dict):
75+
if item.get('type') == 'text':
76+
normalized_parts.append(item.get('text', ''))
77+
message.content = ''.join(normalized_parts)
78+
self.__dict__.setdefault('_last_generation_info', {}).update(message.usage_metadata)
79+
return message

0 commit comments

Comments
 (0)