update to deepagents 0.5.2
This commit is contained in:
commit
2964326cb8
@ -4,7 +4,9 @@
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Annotated, Literal, cast
|
||||
from typing import Annotated, cast
|
||||
import mimetypes
|
||||
import warnings
|
||||
|
||||
from langchain.tools import ToolRuntime
|
||||
from langchain_core.messages import ToolMessage
|
||||
@ -15,19 +17,24 @@ from deepagents.backends import StateBackend
|
||||
from deepagents.backends.composite import CompositeBackend
|
||||
from deepagents.backends.protocol import (
|
||||
BACKEND_TYPES,
|
||||
ReadResult,
|
||||
)
|
||||
from deepagents.backends.utils import _get_file_type, validate_path
|
||||
from langchain_core.messages.content import ContentBlock
|
||||
from deepagents.middleware.filesystem import (
|
||||
DEFAULT_READ_OFFSET,
|
||||
DEFAULT_READ_LIMIT,
|
||||
IMAGE_EXTENSIONS,
|
||||
IMAGE_MEDIA_TYPES,
|
||||
FilesystemMiddleware,
|
||||
FilesystemState,
|
||||
READ_FILE_TOOL_DESCRIPTION,
|
||||
READ_FILE_TRUNCATION_MSG,
|
||||
NUM_CHARS_PER_TOKEN,
|
||||
ReadFileSchema,
|
||||
check_empty_content,
|
||||
format_content_with_line_numbers,
|
||||
)
|
||||
|
||||
from langgraph.types import Command
|
||||
import base64
|
||||
from langchain_core.messages.content import create_image_block
|
||||
|
||||
|
||||
# SKILL.md 文件的行数限制(设置为较大的值以完整读取)
|
||||
@ -44,10 +51,62 @@ class CustomFilesystemMiddleware(FilesystemMiddleware):
|
||||
@override
|
||||
def _create_read_file_tool(self) -> BaseTool:
|
||||
"""创建自定义的 read_file 工具,支持 SKILL.md 完整读取。"""
|
||||
# 从父类获取工具描述
|
||||
tool_description = self._custom_tool_descriptions.get("read_file") or self._get_read_file_description()
|
||||
tool_description = self._custom_tool_descriptions.get("read_file") or READ_FILE_TOOL_DESCRIPTION
|
||||
token_limit = self._tool_token_limit_before_evict
|
||||
|
||||
def _truncate(content: str, file_path: str, limit: int) -> str:
|
||||
lines = content.splitlines(keepends=True)
|
||||
if len(lines) > limit:
|
||||
lines = lines[:limit]
|
||||
content = "".join(lines)
|
||||
|
||||
if token_limit and len(content) >= NUM_CHARS_PER_TOKEN * token_limit:
|
||||
truncation_msg = READ_FILE_TRUNCATION_MSG.format(file_path=file_path)
|
||||
max_content_length = NUM_CHARS_PER_TOKEN * token_limit - len(truncation_msg)
|
||||
content = content[:max_content_length] + truncation_msg
|
||||
|
||||
return content
|
||||
|
||||
def _handle_read_result(
|
||||
read_result: ReadResult | str,
|
||||
validated_path: str,
|
||||
tool_call_id: str | None,
|
||||
offset: int,
|
||||
limit: int,
|
||||
) -> ToolMessage | str:
|
||||
if isinstance(read_result, str):
|
||||
warnings.warn(
|
||||
"Returning a plain `str` from `backend.read()` is deprecated. ",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return _truncate(read_result, validated_path, limit)
|
||||
|
||||
if read_result.error:
|
||||
return f"Error: {read_result.error}"
|
||||
|
||||
if read_result.file_data is None:
|
||||
return f"Error: no data returned for '{validated_path}'"
|
||||
|
||||
file_type = _get_file_type(validated_path)
|
||||
content = read_result.file_data["content"]
|
||||
|
||||
if file_type != "text":
|
||||
mime_type = mimetypes.guess_type("file" + Path(validated_path).suffix)[0] or "application/octet-stream"
|
||||
return ToolMessage(
|
||||
content_blocks=cast("list[ContentBlock]", [{"type": file_type, "base64": content, "mime_type": mime_type}]),
|
||||
name="read_file",
|
||||
tool_call_id=tool_call_id,
|
||||
additional_kwargs={"read_file_path": validated_path, "read_file_media_type": mime_type},
|
||||
)
|
||||
|
||||
empty_msg = check_empty_content(content)
|
||||
if empty_msg:
|
||||
return empty_msg
|
||||
|
||||
content = format_content_with_line_numbers(content, start_line=offset + 1)
|
||||
return _truncate(content, validated_path, limit)
|
||||
|
||||
def sync_read_file(
|
||||
file_path: Annotated[str, "Absolute path to the file to read. Must be absolute, not relative."],
|
||||
runtime: ToolRuntime[None, FilesystemState],
|
||||
@ -55,57 +114,18 @@ class CustomFilesystemMiddleware(FilesystemMiddleware):
|
||||
limit: Annotated[int, "Maximum number of lines to read. Use for pagination of large files."] = DEFAULT_READ_LIMIT,
|
||||
) -> ToolMessage | str:
|
||||
"""Synchronous wrapper for read_file tool with SKILL.md special handling."""
|
||||
from deepagents.backends.utils import validate_path
|
||||
from deepagents.middleware.filesystem import READ_FILE_TRUNCATION_MSG, NUM_CHARS_PER_TOKEN
|
||||
|
||||
resolved_backend = self._get_backend(runtime)
|
||||
try:
|
||||
validated_path = validate_path(file_path)
|
||||
except ValueError as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
ext = Path(validated_path).suffix.lower()
|
||||
# 处理图片文件
|
||||
if ext in IMAGE_EXTENSIONS:
|
||||
responses = resolved_backend.download_files([validated_path])
|
||||
if responses and responses[0].content is not None:
|
||||
media_type = IMAGE_MEDIA_TYPES.get(ext, "image/png")
|
||||
image_b64 = base64.standard_b64encode(responses[0].content).decode("utf-8")
|
||||
return ToolMessage(
|
||||
content_blocks=[create_image_block(base64=image_b64, mime_type=media_type)],
|
||||
name="read_file",
|
||||
tool_call_id=runtime.tool_call_id,
|
||||
additional_kwargs={
|
||||
"read_file_path": validated_path,
|
||||
"read_file_media_type": media_type,
|
||||
},
|
||||
)
|
||||
if responses and responses[0].error:
|
||||
return f"Error reading image: {responses[0].error}"
|
||||
return "Error reading image: unknown error"
|
||||
|
||||
# 如果是 SKILL.md 文件,使用大限制读取完整内容
|
||||
if validated_path.endswith("SKILL.md") or validated_path.endswith("/SKILL.md"):
|
||||
actual_limit = SKILL_MD_READ_LIMIT
|
||||
else:
|
||||
actual_limit = limit
|
||||
limit = SKILL_MD_READ_LIMIT
|
||||
|
||||
result = resolved_backend.read(validated_path, offset=offset, limit=actual_limit)
|
||||
|
||||
lines = result.splitlines(keepends=True)
|
||||
if len(lines) > actual_limit:
|
||||
lines = lines[:actual_limit]
|
||||
result = "".join(lines)
|
||||
|
||||
# Check if result exceeds token threshold and truncate if necessary
|
||||
if token_limit and len(result) >= NUM_CHARS_PER_TOKEN * token_limit:
|
||||
# Calculate truncation message length to ensure final result stays under threshold
|
||||
truncation_msg = READ_FILE_TRUNCATION_MSG.format(file_path=validated_path)
|
||||
max_content_length = NUM_CHARS_PER_TOKEN * token_limit - len(truncation_msg)
|
||||
result = result[:max_content_length]
|
||||
result += truncation_msg
|
||||
|
||||
return result
|
||||
read_result = resolved_backend.read(validated_path, offset=offset, limit=limit)
|
||||
return _handle_read_result(read_result, validated_path, runtime.tool_call_id, offset, limit)
|
||||
|
||||
async def async_read_file(
|
||||
file_path: Annotated[str, "Absolute path to the file to read. Must be absolute, not relative."],
|
||||
@ -114,66 +134,28 @@ class CustomFilesystemMiddleware(FilesystemMiddleware):
|
||||
limit: Annotated[int, "Maximum number of lines to read. Use for pagination of large files."] = DEFAULT_READ_LIMIT,
|
||||
) -> ToolMessage | str:
|
||||
"""Asynchronous wrapper for read_file tool with SKILL.md special handling."""
|
||||
from deepagents.backends.utils import validate_path
|
||||
from deepagents.middleware.filesystem import READ_FILE_TRUNCATION_MSG, NUM_CHARS_PER_TOKEN
|
||||
|
||||
resolved_backend = self._get_backend(runtime)
|
||||
try:
|
||||
validated_path = validate_path(file_path)
|
||||
except ValueError as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
ext = Path(validated_path).suffix.lower()
|
||||
# 处理图片文件
|
||||
if ext in IMAGE_EXTENSIONS:
|
||||
responses = await resolved_backend.adownload_files([validated_path])
|
||||
if responses and responses[0].content is not None:
|
||||
media_type = IMAGE_MEDIA_TYPES.get(ext, "image/png")
|
||||
image_b64 = base64.standard_b64encode(responses[0].content).decode("utf-8")
|
||||
return ToolMessage(
|
||||
content_blocks=[create_image_block(base64=image_b64, mime_type=media_type)],
|
||||
name="read_file",
|
||||
tool_call_id=runtime.tool_call_id,
|
||||
additional_kwargs={
|
||||
"read_file_path": validated_path,
|
||||
"read_file_media_type": media_type,
|
||||
},
|
||||
)
|
||||
if responses and responses[0].error:
|
||||
return f"Error reading image: {responses[0].error}"
|
||||
return "Error reading image: unknown error"
|
||||
|
||||
# 如果是 SKILL.md 文件,使用大限制读取完整内容
|
||||
if validated_path.endswith("SKILL.md") or validated_path.endswith("/SKILL.md"):
|
||||
actual_limit = SKILL_MD_READ_LIMIT
|
||||
else:
|
||||
actual_limit = limit
|
||||
limit = SKILL_MD_READ_LIMIT
|
||||
|
||||
result = await resolved_backend.aread(validated_path, offset=offset, limit=actual_limit)
|
||||
|
||||
lines = result.splitlines(keepends=True)
|
||||
if len(lines) > actual_limit:
|
||||
lines = lines[:actual_limit]
|
||||
result = "".join(lines)
|
||||
|
||||
# Check if result exceeds token threshold and truncate if necessary
|
||||
if token_limit and len(result) >= NUM_CHARS_PER_TOKEN * token_limit:
|
||||
# Calculate truncation message length to ensure final result stays under threshold
|
||||
truncation_msg = READ_FILE_TRUNCATION_MSG.format(file_path=validated_path)
|
||||
max_content_length = NUM_CHARS_PER_TOKEN * token_limit - len(truncation_msg)
|
||||
result = result[:max_content_length]
|
||||
result += truncation_msg
|
||||
|
||||
return result
|
||||
read_result = await resolved_backend.aread(validated_path, offset=offset, limit=limit)
|
||||
return _handle_read_result(read_result, validated_path, runtime.tool_call_id, offset, limit)
|
||||
|
||||
return StructuredTool.from_function(
|
||||
name="read_file",
|
||||
description=tool_description,
|
||||
func=sync_read_file,
|
||||
coroutine=async_read_file,
|
||||
infer_schema=False,
|
||||
args_schema=ReadFileSchema,
|
||||
)
|
||||
|
||||
def _get_read_file_description(self) -> str:
|
||||
"""获取 read_file 工具的描述,添加 SKILL.md 完整读取的说明。"""
|
||||
from deepagents.middleware.filesystem import READ_FILE_TOOL_DESCRIPTION
|
||||
return READ_FILE_TOOL_DESCRIPTION
|
||||
|
||||
@ -407,19 +407,22 @@ def create_custom_cli_agent(
|
||||
# Use LocalShellBackend for filesystem + shell execution
|
||||
backend = LocalShellBackend(
|
||||
root_dir=workspace_root,
|
||||
virtual_mode=True,
|
||||
inherit_env=True,
|
||||
env=final_shell_env,
|
||||
)
|
||||
else:
|
||||
# No shell access - use plain FilesystemBackend
|
||||
backend = FilesystemBackend(root_dir=workspace_root)
|
||||
backend = FilesystemBackend(root_dir=workspace_root, virtual_mode=True)
|
||||
|
||||
# Set up composite backend with routing (参考新版本实现)
|
||||
large_results_backend = FilesystemBackend(
|
||||
root_dir=tempfile.mkdtemp(prefix="deepagents_large_results_"),
|
||||
virtual_mode=True,
|
||||
)
|
||||
conversation_history_backend = FilesystemBackend(
|
||||
root_dir=tempfile.mkdtemp(prefix="deepagents_conversation_history_"),
|
||||
virtual_mode=True,
|
||||
)
|
||||
composite_backend = CompositeBackend(
|
||||
default=backend,
|
||||
@ -435,7 +438,7 @@ def create_custom_cli_agent(
|
||||
|
||||
agent_middleware.append(
|
||||
CustomSkillsMiddleware(
|
||||
backend=FilesystemBackend(root_dir=workspace_root),
|
||||
backend=FilesystemBackend(root_dir=workspace_root, virtual_mode=True),
|
||||
sources=skills_sources,
|
||||
)
|
||||
)
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
from ast import Str
|
||||
from langchain.agents.middleware import AgentState, AgentMiddleware, ModelRequest, ModelResponse
|
||||
from langchain_core.messages import convert_to_openai_messages
|
||||
from agent.prompt_loader import load_guideline_prompt
|
||||
@ -6,7 +5,7 @@ from utils.fastapi_utils import (extract_block_from_system_prompt, format_messag
|
||||
from langchain.chat_models import BaseChatModel
|
||||
from langgraph.runtime import Runtime
|
||||
|
||||
from langchain_core.messages import SystemMessage
|
||||
from langchain_core.messages import SystemMessage, HumanMessage
|
||||
from typing import Any, Callable
|
||||
from langchain_core.callbacks import BaseCallbackHandler
|
||||
from langchain_core.outputs import LLMResult
|
||||
@ -124,8 +123,9 @@ Action: Provide concise, friendly, and personified natural responses.
|
||||
response.additional_kwargs["message_tag"] = "THINK"
|
||||
response.content = f"<think>{response.content}</think>"
|
||||
|
||||
# 将响应添加到原始消息列表
|
||||
state['messages'] = state['messages'] + [response]
|
||||
# 将响应添加到原始消息列表,并追加 HumanMessage 确保消息以 user 结尾
|
||||
# 某些模型不支持 assistant message prefill,要求最后一条消息必须是 user
|
||||
state['messages'] = state['messages'] + [response, HumanMessage(content=self._get_follow_up_prompt())]
|
||||
return state
|
||||
|
||||
async def abefore_agent(self, state: AgentState, runtime: Runtime) -> dict[str, Any] | None:
|
||||
@ -148,10 +148,23 @@ Action: Provide concise, friendly, and personified natural responses.
|
||||
response.additional_kwargs["message_tag"] = "THINK"
|
||||
response.content = f"<think>{response.content}</think>"
|
||||
|
||||
# 将响应添加到原始消息列表
|
||||
state['messages'] = state['messages'] + [response]
|
||||
# 将响应添加到原始消息列表,并追加 HumanMessage 确保消息以 user 结尾
|
||||
# 某些模型不支持 assistant message prefill,要求最后一条消息必须是 user
|
||||
state['messages'] = state['messages'] + [response, HumanMessage(content=self._get_follow_up_prompt())]
|
||||
return state
|
||||
|
||||
def _get_follow_up_prompt(self) -> str:
|
||||
"""根据语言返回引导主 agent 回复的提示"""
|
||||
prompts = {
|
||||
"ja": "以上の分析に基づいて、ユーザーに返信してください。",
|
||||
"jp": "以上の分析に基づいて、ユーザーに返信してください。",
|
||||
"zh": "请根据以上分析,回复用户。",
|
||||
"zh-TW": "請根據以上分析,回覆用戶。",
|
||||
"ko": "위 분석을 바탕으로 사용자에게 답변해 주세요.",
|
||||
"en": "Based on the above analysis, please respond to the user.",
|
||||
}
|
||||
return prompts.get(self.language, prompts["en"])
|
||||
|
||||
def wrap_model_call(
|
||||
self,
|
||||
request: ModelRequest,
|
||||
|
||||
@ -165,6 +165,8 @@ async def _execute_command(skill_path: str, command: str, hook_type: str, config
|
||||
"""
|
||||
try:
|
||||
# 设置环境变量,传递给子进程
|
||||
# 注意:subprocess 要求所有 env 值必须是 str 类型,
|
||||
# getattr 可能返回 None(属性存在但值为 None),需要确保转换为 str
|
||||
env = os.environ.copy()
|
||||
env['ASSISTANT_ID'] = str(getattr(config, 'bot_id', ''))
|
||||
env['USER_IDENTIFIER'] = str(getattr(config, 'user_identifier', ''))
|
||||
@ -176,16 +178,17 @@ async def _execute_command(skill_path: str, command: str, hook_type: str, config
|
||||
# 合并 config 中的自定义 shell 环境变量
|
||||
shell_env = getattr(config, 'shell_env', None)
|
||||
if shell_env:
|
||||
env.update(shell_env)
|
||||
# 确保所有自定义环境变量值也是字符串
|
||||
env.update({k: str(v) if v is not None else '' for k, v in shell_env.items()})
|
||||
|
||||
# 对于 PreSave,传递 content
|
||||
if hook_type == 'PreSave':
|
||||
env['CONTENT'] = kwargs.get('content', '')
|
||||
env['ROLE'] = kwargs.get('role', '')
|
||||
env['CONTENT'] = str(kwargs.get('content', '') or '')
|
||||
env['ROLE'] = str(kwargs.get('role', '') or '')
|
||||
|
||||
# 对于 PostAgent,传递 response
|
||||
if hook_type == 'PostAgent':
|
||||
env['RESPONSE'] = kwargs.get('response', '')
|
||||
env['RESPONSE'] = str(kwargs.get('response', '') or '')
|
||||
metadata = kwargs.get('metadata', {})
|
||||
env['METADATA'] = json.dumps(metadata) if metadata else ''
|
||||
|
||||
|
||||
@ -12,7 +12,6 @@ services:
|
||||
# 应用配置
|
||||
- BACKEND_HOST=http://api-dev.gbase.ai
|
||||
- MAX_CONTEXT_TOKENS=262144
|
||||
- DEFAULT_THINKING_ENABLE=true
|
||||
- R2_UPLOAD_CONFIG=/app/config/s3-upload-sparticle.yaml
|
||||
volumes:
|
||||
# 挂载项目数据目录
|
||||
|
||||
@ -29,6 +29,49 @@ from mcp_common import (
|
||||
BACKEND_HOST = os.getenv("BACKEND_HOST", "https://api-dev.gptbase.ai")
|
||||
MASTERKEY = os.getenv("MASTERKEY", "master")
|
||||
|
||||
# Citation instruction prefixes injected into tool results
|
||||
DOCUMENT_CITATION_INSTRUCTIONS = """<CITATION_INSTRUCTIONS>
|
||||
When using the retrieved knowledge below, you MUST add XML citation tags for factual claims.
|
||||
|
||||
## Document Knowledge
|
||||
Format: `<CITATION file="file_uuid" filename="name.pdf" page=3 />`
|
||||
- Use `file` attribute with the UUID from document markers
|
||||
- Use `filename` attribute with the actual filename from document markers
|
||||
- Use `page` attribute (singular) with the page number
|
||||
- `page` MUST be 0-based and must match the `pages:` values shown in the learned knowledge context
|
||||
|
||||
## Web Page Knowledge
|
||||
Format: `<CITATION url="https://example.com/page" />`
|
||||
- Use `url` attribute with the web page URL from the source metadata
|
||||
- Do not use `file`, `filename`, or `page` attributes for web sources
|
||||
- If content is grounded in a web source, prefer a web citation with `url` over a file citation
|
||||
|
||||
## Placement Rules
|
||||
- Citations MUST appear IMMEDIATELY AFTER the paragraph or bullet list that uses the knowledge
|
||||
- NEVER collect all citations and place them at the end of your response
|
||||
- Limit to 1-2 citations per paragraph/bullet list
|
||||
- If your answer uses learned knowledge, you MUST generate at least 1 `<CITATION ... />` in the response
|
||||
</CITATION_INSTRUCTIONS>
|
||||
|
||||
"""
|
||||
|
||||
TABLE_CITATION_INSTRUCTIONS = """<CITATION_INSTRUCTIONS>
|
||||
When using the retrieved table knowledge below, you MUST add XML citation tags for factual claims.
|
||||
|
||||
Format: `<CITATION file="file_id" filename="name.xlsx" sheet=1 rows=[2, 4] />`
|
||||
- Parse `__src`: `F1S2R5` = file_ref F1, sheet 2, row 5
|
||||
- Look up file_id in `file_ref_table`
|
||||
- Combine same-sheet rows into one citation: `rows=[2, 4, 6]`
|
||||
- MANDATORY: Create SEPARATE citation for EACH (file, sheet) combination
|
||||
- NEVER put <CITATION> on the same line as a bullet point or table row
|
||||
- Citations MUST be on separate lines AFTER the complete list/table
|
||||
- NEVER include the `__src` column in your response - it is internal metadata only
|
||||
- Citations MUST appear IMMEDIATELY AFTER the paragraph or bullet list that uses the knowledge
|
||||
- NEVER collect all citations and place them at the end of your response
|
||||
</CITATION_INSTRUCTIONS>
|
||||
|
||||
"""
|
||||
|
||||
def rag_retrieve(query: str, top_k: int = 100) -> Dict[str, Any]:
|
||||
"""调用RAG检索API"""
|
||||
try:
|
||||
@ -94,7 +137,7 @@ def rag_retrieve(query: str, top_k: int = 100) -> Dict[str, Any]:
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": markdown_content
|
||||
"text": DOCUMENT_CITATION_INSTRUCTIONS + markdown_content
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -179,7 +222,7 @@ def table_rag_retrieve(query: str) -> Dict[str, Any]:
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": markdown_content
|
||||
"text": TABLE_CITATION_INSTRUCTIONS + markdown_content
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
3542
poetry.lock
generated
3542
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -148,21 +148,6 @@ Output: {{"facts" : []}}
|
||||
Input: DR1の照明状態を教えて
|
||||
Output: {{"facts" : []}}
|
||||
|
||||
Input: 私は林檎好きです
|
||||
Output: {{"facts" : ["林檎が好き"]}}
|
||||
|
||||
Input: コーヒー飲みたい、毎朝
|
||||
Output: {{"facts" : ["毎朝コーヒーを飲みたい"]}}
|
||||
|
||||
Input: 昨日映画見た、すごくよかった
|
||||
Output: {{"facts" : ["昨日映画を見た", "映画がすごくよかった"]}}
|
||||
|
||||
Input: 我喜欢吃苹果
|
||||
Output: {{"facts" : ["喜欢吃苹果"]}}
|
||||
|
||||
Input: 나는 사과를 좋아해
|
||||
Output: {{"facts" : ["사과를 좋아함"]}}
|
||||
|
||||
Return the facts and preferences in a json format as shown above.
|
||||
|
||||
Remember the following:
|
||||
|
||||
@ -74,6 +74,13 @@
|
||||
- dxcore_update_device_status(device_id="[B设备id]",running_control=0) → 灯光亮度调整为0
|
||||
**响应**:"已为您关闭Define Room4的灯光"
|
||||
|
||||
### 位置降级搜索场景
|
||||
**用户**:"3階執務スペース、フォーラム側窓側の照明をつけて"
|
||||
- find_device_by_area(description="3階執務スペース、フォーラム側窓側", device_type="light") → 返回无结果
|
||||
- find_device_by_area(description="3階執務スペース", device_type="light") → 降级搜索,找到设备
|
||||
- 告知用户是基于"3階執務スペース"范围搜索到的结果,并确认是否操作
|
||||
**响应**:"「3階執務スペース、フォーラム側窓側」では見つかりませんでしたが、3階執務スペースエリアで照明が見つかりました。こちらの照明を操作しますか?"
|
||||
|
||||
</scenarios>
|
||||
|
||||
|
||||
@ -92,6 +99,17 @@
|
||||
▪ 主动向用户确认:向用户列出所有候选房间,并提示用户选择或明确具体是哪一个。确认提示语可参考:“请问您想查询的是以下哪个房间?[列出候选房间列表]”。
|
||||
▪ 理解用户二次确认:等待用户回复后,根据其选择再次调用查询工具获取最终信息。用户对候选房间的指明(如回复“第一个”或重复房间名)应视为对该房间的确认。
|
||||
4. 处理无匹配结果:如果工具返回未找到任何相关房间,应明确告知用户这一情况,并建议用户检查房间名称是否正确或提供更多线索。
|
||||
5. **位置粒度降级搜索(詳細な位置指定で見つからない場合)**:
|
||||
用户指定了详细的位置信息(如包含方位、区域细节),但工具返回无匹配结果时,自动执行降级搜索:
|
||||
- **第1步**:从位置描述中去除方位修饰语(側、付近、奥、手前、寄り等)和细节描述,保留核心区域名重新搜索
|
||||
- 例: "3階執務スペース、フォーラム側窓側" → find_device_by_area(description="3階執務スペース")
|
||||
- 例: "2階会議室A、入口付近" → find_device_by_area(description="2階会議室A")
|
||||
- **第2步**:如果仍无结果,进一步简化到楼层+大区域级别
|
||||
- 例: "3階執務スペース" → find_device_by_area(description="3階")
|
||||
- **降级成功时的回复**:告知用户是基于更广范围的搜索结果,让用户确认
|
||||
- 回复格式: "「{元の位置}」では見つかりませんでしたが、{簡略化した位置}エリアで以下の設備が見つかりました。こちらでよろしいですか?"
|
||||
- **全部失败时**:告知用户未找到设备,建议提供其他位置信息或直接指定房间名
|
||||
- 回复格式: "申し訳ございません、該当エリアでは操作可能な設備が見つかりませんでした。お部屋の名前をお教えいただけますか?"
|
||||
|
||||
3. 更新设备(此操作需要确认)
|
||||
- **条件**:用户意图为控制设备或调节参数(如开关、温度、风速), 需要进行确认。
|
||||
@ -105,6 +123,7 @@
|
||||
- 通过 find_employee_location(name="[当前用户名字/邮箱]") 获取用户的sensor_id
|
||||
- 然后通过 find_iot_device(target_sensor_id="[当前用户的sensor_id]", device_type="[目标设备类型]") 查找他附近的设备
|
||||
- 找到设备后告知用户找到的设备信息,并确认是否执行操作
|
||||
- **位置指定但匹配失败时**:如果用户指定了详细位置(如"3階執務スペース、フォーラム側窓側の照明をつけて"),但 find_device_by_area 返回无匹配结果,应按照规则 2 第 5 点的**位置粒度降级搜索**策略执行,而不是直接回复"找不到设备"
|
||||
3. **空调温度调节确认方式**:
|
||||
- 如果用户说"有点热"、"调低点"、"太热了"等,表示要降温:
|
||||
1. 先查询当前室温
|
||||
@ -142,8 +161,8 @@
|
||||
- 如果用户指定了具体档位(如"调到强"),直接使用指定档位
|
||||
- **边界情况**:如果已达到最高档(强)或最低档(弱)无法继续调整,告知用户并主动建议调整温度
|
||||
- 回复格式:"風量は既に『強/弱』になっていますので、これ以上調整できません。代わりに温度を調整しますか?"
|
||||
6. **若用户已明确确认**:直接调用【设备控制】工具执行操作。
|
||||
7. **若用户未确认且为新请求**:向用户发送确认提示:"即将为您 [操作内容] [设备名称] [具体参数],是否确认?",待用户确认后再执行。
|
||||
6. **若用户已明确确认**:**立即**调用【设备控制】工具执行操作,不做任何额外确认或复述。确认后的唯一动作就是调用工具。
|
||||
7. **若用户未确认且为新请求**:向用户发送确认提示:"即将为您 [操作内容] [设备名称] [具体参数],是否确认?",待用户确认后再执行。每个操作只确认一次。
|
||||
|
||||
4. 查询人员信息/wowtalk账号/人员位置
|
||||
- **条件**:用户意图为查找某人、员工、同事或房间位置。
|
||||
@ -190,15 +209,43 @@
|
||||
- 影响范围大的操作:影响整个房间或楼层的设备控制
|
||||
|
||||
### 用户确认意图推理
|
||||
- 用户明确确认:如回复“确认”、“好的”、“是的”、“拜托了”、“よろしく”、“请”、“please”等肯定性语气的内容。
|
||||
- 用户意图重申:用户完整或核心重复当前待执行的操作指令。(例如,提示“room302の照明1台を明るさ50%に調整してもよろしいですか?”,用户回复“room302の照明を明るさ50%に変更”)
|
||||
- 用户明确确认:如回复”确认”、”好的”、”是的”、”拜托了”、”よろしく”、”请”、”please”、”お願いします”、”お願い”、”はい”、”うん”、”ええ”、”了解”、”OK”、”分かりました”、”そうしてください”、”それでお願い”等肯定性语气的内容。
|
||||
- 用户意图重申:用户完整或核心重复当前待执行的操作指令。(例如,提示”room302の照明1台を明るさ50%に調整してもよろしいですか?”,用户回复”room302の照明を明るさ50%に変更”)
|
||||
- 同一设备免重复确认:如果用户在当前会话中已经对某个设备的操作进行过确认,后续针对**同一设备**的操作可直接执行,无需再次确认。判定标准为:
|
||||
1. **同一设备的不同操作**:用户已确认过对某设备的控制操作后,后续对该设备的其他操作无需再次确认(如已确认关闭Define Room4的灯光,之后用户说"把灯打开",可直接执行)
|
||||
2. **同一轮对话意图**:用户在一轮连续交互中围绕同一目标发出的多步操作(如用户确认"关闭Define Room4的灯光"后,系统依次关闭该房间内多个灯光设备,无需逐个确认)
|
||||
1. **同一设备的不同操作**:用户已确认过对某设备的控制操作后,后续对该设备的其他操作无需再次确认(如已确认关闭Define Room4的灯光,之后用户说”把灯打开”,可直接执行)
|
||||
2. **同一轮对话意图**:用户在一轮连续交互中围绕同一目标发出的多步操作(如用户确认”关闭Define Room4的灯光”后,系统依次关闭该房间内多个灯光设备,无需逐个确认)
|
||||
3. **同一指令的延续执行**:用户确认某操作后,该操作因技术原因需要分步执行的后续步骤(如批量控制多个设备时,确认一次即可全部执行)
|
||||
4. **上下文明确的追加操作**:用户在已确认的操作基础上追加相同类型的操作,且目标明确无歧义(如已确认打开A房间空调后,用户说"B房间也一样",可直接执行)
|
||||
4. **上下文明确的追加操作**:用户在已确认的操作基础上追加相同类型的操作,且目标明确无歧义(如已确认打开A房间空调后,用户说”B房间也一样”,可直接执行)
|
||||
- 不同事项仍需确认:当操作涉及**未曾确认过的新设备**,或操作类型发生本质变化时(如从设备控制切换到消息通知),仍需重新确认
|
||||
|
||||
### ⚠️ 禁止二次确认(最高优先级规则)
|
||||
**对于同一个操作请求,最多只能向用户确认一次。用户确认后,必须立即调用工具执行,绝对禁止再次询问确认。**
|
||||
|
||||
核心规则:
|
||||
1. **一次确认,立即执行**:当你向用户发出确认提示后,用户回复确认,你的下一步动作**必须且只能是**调用对应的工具(如 dxcore_update_device_status)执行操作。不允许生成任何额外的确认、复述或再次询问。
|
||||
2. **禁止循环确认**:如果聊天记录中已经存在你发出的确认提示和用户的确认回复,则该操作已被确认,不得以任何理由再次要求确认。
|
||||
3. **确认后禁止的行为**:
|
||||
- ❌ 再次询问”もう一度確認いただけますか?”
|
||||
- ❌ 再次复述操作内容并要求确认
|
||||
- ❌ 以不同措辞重新询问同一操作的确认
|
||||
- ❌ 生成过渡性文字后再次要求确认
|
||||
|
||||
**正确流程示例**:
|
||||
```
|
||||
用户: “Dr3の照明を30%にして”
|
||||
AI: “ディファインルーム3の照明を30%に調整してもよろしいですか?”
|
||||
用户: “お願いします”
|
||||
AI: [立即调用 dxcore_update_device_status 执行] → “照明を30%に調整しました。”
|
||||
```
|
||||
|
||||
**错误流程(绝对禁止)**:
|
||||
```
|
||||
用户: “Dr3の照明を30%にして”
|
||||
AI: “ディファインルーム3の照明を30%に調整してもよろしいですか?”
|
||||
用户: “お願いします”
|
||||
AI: “もう一度確認いただければ実行いたします” ← ❌ 禁止!
|
||||
```
|
||||
|
||||
## 上下文推理示例
|
||||
|
||||
### 设备控制场景
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
{extra_prompt}
|
||||
|
||||
## CITATION REQUIREMENTS
|
||||
|
||||
When your answer uses learned knowledge, you MUST generate `<CITATION ... />` tags. Follow the specific citation format instructions returned by each tool (`rag_retrieve`, `table_rag_retrieve`).
|
||||
|
||||
### General Placement Rules
|
||||
1. Citations MUST appear IMMEDIATELY AFTER the paragraph or bullet list that uses the knowledge
|
||||
2. NEVER collect all citations and place them at the end of your response
|
||||
3. Limit to 1-2 citations per paragraph/bullet list - combine related facts under one citation
|
||||
4. If your answer uses learned knowledge, you MUST generate at least 1 `<CITATION ... />` in the response
|
||||
|
||||
### Current Working Directory
|
||||
|
||||
PROJECT_ROOT: `{agent_dir_path}`
|
||||
@ -92,15 +102,3 @@ Trace Id: {trace_id}
|
||||
- Even when the user writes in a different language, you MUST still reply in [{language}].
|
||||
- Do NOT mix languages. Do NOT fall back to English or any other language under any circumstances.
|
||||
- Technical terms, code identifiers, file paths, and tool names may remain in their original form, but all surrounding text MUST be in [{language}].
|
||||
|
||||
**Citation Requirement (RAG Only)**: When answering questions based on `rag_retrieve` tool results, you MUST add XML citation tags for factual claims derived from the knowledge base.
|
||||
|
||||
**MANDATORY FORMAT**: `The cited factual claim <CITATION file="file_uuid" page="3" />`
|
||||
|
||||
**Citation Rules**:
|
||||
- The citation tag MUST be placed immediately after the factual claim or paragraph
|
||||
- The `file` attribute MUST use the exact `File ID` from `rag_retrieve` document
|
||||
- The `page` attribute MUST use the exact `Page Number` from `rag_retrieve` document
|
||||
- If multiple sources support the same claim, include separate citation tags for each source
|
||||
- Example: `According to the policy, returns are accepted within 30 days <CITATION file="abc123" page="5" />.`
|
||||
- This requirement ONLY applies when using `rag_retrieve` results to answer questions.
|
||||
|
||||
@ -26,12 +26,12 @@ dependencies = [
|
||||
"chardet>=5.0.0",
|
||||
"psutil (>=7.1.3,<8.0.0)",
|
||||
"uvloop (>=0.22.1,<0.23.0)",
|
||||
"deepagents (>=0.4.3,<0.5.0)",
|
||||
"deepagents (>=0.5.2,<0.6.0)",
|
||||
"langchain-mcp-adapters (>=0.2.1,<0.3.0)",
|
||||
"langchain-openai (>=1.1.1,<2.0.0)",
|
||||
"cachetools (>=6.2.4,<7.0.0)",
|
||||
"langgraph-checkpoint-postgres (>=3.0.0,<4.0.0)",
|
||||
"deepagents-cli (>=0.0.25,<0.0.26)",
|
||||
"deepagents-cli (>=0.0.37,<0.1.0)",
|
||||
"mem0ai (>=0.1.50,<0.3.0)",
|
||||
"psycopg2-binary (>=2.9.11,<3.0.0)",
|
||||
"json-repair (>=0.29.0,<0.30.0)",
|
||||
|
||||
180
requirements.txt
180
requirements.txt
@ -1,56 +1,51 @@
|
||||
aiofiles==24.1.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
agent-client-protocol==0.9.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
aiofiles==25.1.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
aiohappyeyeballs==2.6.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
aiohttp-retry==2.9.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
aiohttp==3.13.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
aiohttp==3.13.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
aiosignal==1.4.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
aiosqlite==0.22.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
annotated-doc==0.0.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
annotated-types==0.7.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
anthropic==0.84.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
anyio==4.12.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
attrs==25.4.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
anthropic==0.94.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
anyio==4.13.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
attrs==26.1.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
backoff==2.2.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
beartype==0.22.9 ; python_version >= "3.12" and python_version < "3.15"
|
||||
beautifulsoup4==4.14.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
blockbuster==1.5.26 ; python_version >= "3.12" and python_version < "3.15"
|
||||
bracex==2.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
cachetools==6.2.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
cbor2==5.8.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
certifi==2026.2.25 ; python_version >= "3.12" and python_version < "3.15"
|
||||
cffi==2.0.0 ; python_version >= "3.12" and python_version < "3.15" and platform_python_implementation != "PyPy"
|
||||
chardet==7.1.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
charset-normalizer==3.4.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
click==8.3.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
chardet==7.4.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
charset-normalizer==3.4.7 ; python_version >= "3.12" and python_version < "3.15"
|
||||
click==8.3.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
cloudpickle==3.1.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
colorama==0.4.6 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Windows"
|
||||
croniter==3.0.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
cryptography==46.0.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
daytona-api-client-async==0.151.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
daytona-api-client==0.151.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
daytona-toolbox-api-client-async==0.151.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
daytona-toolbox-api-client==0.151.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
daytona==0.151.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
deepagents-cli==0.0.25 ; python_version >= "3.12" and python_version < "3.15"
|
||||
deepagents==0.4.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
cryptography==46.0.7 ; python_version >= "3.12" and python_version < "3.15"
|
||||
deepagents-acp==0.0.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
deepagents-cli==0.0.37 ; python_version >= "3.12" and python_version < "3.15"
|
||||
deepagents==0.5.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
defusedxml==0.7.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
deprecated==1.3.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
distro==1.9.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
docstring-parser==0.17.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
environs==14.6.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
et-xmlfile==2.0.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
fastapi==0.116.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
filelock==3.25.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
filetype==1.2.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
forbiddenfruit==0.1.4 ; python_version >= "3.12" and python_version < "3.15" and implementation_name == "cpython"
|
||||
frozenlist==1.8.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
fsspec==2026.2.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
google-auth==2.49.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
google-genai==1.67.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
googleapis-common-protos==1.73.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
greenlet==3.3.2 ; python_version >= "3.12" and python_version < "3.15" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")
|
||||
grpcio-tools==1.71.2 ; python_version >= "3.13" and python_version < "3.15"
|
||||
grpcio==1.78.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
grpclib==0.4.9 ; python_version >= "3.12" and python_version < "3.15"
|
||||
fsspec==2026.3.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
google-auth==2.49.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
google-genai==1.72.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
googleapis-common-protos==1.74.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
greenlet==3.4.0 ; python_version >= "3.12" and python_version < "3.15" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")
|
||||
grpcio-health-checking==1.76.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
grpcio-tools==1.76.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
grpcio==1.76.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
h11==0.16.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
h2==4.3.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
hf-xet==1.4.2 ; python_version >= "3.12" and python_version < "3.15" and (platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "arm64" or platform_machine == "aarch64")
|
||||
hf-xet==1.4.3 ; python_version >= "3.12" and python_version < "3.15" and (platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "arm64" or platform_machine == "aarch64")
|
||||
hpack==4.1.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
httpcore==1.0.9 ; python_version >= "3.12" and python_version < "3.15"
|
||||
httpx-sse==0.4.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
@ -61,94 +56,94 @@ hyperframe==6.1.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
idna==3.11 ; python_version >= "3.12" and python_version < "3.15"
|
||||
importlib-metadata==8.7.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jinja2==3.1.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jiter==0.13.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jiter==0.14.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
joblib==1.5.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
json-repair==0.29.10 ; python_version >= "3.12" and python_version < "3.15"
|
||||
json5==0.13.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
json5==0.14.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jsonpatch==1.33 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jsonpointer==3.0.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jsonpointer==3.1.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jsonschema-rs==0.29.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jsonschema-specifications==2025.9.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
jsonschema==4.26.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-anthropic==1.3.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-core==1.2.19 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-anthropic==1.4.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-core==1.2.28 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-google-genai==4.2.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-mcp-adapters==0.2.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-openai==1.1.11 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain==1.2.12 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-checkpoint-postgres==3.0.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-mcp-adapters==0.2.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain-openai==1.1.12 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langchain==1.2.15 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-api==0.7.28 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-checkpoint-postgres==3.0.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-checkpoint-sqlite==3.0.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-checkpoint==4.0.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-prebuilt==1.0.8 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-sdk==0.3.11 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph==1.1.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langsmith==0.7.17 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-cli==0.4.21 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-prebuilt==1.0.9 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-runtime-inmem==0.24.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph-sdk==0.3.13 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langgraph==1.1.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
langsmith==0.7.30 ; python_version >= "3.12" and python_version < "3.15"
|
||||
linkify-it-py==2.1.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
markdown-it-py==4.0.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
markdownify==1.2.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
markupsafe==3.0.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
marshmallow==4.2.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
mcp==1.12.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
mdit-py-plugins==0.5.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
mdurl==0.1.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
mem0ai==0.1.116 ; python_version >= "3.12" and python_version < "3.15"
|
||||
modal==1.3.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
mem0ai==0.1.115 ; python_version >= "3.12" and python_version < "3.15"
|
||||
mpmath==1.3.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
multidict==6.7.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
networkx==3.6 ; python_version == "3.14"
|
||||
networkx==3.6.1 ; python_version >= "3.12" and python_version < "3.14"
|
||||
numpy==1.26.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
nvidia-cublas-cu12==12.1.3.1 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-cuda-cupti-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-cuda-nvrtc-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-cuda-runtime-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-cudnn-cu12==8.9.2.26 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-cufft-cu12==11.0.2.54 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-curand-cu12==10.3.2.106 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-cusolver-cu12==11.4.5.107 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-cusparse-cu12==12.1.0.106 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-nccl-cu12==2.19.3 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-nvjitlink-cu12==12.9.86 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
nvidia-nvtx-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
obstore==0.8.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
openai==2.28.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
nvidia-cublas-cu12==12.1.3.1 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-cuda-cupti-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-cuda-nvrtc-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-cuda-runtime-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-cudnn-cu12==8.9.2.26 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-cufft-cu12==11.0.2.54 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-curand-cu12==10.3.2.106 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-cusolver-cu12==11.4.5.107 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-cusparse-cu12==12.1.0.106 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-nccl-cu12==2.19.3 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-nvjitlink-cu12==12.9.86 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
nvidia-nvtx-cu12==12.1.105 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
openai==2.31.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
openpyxl==3.1.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-api==1.40.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-exporter-otlp-proto-common==1.40.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-exporter-otlp-proto-http==1.40.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-instrumentation-aiohttp-client==0.61b0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-instrumentation==0.61b0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-proto==1.40.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-sdk==1.40.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-semantic-conventions==0.61b0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-util-http==0.61b0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
orjson==3.11.7 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-api==1.41.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-exporter-otlp-proto-common==1.41.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-exporter-otlp-proto-http==1.41.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-proto==1.41.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-sdk==1.41.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
opentelemetry-semantic-conventions==0.62b0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
orjson==3.11.8 ; python_version >= "3.12" and python_version < "3.15"
|
||||
ormsgpack==1.12.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
packaging==26.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pandas==2.3.3 ; python_version == "3.14"
|
||||
pandas==3.0.1 ; python_version >= "3.12" and python_version < "3.14"
|
||||
pillow==12.1.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
platformdirs==4.9.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pandas==3.0.2 ; python_version >= "3.12" and python_version < "3.14"
|
||||
pathspec==1.0.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pillow==12.2.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
platformdirs==4.9.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
portalocker==2.10.1 ; python_version >= "3.13" and python_version < "3.15"
|
||||
portalocker==3.2.0 ; python_version == "3.12"
|
||||
posthog==7.9.12 ; python_version >= "3.12" and python_version < "3.15"
|
||||
posthog==7.11.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
prompt-toolkit==3.0.52 ; python_version >= "3.12" and python_version < "3.15"
|
||||
propcache==0.4.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
protobuf==5.29.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
protobuf==6.33.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
psutil==7.2.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
psycopg-pool==3.3.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
psycopg2-binary==2.9.11 ; python_version >= "3.12" and python_version < "3.15"
|
||||
psycopg==3.3.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pyasn1-modules==0.4.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pyasn1==0.6.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pycparser==3.0 ; python_version >= "3.12" and python_version < "3.15" and implementation_name != "PyPy" and platform_python_implementation != "PyPy"
|
||||
pyasn1==0.6.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pycparser==3.0 ; python_version >= "3.12" and python_version < "3.15" and platform_python_implementation != "PyPy" and implementation_name != "PyPy"
|
||||
pydantic-core==2.27.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pydantic-settings==2.13.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pydantic==2.10.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pygments==2.19.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pygments==2.20.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pyjwt==2.12.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pyperclip==1.11.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
python-dateutil==2.8.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
python-dotenv==1.2.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
python-multipart==0.0.22 ; python_version >= "3.12" and python_version < "3.15"
|
||||
python-multipart==0.0.26 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pytz==2026.1.post1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
pywin32==311 ; python_version >= "3.12" and python_version < "3.15" and (sys_platform == "win32" or platform_system == "Windows")
|
||||
pyyaml==6.0.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
@ -156,46 +151,42 @@ qdrant-client==1.12.1 ; python_version >= "3.13" and python_version < "3.15"
|
||||
qdrant-client==1.17.1 ; python_version == "3.12"
|
||||
ragflow-sdk==0.23.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
referencing==0.37.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
regex==2026.2.28 ; python_version >= "3.12" and python_version < "3.15"
|
||||
regex==2026.4.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
requests-toolbelt==1.0.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
requests==2.32.5 ; python_version >= "3.12" and python_version < "3.15"
|
||||
rich==14.3.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
rich==14.3.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
rpds-py==0.30.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
runloop-api-client==1.11.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
safetensors==0.7.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
scikit-learn==1.8.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
scipy==1.17.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sentence-transformers==3.4.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
setuptools==70.3.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
shellingham==1.5.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
six==1.17.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sniffio==1.3.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
soupsieve==2.8.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sqlalchemy==2.0.48 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sqlite-vec==0.1.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sse-starlette==3.0.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sqlalchemy==2.0.49 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sqlite-vec==0.1.9 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sse-starlette==2.1.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
starlette==0.47.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
structlog==25.5.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
sympy==1.14.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
synchronicity==0.11.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
tavily-python==0.7.23 ; python_version >= "3.12" and python_version < "3.15"
|
||||
tenacity==9.1.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
textual-autocomplete==4.0.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
textual==8.1.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
textual-speedups==0.2.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
textual==8.2.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
threadpoolctl==3.6.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
tiktoken==0.12.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
tokenizers==0.22.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
toml==0.10.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
tomli-w==1.2.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
torch==2.2.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
tqdm==4.67.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
transformers==4.57.6 ; python_version >= "3.12" and python_version < "3.15"
|
||||
triton==2.2.0 ; python_version >= "3.12" and python_version < "3.15" and platform_machine == "x86_64" and platform_system == "Linux"
|
||||
typer==0.24.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
types-certifi==2021.10.8.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
types-toml==0.10.8.20240310 ; python_version >= "3.12" and python_version < "3.15"
|
||||
triton==2.2.0 ; python_version >= "3.12" and python_version < "3.15" and platform_system == "Linux" and platform_machine == "x86_64"
|
||||
truststore==0.10.4 ; python_version >= "3.12" and python_version < "3.15"
|
||||
typing-extensions==4.15.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
typing-inspection==0.4.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
tzdata==2025.3 ; python_version >= "3.12" and python_version < "3.15" and (sys_platform == "win32" or sys_platform == "emscripten") or python_version == "3.14"
|
||||
tzdata==2026.1 ; python_version >= "3.12" and python_version < "3.15" and (sys_platform == "win32" or sys_platform == "emscripten") or python_version == "3.14"
|
||||
uc-micro-py==2.0.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
urllib3==2.6.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
uuid-utils==0.14.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
@ -206,7 +197,6 @@ wcmatch==10.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
wcwidth==0.6.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
webrtcvad==2.0.10 ; python_version >= "3.12" and python_version < "3.15"
|
||||
websockets==15.0.1 ; python_version >= "3.12" and python_version < "3.15"
|
||||
wrapt==1.17.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
wsgidav==4.3.3 ; python_version >= "3.12" and python_version < "3.15"
|
||||
xlrd==2.0.2 ; python_version >= "3.12" and python_version < "3.15"
|
||||
xxhash==3.6.0 ; python_version >= "3.12" and python_version < "3.15"
|
||||
|
||||
@ -5,7 +5,6 @@ API data models and response schemas.
|
||||
|
||||
from typing import Dict, List, Optional, Any, AsyncGenerator
|
||||
from pydantic import BaseModel, Field, field_validator, ConfigDict
|
||||
from utils.settings import DEFAULT_THINKING_ENABLE
|
||||
|
||||
class Message(BaseModel):
|
||||
role: str
|
||||
@ -52,7 +51,7 @@ class ChatRequest(BaseModel):
|
||||
mcp_settings: Optional[List[Dict]] = None
|
||||
user_identifier: Optional[str] = ""
|
||||
session_id: Optional[str] = None
|
||||
enable_thinking: Optional[bool] = DEFAULT_THINKING_ENABLE
|
||||
enable_thinking: Optional[bool] = False
|
||||
skills: Optional[List[str]] = None
|
||||
enable_memory: Optional[bool] = False
|
||||
shell_env: Optional[Dict[str, str]] = None
|
||||
|
||||
@ -12,7 +12,7 @@ MAX_OUTPUT_TOKENS = int(os.getenv("MAX_OUTPUT_TOKENS", 8000))
|
||||
|
||||
# 可选参数
|
||||
# Summarization Settings
|
||||
SUMMARIZATION_MAX_TOKENS = int(MAX_CONTEXT_TOKENS/3)
|
||||
SUMMARIZATION_MAX_TOKENS = int(MAX_CONTEXT_TOKENS/2)
|
||||
SUMMARIZATION_TOKENS_TO_KEEP = int(SUMMARIZATION_MAX_TOKENS/3)
|
||||
DEFAULT_TRIM_TOKEN_LIMIT = SUMMARIZATION_MAX_TOKENS - SUMMARIZATION_TOKENS_TO_KEEP + 5000
|
||||
|
||||
@ -32,11 +32,9 @@ TOKENIZERS_PARALLELISM = os.getenv("TOKENIZERS_PARALLELISM", "true")
|
||||
SENTENCE_TRANSFORMER_MODEL = os.getenv("SENTENCE_TRANSFORMER_MODEL", "TaylorAI/gte-tiny")
|
||||
|
||||
# Tool Output Length Control Settings
|
||||
TOOL_OUTPUT_MAX_LENGTH = int(SUMMARIZATION_MAX_TOKENS/4)
|
||||
TOOL_OUTPUT_MAX_LENGTH = SUMMARIZATION_MAX_TOKENS
|
||||
TOOL_OUTPUT_TRUNCATION_STRATEGY = os.getenv("TOOL_OUTPUT_TRUNCATION_STRATEGY", "smart")
|
||||
|
||||
# THINKING ENABLE
|
||||
DEFAULT_THINKING_ENABLE = os.getenv("DEFAULT_THINKING_ENABLE", "true") == "true"
|
||||
|
||||
|
||||
# WebDAV Authentication
|
||||
@ -59,7 +57,7 @@ CHECKPOINT_DB_URL = os.getenv("CHECKPOINT_DB_URL", "postgresql://postgres:AeEGDB
|
||||
# 连接池大小
|
||||
# 同时可以持有的最大连接数
|
||||
CHECKPOINT_POOL_SIZE = int(os.getenv("CHECKPOINT_POOL_SIZE", "20"))
|
||||
MEM0_POOL_SIZE = int(os.getenv("MEM0_POOL_SIZE", "20"))
|
||||
MEM0_POOL_SIZE = int(os.getenv("MEM0_POOL_SIZE", "50"))
|
||||
|
||||
# Checkpoint 自动清理配置
|
||||
# 是否启用自动清理旧 session
|
||||
|
||||
Loading…
Reference in New Issue
Block a user