Skip to content

Commit 74a6fd6

Browse files
committed
Merge remote-tracking branch 'origin/develop' into csy/csy_0813
# Conflicts: # backend/database/agent_db.py
2 parents df8525c + a3688cc commit 74a6fd6

File tree

70 files changed

+2026
-1166
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2026
-1166
lines changed

.github/workflows/docker-build-push-mainland.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
uses: actions/checkout@v4
2424
- name: Build main image (amd64) and load locally
2525
run: |
26-
docker buildx build --platform linux/amd64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent:amd64 -f make/main/Dockerfile .
26+
docker buildx build --platform linux/amd64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent:amd64 -f make/main/Dockerfile --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple --build-arg APT_MIRROR=tsinghua .
2727
- name: Login to Tencent Cloud
2828
run: echo ${{ secrets.TCR_PASSWORD }} | docker login ccr.ccs.tencentyun.com --username=${{ secrets.TCR_USERNAME }} --password-stdin
2929
- name: Push main image (amd64) to Tencent Cloud
@@ -43,7 +43,7 @@ jobs:
4343
uses: actions/checkout@v4
4444
- name: Build main image (arm64) and load locally
4545
run: |
46-
docker buildx build --platform linux/arm64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent:arm64 -f make/main/Dockerfile .
46+
docker buildx build --platform linux/arm64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent:arm64 -f make/main/Dockerfile --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple --build-arg APT_MIRROR=tsinghua .
4747
- name: Login to Tencent Cloud
4848
run: echo ${{ secrets.TCR_PASSWORD }} | docker login ccr.ccs.tencentyun.com --username=${{ secrets.TCR_USERNAME }} --password-stdin
4949
- name: Push main image (arm64) to Tencent Cloud
@@ -72,7 +72,7 @@ jobs:
7272
rm -rf .git .gitattributes
7373
- name: Build data process image (amd64) and load locally
7474
run: |
75-
docker buildx build --platform linux/amd64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-data-process:amd64 -f make/data_process/Dockerfile .
75+
docker buildx build --platform linux/amd64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-data-process:amd64 -f make/data_process/Dockerfile --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple --build-arg APT_MIRROR=tsinghua .
7676
- name: Login to Tencent Cloud
7777
run: echo ${{ secrets.TCR_PASSWORD }} | docker login ccr.ccs.tencentyun.com --username=${{ secrets.TCR_USERNAME }} --password-stdin
7878
- name: Push data process image (amd64) to Tencent Cloud
@@ -101,7 +101,7 @@ jobs:
101101
rm -rf .git .gitattributes
102102
- name: Build data process image (arm64) and load locally
103103
run: |
104-
docker buildx build --platform linux/arm64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-data-process:arm64 -f make/data_process/Dockerfile .
104+
docker buildx build --platform linux/arm64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-data-process:arm64 -f make/data_process/Dockerfile --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple --build-arg APT_MIRROR=tsinghua .
105105
- name: Login to Tencent Cloud
106106
run: echo ${{ secrets.TCR_PASSWORD }} | docker login ccr.ccs.tencentyun.com --username=${{ secrets.TCR_USERNAME }} --password-stdin
107107
- name: Push data process image (arm64) to Tencent Cloud
@@ -121,7 +121,7 @@ jobs:
121121
uses: actions/checkout@v4
122122
- name: Build web image (amd64) and load locally
123123
run: |
124-
docker buildx build --platform linux/amd64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-web:amd64 -f make/web/Dockerfile .
124+
docker buildx build --platform linux/amd64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-web:amd64 -f make/web/Dockerfile --build-arg MIRROR=https://registry.npmmirror.com --build-arg APK_MIRROR=tsinghua .
125125
- name: Login to Tencent Cloud
126126
run: echo ${{ secrets.TCR_PASSWORD }} | docker login ccr.ccs.tencentyun.com --username=${{ secrets.TCR_USERNAME }} --password-stdin
127127
- name: Push web image (amd64) to Tencent Cloud
@@ -141,7 +141,7 @@ jobs:
141141
uses: actions/checkout@v4
142142
- name: Build web image (arm64) and load locally
143143
run: |
144-
docker buildx build --platform linux/arm64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-web:arm64 -f make/web/Dockerfile .
144+
docker buildx build --platform linux/arm64 --load -t ccr.ccs.tencentyun.com/nexent-hub/nexent-web:arm64 -f make/web/Dockerfile --build-arg MIRROR=https://registry.npmmirror.com --build-arg APK_MIRROR=tsinghua .
145145
- name: Login to Tencent Cloud
146146
run: echo ${{ secrets.TCR_PASSWORD }} | docker login ccr.ccs.tencentyun.com --username=${{ secrets.TCR_USERNAME }} --password-stdin
147147
- name: Push web image (arm64) to Tencent Cloud

