Files
liqiang b119135836
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
2026-08-20 13:12:50 +00:00

161 lines
5.9 KiB
Python

# coding: utf-8
# Copyright (c) 2025 inclusionAI.
import abc
import os
import time
import uuid
from typing import Callable, Any
from pydantic import BaseModel
import aworld.tools
from aworld.config import ConfigDict
from aworld.config.conf import ToolConfig
from aworld.core.agent.swarm import Swarm
from aworld.core.common import Observation
from aworld.core.context.base import Context
from aworld.core.context.session import Session
from aworld.core.tool.base import Tool, AsyncTool
from aworld.core.task import Task, TaskResponse, Runner
from aworld.logs.util import logger
from aworld import trace, cleanup
from aworld.utils.common import load_module_by_path
class TaskRunner(Runner):
"""Task based runner api class."""
__metaclass__ = abc.ABCMeta
def __init__(self,
task: Task,
*,
agent_oriented: bool = True,
daemon_target: Callable[..., Any] = None):
"""Task runner initialize.
Args:
task: Task entity to be executed.
agent_oriented: Is it an agent oriented task, default is True.
"""
if task.tools is None:
task.tools = []
if task.tool_names is None:
task.tool_names = []
if agent_oriented:
if not task.agent and not task.swarm:
raise ValueError("agent and swarm all is None.")
if task.agent and task.swarm:
logger.warning("agent and swarm all is not None.")
raise ValueError("agent and swarm choose one only.")
if task.agent:
# uniform agent
task.swarm = Swarm(task.agent)
if task.conf is None:
task.conf = dict()
if isinstance(task.conf, BaseModel):
task.conf = task.conf.model_dump()
task.conf = ConfigDict(task.conf)
check_input = task.conf.get("check_input", False)
if check_input and not task.input:
raise ValueError("task no input")
if not task.is_sub_task:
self.context = task.context if task.context else Context()
self.context.set_task(task)
self.task = task
self.agent_oriented = agent_oriented
self.daemon_target = daemon_target
self._use_demon = False if not task.conf else task.conf.get(
'use_demon', False)
self._exception = None
self.start_time = time.time()
self.step_agent_counter = {}
async def pre_run(self):
task = self.task
# copy context from parent_task(if exists)
if task.is_sub_task:
task.context = await task.context.build_sub_context(
task.input, task.id,
agents=task.swarm.agents if task.swarm and task.swarm.agents else None
)
self.context = task.context
self.context.set_task(task)
self.swarm = task.swarm
self.input = task.input
self.outputs = task.outputs
self.name = task.name
self.conf = task.conf if task.conf else ConfigDict()
self.tools = {
tool.name(): tool for tool in task.tools} if task.tools else {}
task.tool_names.extend(self.tools.keys())
# lazy load
self.tool_names = task.tool_names
self.tools_conf = task.tools_conf
if self.tools_conf is None:
self.tools_conf = {}
# mcp performs special process, use async only in the runn
self.tools_conf['mcp'] = ToolConfig(use_async=True, name='mcp')
self.endless_threshold = task.endless_threshold
# build context
if task.session_id:
session = Session(session_id=task.session_id)
else:
session = Session(session_id=uuid.uuid4().hex)
trace_id = uuid.uuid1().hex if trace.get_current_span(
) is None else trace.get_current_span().get_trace_id()
self.context.task_id = self.task.id
self.context.trace_id = trace_id
self.context.session = session
self.context.swarm = self.swarm
# init tool state by reset(), and ignore them observation
observation = None
if self.tools:
for _, tool in self.tools.items():
# use the observation and info of the last one
if isinstance(tool, Tool):
tool.context = self.context
observation, info = tool.reset()
elif isinstance(tool, AsyncTool):
observation, info = await tool.reset()
else:
logger.warning(f"Unsupported tool type: {tool}, will ignored.")
if observation:
if not observation.content:
observation.content = self.input
else:
observation = Observation(content=self.input)
self.observation = observation
if self.swarm:
self.swarm.event_driven = task.event_driven
self.swarm.reset(observation.content,
context=self.context, tools=self.tool_names)
self._load_tool_module()
logger.info(f'{"sub task: " if self.task.is_sub_task else "main task: "}{self.task.id} started...')
def _load_tool_module(self):
# used to distributed running local tools
try:
value = os.environ.get(aworld.tools.LOCAL_TOOLS_ENV_VAR, '')
if value:
for val in value.split(";"):
load_module_by_path(os.path.basename(val).replace("_action", ""),
val.replace("_action.py", ".py"))
load_module_by_path(os.path.basename(val), val)
except:
logger.warning(f"{os.environ.get(aworld.tools.LOCAL_TOOLS_ENV_VAR, '')} tools load fail, can't use them!!")
async def post_run(self):
pass
@abc.abstractmethod
async def do_run(self, context: Context = None) -> TaskResponse:
"""Task do run."""