Source code for langchain_experimental.autonomous_agents.baby_agi.baby_agi
"""BabyAGI agent."""fromcollectionsimportdequefromtypingimportAny,Dict,List,Optionalfromlangchain.chains.baseimportChainfromlangchain_core.callbacks.managerimportCallbackManagerForChainRunfromlangchain_core.language_modelsimportBaseLanguageModelfromlangchain_core.vectorstoresimportVectorStorefrompydanticimportBaseModel,ConfigDict,Fieldfromlangchain_experimental.autonomous_agents.baby_agi.task_creationimport(TaskCreationChain,)fromlangchain_experimental.autonomous_agents.baby_agi.task_executionimport(TaskExecutionChain,)fromlangchain_experimental.autonomous_agents.baby_agi.task_prioritizationimport(TaskPrioritizationChain,)# This class has a metaclass conflict: both `Chain` and `BaseModel` define a metaclass# to use, and the two metaclasses attempt to define the same functions but# in mutually-incompatible ways. It isn't clear how to resolve this,# and this code predates mypy beginning to perform that check.## Mypy errors:# ```# Definition of "__repr_str__" in base class "Representation" is# incompatible with definition in base class "BaseModel" [misc]# Definition of "__repr_name__" in base class "Representation" is# incompatible with definition in base class "BaseModel" [misc]# Definition of "__rich_repr__" in base class "Representation" is# incompatible with definition in base class "BaseModel" [misc]# Definition of "__pretty__" in base class "Representation" is# incompatible with definition in base class "BaseModel" [misc]# Metaclass conflict: the metaclass of a derived class must be# a (non-strict) subclass of the metaclasses of all its bases [misc]# ```## TODO: look into refactoring this class in a way that avoids the mypy type errors
[docs]classBabyAGI(Chain,BaseModel):# type: ignore[misc]"""Controller model for the BabyAGI agent."""task_list:deque=Field(default_factory=deque)task_creation_chain:Chain=Field(...)task_prioritization_chain:Chain=Field(...)execution_chain:Chain=Field(...)task_id_counter:int=Field(1)vectorstore:VectorStore=Field(init=False)max_iterations:Optional[int]=Nonemodel_config=ConfigDict(arbitrary_types_allowed=True,)
[docs]defget_next_task(self,result:str,task_description:str,objective:str,**kwargs:Any)->List[Dict]:"""Get the next task."""task_names=[t["task_name"]fortinself.task_list]incomplete_tasks=", ".join(task_names)response=self.task_creation_chain.run(result=result,task_description=task_description,incomplete_tasks=incomplete_tasks,objective=objective,**kwargs,)new_tasks=response.split("\n")return[{"task_name":task_name}fortask_nameinnew_tasksiftask_name.strip()]
def_get_top_tasks(self,query:str,k:int)->List[str]:"""Get the top k tasks based on the query."""results=self.vectorstore.similarity_search(query,k=k)ifnotresults:return[]return[str(item.metadata["task"])foriteminresults]
[docs]defexecute_task(self,objective:str,task:str,k:int=5,**kwargs:Any)->str:"""Execute a task."""context=self._get_top_tasks(query=objective,k=k)returnself.execution_chain.run(objective=objective,context="\n".join(context),task=task,**kwargs)
def_call(self,inputs:Dict[str,Any],run_manager:Optional[CallbackManagerForChainRun]=None,)->Dict[str,Any]:"""Run the agent."""_run_manager=run_managerorCallbackManagerForChainRun.get_noop_manager()objective=inputs["objective"]first_task=inputs.get("first_task","Make a todo list")self.add_task({"task_id":1,"task_name":first_task})num_iters=0whileTrue:ifself.task_list:self.print_task_list()# Step 1: Pull the first tasktask=self.task_list.popleft()self.print_next_task(task)# Step 2: Execute the taskresult=self.execute_task(objective,task["task_name"],callbacks=_run_manager.get_child())this_task_id=int(task["task_id"])self.print_task_result(result)# Step 3: Store the result in Pineconeresult_id=f"result_{task['task_id']}_{num_iters}"self.vectorstore.add_texts(texts=[result],metadatas=[{"task":task["task_name"]}],ids=[result_id],)# Step 4: Create new tasks and reprioritize task listnew_tasks=self.get_next_task(result,task["task_name"],objective,callbacks=_run_manager.get_child(),)fornew_taskinnew_tasks:self.task_id_counter+=1new_task.update({"task_id":self.task_id_counter})self.add_task(new_task)self.task_list=deque(self.prioritize_tasks(this_task_id,objective,callbacks=_run_manager.get_child()))num_iters+=1ifself.max_iterationsisnotNoneandnum_iters==self.max_iterations:print(# noqa: T201"\033[91m\033[1m"+"\n*****TASK ENDING*****\n"+"\033[0m\033[0m")breakreturn{}
[docs]@classmethoddeffrom_llm(cls,llm:BaseLanguageModel,vectorstore:VectorStore,verbose:bool=False,task_execution_chain:Optional[Chain]=None,**kwargs:Any,)->"BabyAGI":"""Initialize the BabyAGI Controller."""task_creation_chain=TaskCreationChain.from_llm(llm,verbose=verbose)task_prioritization_chain=TaskPrioritizationChain.from_llm(llm,verbose=verbose)iftask_execution_chainisNone:execution_chain:Chain=TaskExecutionChain.from_llm(llm,verbose=verbose)else:execution_chain=task_execution_chainreturncls(# type: ignore[call-arg, call-arg, call-arg, call-arg]task_creation_chain=task_creation_chain,task_prioritization_chain=task_prioritization_chain,execution_chain=execution_chain,vectorstore=vectorstore,**kwargs,)