feat: raise configurable chat tool call limit
This commit is contained in:
@@ -10,6 +10,7 @@ from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from .actions import action_dict, confirm, prepare, require_scope
|
||||
from .agent_tools import execute, tool_specs
|
||||
from .config import get_settings
|
||||
from .db import get_db
|
||||
from .llm import ModelError
|
||||
from .models import AgentRun, ChatMessage, Conversation, PendingAction, Project, ScoringBatch, now
|
||||
@@ -113,7 +114,10 @@ def _run_agent(factory, conversation_id, run_id, user_text):
|
||||
"project_id": conversation.project_id}, ensure_ascii=False)}]
|
||||
messages.extend({"role": m.role, "content": m.content[:4000]} for m in history)
|
||||
yield _event("run", {"id": run.id, "status": "running"})
|
||||
for round_number in range(4):
|
||||
max_tool_calls = get_settings().chat_max_tool_calls
|
||||
attempted_calls = 0
|
||||
# One extra model response lets the agent answer after its last allowed tool call.
|
||||
for _ in range(max_tool_calls + 1):
|
||||
reply = client.tool_call(messages, tool_specs())
|
||||
calls = reply.get("tool_calls") or []
|
||||
if not calls:
|
||||
@@ -121,16 +125,17 @@ def _run_agent(factory, conversation_id, run_id, user_text):
|
||||
if not isinstance(content, str) or not content.strip():
|
||||
raise ModelError("对话模型未返回文字或工具调用")
|
||||
db.add(ChatMessage(conversation_id=conversation_id, role="assistant", content=content,
|
||||
citations=citations[:20], tool_calls=used[:8]))
|
||||
citations=citations[:20], tool_calls=used))
|
||||
run.status, run.finished_at = "completed", now()
|
||||
conversation.updated_at = now()
|
||||
db.commit()
|
||||
completed = True
|
||||
yield _event("message", {"content": content, "citations": citations[:20], "tool_calls": used[:8]})
|
||||
yield _event("message", {"content": content, "citations": citations[:20], "tool_calls": used})
|
||||
yield _event("done", {"run_id": run.id})
|
||||
return
|
||||
if len(calls) + len(used) > 8:
|
||||
raise ModelError("单轮工具调用超过上限 8 次")
|
||||
if attempted_calls + len(calls) > max_tool_calls:
|
||||
raise ModelError(f"本次消息工具调用超过上限 {max_tool_calls} 次")
|
||||
attempted_calls += len(calls)
|
||||
messages.append({"role": "assistant", "content": reply.get("content"), "tool_calls": calls})
|
||||
for call in calls:
|
||||
name = call.get("function", {}).get("name", "")
|
||||
@@ -155,7 +160,7 @@ def _run_agent(factory, conversation_id, run_id, user_text):
|
||||
messages.append({"role": "tool", "tool_call_id": call_id,
|
||||
"content": json.dumps({"error": error[:500]}, ensure_ascii=False)})
|
||||
yield _event("tool", {"name": name, "status": "failed", "error": error[:500]})
|
||||
raise ModelError("模型工具调用轮数超过上限 4 次")
|
||||
raise ModelError(f"本次消息模型调用超过上限 {max_tool_calls + 1} 轮")
|
||||
except Exception as exc:
|
||||
run.status, run.error, run.finished_at = "failed", str(exc)[:500], now()
|
||||
db.commit()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
|
||||
from pydantic import Field
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
@@ -23,6 +24,7 @@ class Settings(BaseSettings):
|
||||
model_timeout_seconds: int = 120
|
||||
model_concurrency: int = 2
|
||||
model_retries: int = 2
|
||||
chat_max_tool_calls: int = Field(default=32, ge=1, le=64)
|
||||
|
||||
|
||||
@lru_cache
|
||||
|
||||
Reference in New Issue
Block a user