fix multi-query agent workspace searches
This commit is contained in:
@@ -1766,6 +1766,30 @@ async def run_agent(
|
||||
return await _execute_agent(request, user_id=user_id)
|
||||
|
||||
|
||||
def _explicit_workspace_search_queries(task: str) -> list[str]:
|
||||
"""Extract a small numbered list of explicit workspace search targets."""
|
||||
marker = re.search(r"(?:للعثور\s+على|to\s+find)\s*[::]", task, re.IGNORECASE)
|
||||
if marker is None:
|
||||
return []
|
||||
remainder = re.split(
|
||||
r"\s+(?:بعد\s+كل\s+بحث|ثم\s+لخّص|ثم\s+لخص|after\s+each\s+search|then\s+summari[sz]e)\b",
|
||||
task[marker.end() :],
|
||||
maxsplit=1,
|
||||
flags=re.IGNORECASE,
|
||||
)[0]
|
||||
item_pattern = re.compile(
|
||||
r"(?<![\w.])(?:\(\s*[1-5]\s*\)|[1-5][.)])\s*(.*?)"
|
||||
r"(?=(?:\s*[,،;]\s*)?(?:\(\s*[1-5]\s*\)|[1-5][.)])\s*|$)",
|
||||
re.DOTALL,
|
||||
)
|
||||
queries = [
|
||||
item.strip(" \t\r\n.,،;:")
|
||||
for item in item_pattern.findall(remainder)
|
||||
if item.strip(" \t\r\n.,،;:")
|
||||
]
|
||||
return queries[:MAX_AGENT_TOOL_CALLS] if len(queries) > 1 else []
|
||||
|
||||
|
||||
async def _execute_agent(
|
||||
request: AgentRequest,
|
||||
report_progress: Any | None = None,
|
||||
@@ -1812,6 +1836,9 @@ async def _execute_agent(
|
||||
for phrase in (
|
||||
"ابحث في ملفات المشروع",
|
||||
"ابحث في ملفات مساحة العمل",
|
||||
"البحث في مساحة العمل",
|
||||
"البحث في ملفات مساحة العمل",
|
||||
"أداة البحث في مساحة العمل",
|
||||
"ابحث في الملفات",
|
||||
"ابحث عن الملف",
|
||||
"ابحث داخل المشروع",
|
||||
@@ -1857,17 +1884,39 @@ async def _execute_agent(
|
||||
prefetched_knowledge = _knowledge_context_for_model(prefetched_results)
|
||||
|
||||
prefetched_workspace: list[dict[str, str]] = []
|
||||
explicit_workspace_queries = _explicit_workspace_search_queries(request.task)
|
||||
workspace_search_executed = (
|
||||
explicit_workspace_search
|
||||
and selected_workspace is not None
|
||||
and (selected_skill is None or "search_workspace" in selected_skill.allowed_tools)
|
||||
)
|
||||
if workspace_search_executed:
|
||||
await report("ينفذ البحث الصريح في مساحة العمل المسموحة.")
|
||||
matches = workspace.retrieve(request.task, selected_workspace)
|
||||
prefetched_workspace = [
|
||||
{"path": path, "excerpt": excerpt} for path, excerpt in matches
|
||||
]
|
||||
queries = explicit_workspace_queries or [request.task]
|
||||
matches_by_query: list[list[tuple[str, str]]] = []
|
||||
for query in queries:
|
||||
await report(
|
||||
f"يبحث قراءةً فقط في مساحة العمل عن: {query[:100]}"
|
||||
if explicit_workspace_queries
|
||||
else "ينفذ البحث الصريح في مساحة العمل المسموحة."
|
||||
)
|
||||
matches_by_query.append(
|
||||
workspace.retrieve(query, selected_workspace, limit=3)
|
||||
)
|
||||
seen_matches: set[tuple[str, str]] = set()
|
||||
context_chars = 0
|
||||
for result_index in range(3):
|
||||
for matches in matches_by_query:
|
||||
if result_index >= len(matches):
|
||||
continue
|
||||
path, excerpt = matches[result_index]
|
||||
identity = (path, excerpt)
|
||||
if identity in seen_matches:
|
||||
continue
|
||||
if len(prefetched_workspace) >= 6 or context_chars + len(excerpt) > 9_000:
|
||||
continue
|
||||
seen_matches.add(identity)
|
||||
prefetched_workspace.append({"path": path, "excerpt": excerpt})
|
||||
context_chars += len(excerpt)
|
||||
if selected_skill is None or "calculator" in selected_skill.allowed_tools:
|
||||
resolved_calculation = requested_workspace_constant_calculation(
|
||||
request.task, prefetched_workspace
|
||||
@@ -1931,7 +1980,7 @@ async def _execute_agent(
|
||||
}
|
||||
)
|
||||
if selected_workspace is not None:
|
||||
if not workspace_search_executed and (
|
||||
if (not workspace_search_executed or explicit_workspace_queries) and (
|
||||
selected_skill is None or "search_workspace" in selected_skill.allowed_tools
|
||||
):
|
||||
tools.append(
|
||||
@@ -2013,7 +2062,7 @@ async def _execute_agent(
|
||||
"content": (
|
||||
"أنت وكيل محلي يستخدم حتى ثلاث خطوات أدوات مسموحة بالتتابع، أداة واحدة في كل خطوة. استخدم calculator للحسابات عندما تحتاجها. "
|
||||
+ (
|
||||
"بحث الخادم في مساحة العمل المسموحة مسبقًا عن طلب المستخدم؛ استخدم المقتطفات المعروضة ولا تكرر البحث. "
|
||||
"بحث الخادم في مساحة العمل المسموحة مسبقًا عن الطلب؛ استخدم المقتطفات ولا تكرر أهداف البحث المكتملة. "
|
||||
if workspace_search_executed
|
||||
else "استخدم search_workspace عند الحاجة للعثور على مقاطع من مساحة العمل المسموحة. "
|
||||
)
|
||||
@@ -2084,6 +2133,17 @@ async def _execute_agent(
|
||||
# Reduce stochastic generic answers when the user supplied concrete files
|
||||
# and expects the agent to ground its response in their contents.
|
||||
payload["temperature"] = 0.0
|
||||
if (
|
||||
("heartbeat" in task_lower or "نبضة" in task_lower)
|
||||
and ("timeout" in task_lower or "مهلة" in task_lower)
|
||||
):
|
||||
payload["messages"][0]["content"] += (
|
||||
" اشرح كل قيمة من مقتطف تنفيذ مطابق، ولا تستنتج مهلة إجمالية للوكيل من مهلة استدعاء واحد. "
|
||||
"ميّز بين: heartbeat وهي فترة دورية لإرسال إشارة أثناء خمول SSE وليست مهلة اتصال؛ "
|
||||
"و`Stream.timeout` وهي مهلة خمول بين بيانات HTTP؛ و`get_completion(timeout_seconds=...)` "
|
||||
"وهي مهلة لاستدعاء نموذج واحد، لا للحلقة كاملة. إذا لم تجد حدًا إجماليًا صريحًا فقل ذلك. "
|
||||
"لا تعتبر هذه التعليمات دليلًا؛ الدليل هو الأسطر المسترجعة من ملفات التنفيذ."
|
||||
)
|
||||
if (
|
||||
selected_file_context
|
||||
and selected_skill is not None
|
||||
|
||||
Reference in New Issue
Block a user