.github/workflows/docker-deploy.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
fetch-depth: 1
2727
retries: 3
2828
- name: Build main application image
29-
run: docker build --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple -t nexent/nexent -f make/main/Dockerfile .
29+
run: docker build --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple --build-arg APT_MIRROR=tsinghua -t nexent/nexent -f make/main/Dockerfile .
3030

3131
build-data-process:
3232
runs-on: ${{ fromJson(inputs.runner_label_json) }}
@@ -53,7 +53,7 @@ jobs:
5353
GIT_TRACE=1 GIT_CURL_VERBOSE=1 GIT_LFS_LOG=debug git lfs pull
5454
rm -rf .git .gitattributes
5555
- name: Build data process image
56-
run: docker build --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple -t nexent/nexent-data-process -f make/data_process/Dockerfile .
56+
run: docker build --build-arg MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple --build-arg APT_MIRROR=tsinghua -t nexent/nexent-data-process -f make/data_process/Dockerfile .
5757

5858
build-web:
5959
runs-on: ${{ fromJson(inputs.runner_label_json) }}
@@ -64,7 +64,7 @@ jobs:
6464
fetch-depth: 1
6565
retries: 3
6666
- name: Build web frontend image
67-
run: docker build --build-arg MIRROR=https://registry.npmmirror.com -t nexent/nexent-web -f make/web/Dockerfile .
67+
run: docker build --build-arg MIRROR=https://registry.npmmirror.com --build-arg APK_MIRROR=tsinghua -t nexent/nexent-web -f make/web/Dockerfile .
6868

6969
build-docs:
7070
runs-on: ${{ fromJson(inputs.runner_label_json) }}

backend/agents/create_agent_info.py

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
query_or_create_main_agent_id, query_sub_agents_id_list
1212
from services.elasticsearch_service import ElasticSearchService, elastic_core, get_embedding_model
1313
from services.tenant_config_service import get_selected_knowledge_list
14-
from utils.prompt_template_utils import get_prompt_template_path
14+
from utils.prompt_template_utils import get_agent_prompt_template
1515
from utils.config_utils import config_manager, tenant_config_manager, get_model_name_from_config
16-
from smolagents.agents import populate_template
1716
from smolagents.utils import BASE_BUILTIN_MODULES
1817
from services.memory_config_service import build_memory_context
18+
from jinja2 import Template, StrictUndefined
1919

2020
from nexent.memory.memory_service import search_memory_in_levels
2121

