Skip to content

Commit 4490075

Browse files
committed
✨ Agent duplicate name handling logic improvement #1622
[Specification Details] 1.Extract the LLM call method from prompt_service to llm_utils to avoid circular calls.
1 parent 9d0491a commit 4490075

File tree

5 files changed

+363
-294
lines changed

5 files changed

+363
-294
lines changed

backend/services/agent_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@
5555
from services.memory_config_service import build_memory_context
5656
from services.remote_mcp_service import add_remote_mcp_server_list
5757
from services.tool_configuration_service import update_tool_list
58-
from services.prompt_service import call_llm_for_system_prompt
5958
from utils.auth_utils import get_current_user_info, get_user_language
6059
from utils.config_utils import tenant_config_manager
6160
from utils.memory_utils import build_memory_config
6261
from utils.thread_utils import submit
6362
from utils.prompt_template_utils import get_prompt_generate_prompt_template
63+
from utils.llm_utils import call_llm_for_system_prompt
6464

6565
# Import monitoring utilities
6666
from utils.monitoring import monitoring_manager

backend/services/prompt_service.py

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
from typing import Optional, List
66

77
from jinja2 import StrictUndefined, Template
8-
from smolagents import OpenAIServerModel
98

10-
from consts.const import LANGUAGE, MESSAGE_ROLE, THINK_END_PATTERN, THINK_START_PATTERN
9+
from consts.const import LANGUAGE
1110
from consts.model import AgentInfoRequest
1211
from database.agent_db import update_agent, search_agent_info_by_agent_id, query_all_agent_info_by_tenant_id, \
1312
query_sub_agents_id_list
14-
from database.model_management_db import get_model_by_model_id
1513
from database.tool_db import query_tools_by_ids
1614
from services.agent_service import (
1715
get_enable_tool_id_by_agent_id,
@@ -22,92 +20,13 @@
2220
_generate_unique_agent_name_with_suffix,
2321
_generate_unique_display_name_with_suffix
2422
)
25-
from utils.config_utils import get_model_name_from_config
23+
from utils.llm_utils import call_llm_for_system_prompt
2624
from utils.prompt_template_utils import get_prompt_generate_prompt_template
2725

2826
# Configure logging
2927
logger = logging.getLogger("prompt_service")
3028

3129