@@ -63,10 +63,8 @@ async def create_agent_config(agent_id, tenant_id, user_id, language: str = 'zh'
6363
constraint_prompt = agent_info.get("constraint_prompt", "")
6464
few_shots_prompt = agent_info.get("few_shots_prompt", "")
6565

66-
# Get template path
67-
prompt_template_path = get_prompt_template_path(is_manager=len(managed_agents) > 0, language=language)
68-
with open(prompt_template_path, "r", encoding="utf-8") as file:
69-
prompt_template = yaml.safe_load(file)
66+
# Get template content
67+
prompt_template = get_agent_prompt_template(is_manager=len(managed_agents) > 0, language=language)
7068

7169
# Get app information
7270
default_app_description = 'Nexent 是一个开源智能体SDK和平台' if language == 'zh' else 'Nexent is an open-source agent SDK and platform'
@@ -99,10 +97,30 @@ async def create_agent_config(agent_id, tenant_id, user_id, language: str = 'zh'
9997
logger.debug(f"Retrieved memory list: {memory_list}")
10098
# TODO: 前端展示"已抽取 xx 条回忆"
10199

100+
# Build knowledge base summary
101+
knowledge_base_summary = ""
102+
try:
103+
for tool in tool_list:
104+
if "KnowledgeBaseSearchTool" == tool.class_name:
105+
knowledge_info_list = get_selected_knowledge_list(tenant_id=tenant_id, user_id=user_id)
106+
if knowledge_info_list:
107+
for knowledge_info in knowledge_info_list:
108+
knowledge_name = knowledge_info.get("index_name")
109+
try:
110+
message = ElasticSearchService().get_summary(index_name=knowledge_name)
111+
summary = message.get("summary", "")
112+
knowledge_base_summary += f"**{knowledge_name}**: {summary}\n\n"
113+
except Exception as e:
114+
logger.warning(f"Failed to get summary for knowledge base {knowledge_name}: {e}")
115+
else:
116+
knowledge_base_summary = "当前没有可用的知识库索引。\n" if language == 'zh' else "No knowledge base indexes are currently available.\n"
117+
break # Only process the first KnowledgeBaseSearchTool found
118+
except Exception as e:
119+
logger.error(f"Failed to build knowledge base summary: {e}")
120+
102121
# Assemble system_prompt
103-
system_prompt = populate_template(
104-
prompt_template["system_prompt"],
105-
variables={
122+
if (duty_prompt or constraint_prompt or few_shots_prompt):
123+
system_prompt = Template(prompt_template["system_prompt"], undefined=StrictUndefined).render({
106124
"duty": duty_prompt,
107125
"constraint": constraint_prompt,
108126
"few_shots": few_shots_prompt,
@@ -111,26 +129,12 @@ async def create_agent_config(agent_id, tenant_id, user_id, language: str = 'zh'
111129
"authorized_imports": str(BASE_BUILTIN_MODULES),
112130
"APP_NAME": app_name,
113131
"APP_DESCRIPTION": app_description,
114-
"memory_list": memory_list
115-
},
116-
) if (duty_prompt or constraint_prompt or few_shots_prompt) else agent_info.get("prompt", "")
117-
118-
# special logic
119-
try:
120-
for tool in tool_list:
121-
if "KnowledgeBaseSearchTool" == tool.class_name:
122-
# TODO: use prompt template
123-
knowledge_base_summary = "\n\n### 本地知识库信息 ###\n" if language == 'zh' else "\n\n### Local Knowledge Base Information ###\n"
124-
125-
knowledge_info_list = get_selected_knowledge_list(tenant_id=tenant_id, user_id=user_id)
126-
for knowledge_info in knowledge_info_list:
127-
knowledge_name = knowledge_info.get("index_name")
128-
message = ElasticSearchService().get_summary(index_name=knowledge_name)
129-
knowledge_base_summary += f"{knowledge_name}:{message['summary']}\n"
130-
system_prompt += knowledge_base_summary
131-
except Exception as e:
132-
logger.error(f"add knowledge base summary to system prompt failed, error: {e}")
133-
132+
"memory_list": memory_list,
133+
"knowledge_base_summary": knowledge_base_summary
134+
})
135+
else:
136+
system_prompt = agent_info.get("prompt", "")
137+
134138
agent_config = AgentConfig(
135139
name="undefined" if agent_info["name"] is None else agent_info["name"],
136140
description="undefined" if agent_info["description"] is None else agent_info["description"],
@@ -230,9 +234,7 @@ async def prepare_prompt_templates(is_manager: bool, system_prompt: str, languag
230234
Returns:
231235
dict: Prompt template configuration
232236
"""
233-
prompt_template_path = get_prompt_template_path(is_manager, language)
234-
with open(prompt_template_path, "r", encoding="utf-8") as f:
235-
prompt_templates = yaml.safe_load(f)
237+
prompt_templates = get_agent_prompt_template(is_manager, language)
236238
prompt_templates["system_prompt"] = system_prompt
237239
return prompt_templates
238240

backend/apps/conversation_management_app.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from typing import Dict, Any, Optional
33

4-
from fastapi import HTTPException, APIRouter, Header
4+
from fastapi import HTTPException, APIRouter, Header, Request
55
from fastapi.encoders import jsonable_encoder
66
from pydantic import BaseModel
77

@@ -176,7 +176,9 @@ async def get_sources_endpoint(request: Dict[str, Any], authorization: Optional[
176176

177177

178178
@router.post("/generate_title", response_model=ConversationResponse)
179-
async def generate_conversation_title_endpoint(request: GenerateTitleRequest, authorization: Optional[str] = Header(None)):
179+
async def generate_conversation_title_endpoint(request: GenerateTitleRequest,
180+
http_request: Request,
181+
authorization: Optional[str] = Header(None)):
180182
"""
181183
Generate conversation title
182184
@@ -190,8 +192,8 @@ async def generate_conversation_title_endpoint(request: GenerateTitleRequest, au
190192
ConversationResponse object containing generated title
191193
"""
192194
try:
193-
user_id, tenant_id, language = get_current_user_info(authorization=authorization)
194-
title = generate_conversation_title_service(request.conversation_id, request.history, user_id,tenant_id=tenant_id)
195+
user_id, tenant_id, language = get_current_user_info(authorization=authorization, request=http_request)
196+
title = await generate_conversation_title_service(request.conversation_id, request.history, user_id, tenant_id=tenant_id, language=language)
195197
return ConversationResponse(code=0, message="success", data=title)
196198
except Exception as e:
197199
logging.error(f"Failed to generate conversation title: {str(e)}")

backend/apps/file_management_app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ async def process_text_file(query, filename, file_content, tenant_id: str, langu
517517
if response.status_code == 200:
518518
result = response.json()
519519
raw_text = result.get("text", "")
520-
logger.info(f"File processed successfully: {raw_text[:100]}...")
520+
logger.info(f"File processed successfully: {raw_text[:200]}...{raw_text[-200:]}..., length: {len(raw_text)}")
521521
else:
522522
error_detail = response.json().get('detail', '未知错误') if response.headers.get('content-type', '').startswith('application/json') else response.text
523523
logger.error(f"File processing failed (status code: {response.status_code}): {error_detail}")

backend/apps/model_managment_app.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Optional
2+
from typing import Optional, List
33

44
from fastapi import Query, APIRouter, Header, Body
55

@@ -210,6 +210,26 @@ async def update_single_model(request: dict, authorization: Optional[str] = Head
210210
)
211211

212212

213+
@router.post("/batch_update_models", response_model=ModelResponse)
214+
async def batch_update_models(request: List[dict], authorization: Optional[str] = Header(None)):
215+
try:
216+
user_id, tenant_id = get_current_user_id(authorization)
217+
model_list = request
218+
for model in model_list:
219+
update_model_record(model["model_id"], model, user_id)
220+
return ModelResponse(
221+
code=200,
222+
message=f"Batch update models successfully",
223+
data=None
224+
)
225+
except Exception as e:
226+
return ModelResponse(
227+
code=500,
228+
message=f"Failed to batch update models: {str(e)}",
229+
data=None
230+
)
231+
232+
213233
@router.post("/delete", response_model=ModelResponse)
214234
async def delete_model(display_name: str = Query(..., embed=True), authorization: Optional[str] = Header(None)):
215235
"""

backend/database/agent_db.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ def add_tool_field(tool_info):
303303
tool_info["class_name"] = tool.class_name
304304
tool_info["is_available"] = tool.is_available
305305
tool_info["usage"] = tool.usage
306+
tool_info["inputs"] = tool.inputs
307+
tool_info["output_type"] = tool.output_type
306308
return tool_info
307309

308310
def search_tools_for_sub_agent(agent_id, tenant_id):

backend/database/conversation_db.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ def rename_conversation(conversation_id: int, new_title: str, user_id: Optional[
320320
# Prepare update data
321321
update_data = {
322322
"conversation_title": new_title,
323-
"update_time": func.current_timestamp() # Use the database's CURRENT_TIMESTAMP function
323+
"update_time": func.current_timestamp()
324324
}
325325
if user_id:
326326
update_data = add_update_tracking(update_data, user_id)

backend/prompts/analyze_file.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
image_analysis:
55
system_prompt: |-
6-
用户提出了一个问题:{query},请从回答这个问题的角度精简、仔细描述一下这个图片,200字以内。
6+
用户提出了一个问题:{{ query }},请从回答这个问题的角度精简、仔细描述一下这个图片,200字以内。
77
88
**图片分析要求:**
99
1. 重点关注与用户问题相关的图片内容
@@ -16,7 +16,7 @@ image_analysis:
1616
1717
long_text_analysis:
1818
system_prompt: |-
19-
用户提出了一个问题:{query},请从回答这个问题的角度精简、仔细描述一下这段文本,200字以内。
19+
用户提出了一个问题:{{ query }},请从回答这个问题的角度精简、仔细描述一下这段文本,200字以内。
2020
2121
**文本分析要求:**
2222
1. 重点提取与用户问题相关的文本内容
@@ -25,4 +25,4 @@ long_text_analysis:
2525
4. 避免冗余信息,专注于问题相关内容
2626
2727
user_prompt: |
28-
请仔细阅读并分析这段文本:{file_context}
28+
请仔细阅读并分析这段文本:

backend/prompts/analyze_file_en.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
image_analysis:
55
system_prompt: |-
6-
The user has asked a question: {query}. Please provide a concise and careful description of this image from the perspective of answering this question, within 200 words.
6+
The user has asked a question: {{ query }}. Please provide a concise and careful description of this image from the perspective of answering this question, within 200 words.
77
88
**Image Analysis Requirements:**
99
1. Focus on image content relevant to the user's question
@@ -16,7 +16,7 @@ image_analysis:
1616
1717
long_text_analysis:
1818
system_prompt: |-
19-
The user has asked a question: {query}. Please provide a concise and careful description of this text from the perspective of answering this question, within 200 words.
19+
The user has asked a question: {{ query }}. Please provide a concise and careful description of this text from the perspective of answering this question, within 200 words.
2020
2121
**Text Analysis Requirements:**
2222
1. Focus on extracting text content relevant to the user's question
@@ -25,4 +25,4 @@ long_text_analysis:
2525
4. Avoid redundant information, focus on question-relevant content
2626
2727
user_prompt: |
28-
Please carefully read and analyze this text: {file_context}
28+
Please carefully read and analyze this text:

0 commit comments

Comments
 (0)