32-
def _process_thinking_tokens(new_token: str, is_thinking: bool, token_join: list, callback=None) -> bool:
33-
"""
34-
Process tokens to filter out thinking content between <think> and </think> tags
35-
36-
Args:
37-
new_token: Current token from LLM stream
38-
is_thinking: Current thinking state
39-
token_join: List to accumulate non-thinking tokens
40-
callback: Callback function for streaming output
41-
42-
Returns:
43-
bool: updated_is_thinking
44-
"""
45-
# Handle thinking mode
46-
if is_thinking:
47-
return THINK_END_PATTERN not in new_token
48-
49-
# Handle start of thinking
50-
if THINK_START_PATTERN in new_token:
51-
return True
52-
53-
# Normal token processing
54-
token_join.append(new_token)
55-
if callback:
56-
callback("".join(token_join))
57-
58-
return False
59-
60-
61-
def call_llm_for_system_prompt(model_id: int, user_prompt: str, system_prompt: str, callback=None, tenant_id: str = None) -> str:
62-
"""
63-
Call LLM to generate system prompt
64-
65-
Args:
66-
model_id: select model for generate prompt
67-
user_prompt: description of the current task
68-
system_prompt: system prompt for the LLM
69-
callback: callback function
70-
tenant_id: tenant id
71-
72-
Returns:
73-
str: Generated system prompt
74-
"""
75-
76-
llm_model_config = get_model_by_model_id(model_id=model_id, tenant_id=tenant_id)
77-
78-
llm = OpenAIServerModel(
79-
model_id=get_model_name_from_config(
80-
llm_model_config) if llm_model_config else "",
81-
api_base=llm_model_config.get("base_url", ""),
82-
api_key=llm_model_config.get("api_key", ""),
83-
temperature=0.3,
84-
top_p=0.95
85-
)
86-
messages = [{"role": MESSAGE_ROLE["SYSTEM"], "content": system_prompt},
87-
{"role": MESSAGE_ROLE["USER"], "content": user_prompt}]
88-
try:
89-
completion_kwargs = llm._prepare_completion_kwargs(
90-
messages=messages,
91-
model=llm.model_id,
92-
temperature=0.3,
93-
top_p=0.95
94-
)
95-
current_request = llm.client.chat.completions.create(
96-
stream=True, **completion_kwargs)
97-
token_join = []
98-
is_thinking = False
99-
for chunk in current_request:
100-
new_token = chunk.choices[0].delta.content
101-
if new_token is not None:
102-
is_thinking = _process_thinking_tokens(
103-
new_token, is_thinking, token_join, callback
104-
)
105-
return "".join(token_join)
106-
except Exception as e:
107-
logger.error(f"Failed to generate prompt from LLM: {str(e)}")
108-
raise e
109-
110-
11130
def gen_system_prompt_streamable(agent_id: int, model_id: int, task_description: str, user_id: str, tenant_id: str, language: str, tool_ids: Optional[List[int]] = None, sub_agent_ids: Optional[List[int]] = None):
11231
for system_prompt in generate_and_save_system_prompt_impl(
11332
agent_id=agent_id,

backend/utils/llm_utils.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import logging
2+
from typing import Callable, List, Optional
3+
4+
from smolagents import OpenAIServerModel
5+
6+
from consts.const import MESSAGE_ROLE, THINK_END_PATTERN, THINK_START_PATTERN
7+
from database.model_management_db import get_model_by_model_id
8+
from utils.config_utils import get_model_name_from_config
9+
10+
logger = logging.getLogger("llm_utils")
11+
12+
13+
def _process_thinking_tokens(
14+
new_token: str,
15+
is_thinking: bool,
16+
token_join: List[str],
17+
callback: Optional[Callable[[str], None]] = None,
18+
) -> bool:
19+
"""
20+
Process tokens to filter out thinking content between <think> and </think> tags.
21+
"""
22+
if is_thinking:
23+
return THINK_END_PATTERN not in new_token
24+
25+
if THINK_START_PATTERN in new_token:
26+
return True
27+
28+
token_join.append(new_token)
29+
if callback:
30+
callback("".join(token_join))
31+
32+
return False
33+
34+
35+
def call_llm_for_system_prompt(
36+
model_id: int,
37+
user_prompt: str,
38+
system_prompt: str,
39+
callback: Optional[Callable[[str], None]] = None,
40+
tenant_id: Optional[str] = None,
41+
) -> str:
42+
"""
43+
Call the LLM to generate a system prompt with optional streaming callbacks.
44+
"""
45+
llm_model_config = get_model_by_model_id(model_id=model_id, tenant_id=tenant_id)
46+
47+
llm = OpenAIServerModel(
48+
model_id=get_model_name_from_config(llm_model_config) if llm_model_config else "",
49+
api_base=llm_model_config.get("base_url", ""),
50+
api_key=llm_model_config.get("api_key", ""),
51+
temperature=0.3,
52+
top_p=0.95,
53+
)
54+
messages = [
55+
{"role": MESSAGE_ROLE["SYSTEM"], "content": system_prompt},
56+
{"role": MESSAGE_ROLE["USER"], "content": user_prompt},
57+
]
58+
try:
59+
completion_kwargs = llm._prepare_completion_kwargs(
60+
messages=messages,
61+
model=llm.model_id,
62+
temperature=0.3,
63+
top_p=0.95,
64+
)
65+
current_request = llm.client.chat.completions.create(stream=True, **completion_kwargs)
66+
token_join: List[str] = []
67+
is_thinking = False
68+
for chunk in current_request:
69+
new_token = chunk.choices[0].delta.content
70+
if new_token is not None:
71+
is_thinking = _process_thinking_tokens(
72+
new_token,
73+
is_thinking,
74+
token_join,
75+
callback,
76+
)
77+
return "".join(token_join)
78+
except Exception as exc:
79+
logger.error("Failed to generate prompt from LLM: %s", str(exc))
80+
raise
81+
82+
83+
__all__ = ["call_llm_for_system_prompt", "_process_thinking_tokens"]
84+

0 commit comments

Comments
 (0)