官网例子1
实现例子
import asyncio #asyncio 模块,用于处理异步操作。
from metagpt.roles import (
Architect,
Engineer,
ProductManager,
ProjectManager,
)
from metagpt.team import Team
async def startup(idea: str):
company = Team()
company.hire(
[
ProductManager(),
Architect(),
ProjectManager(),
Engineer(),
]
)
company.invest(investment=3.0)
company.run_project(idea=idea)
await company.run(n_round=5)# 调用 asyncio.run 方法启动事件循环,并运行 startup 函数
metagpt/team.py
初始化
def __init__(self, context: Context = None, **data: Any):
super(Team, self).__init__(**data)
ctx = context or Context()
if not self.env:
self.env = Environment(context=ctx)
else:
self.env.context = ctx # The `env` object is allocated by deserialization
if "roles" in data:
self.hire(data["roles"])
if "env_desc" in data:
self.env.desc = data["env_desc"]
初始化方法中,在本例子中,上文导入了metagpt.roles
,故将初始化self.hire(data["roles"])
方法,一个 Role 能执行特定的 Action,拥有记忆、思考并采用各种策略行动。
hire
def hire(self, roles: list[Role]): self.env.add_roles(roles)
本质是将上述角色并添加到环境中。
invest
@property
def cost_manager(self):
"""Get cost manager"""
return self.env.context.cost_manager
def invest(self, investment: float):
self.investment = investment
self.cost_manager.max_budget = investment
logger.info(f"Investment: ${investment}.")
将预算赋值给self.investment
,并设置最大预算。预算根据每次请求返回到token数计算消耗的金额,进行扣减,当扣减到0元时,程序提前结束。
学习记录
@property
装饰器用于将一个方法转换为属性。这意味着你可以像访问属性一样访问这个方法,而无需显式调用它。这对于需要计算或逻辑处理的属性非常有用,但你希望用户能够像访问普通属性一样使用它。
@classmethod
装饰器用于定义类方法。类方法的第一个参数是类本身,而不是实例。这个参数通常命名为cls
。类方法可以访问类的属性和方法,但不能访问实例属性。类方法通常用于创建工厂方法(例如,返回类的不同实例)。
run_project
def run_project(self, idea, send_to: str = ""):
self.idea = idea
self.env.publish_message(
Message(role="Human", content=idea, cause_by=UserRequirement, send_to=send_to or MESSAGE_ROUTE_TO_ALL),
peekable=False,
)
@serialize_decorator
async def run(self, n_round=3, idea="", send_to="", auto_archive=True):
if idea:
self.run_project(idea=idea, send_to=send_to)
while n_round > 0:
n_round -= 1
self._check_balance()
await self.env.run()
logger.debug(f"max {n_round=} left.")
self.env.archive(auto_archive)
return self.env.history
RAG
定义
RAG(Retrieval-Augmented Generation)通过引用外部权威知识库来优化大型语言模型(LLM)的输出,增强其生成响应的能力。这种方法允许LLM在不重新训练的情况下,访问特定领域的知识,提高输出的相关性、准确性和实用性。
本文主要介绍当前MetaGPT所提供的RAG功能:
-
数据输入,支持多种格式文件(包括pdf/docx/md/csv/txt/ppt)、python对象
-
检索功能,支持faiss/bm25/chromadb/es,并支持混合检索
-
检索后处理,支持LLM Rerank/ColbertRerank,对上面检索出来的内容进行重排以得到更准确的数据
-
数据更新,增加文本与python对象
-
数据保存及恢复,不用每次都进行向
源码查看
from metagpt.rag.engines import SimpleEngine
init
class SimpleEngine(RetrieverQueryEngine):
"""SimpleEngine is designed to be simple and straightforward.
It is a lightweight and easy-to-use search engine that integrates
document reading, embedding, indexing, retrieving, and ranking functionalities
into a single, straightforward workflow. It is designed to quickly set up a
search engine from a collection of documents.
"""
def __init__(
self,
retriever: BaseRetriever,
response_synthesizer: Optional[BaseSynthesizer] = None,
node_postprocessors: Optional[list[BaseNodePostprocessor]] = None,
callback_manager: Optional[CallbackManager] = None,
transformations: Optional[list[TransformComponent]] = None,
) -> None:
super().__init__(
retriever=retriever,
response_synthesizer=response_synthesizer,
node_postprocessors=node_postprocessors,
callback_manager=callback_manager,
)
self._transformations = transformations or self._default_transformations()
下面三个在父类RetrieverQueryEngine有定义:
retriever: 一个检索器对象
response_synthesizer: 一个可选的响应合成器对象
callback_manager: 一个可选的回调管理器对象
学习记录:
1.为什么要用optional
?
在 Python 中,
Optional
是typing
模块提供的一种类型提示工具,用于表示某个变量或者参数可以是某种类型,也可以是None
。这在函数参数或类属性可能为空值的情况下非常有用。eg:response_synthesizer
: 可以是BaseSynthesizer
的实例,也可以是None
。
2.transformations作用是什么?默认的default_transformations()
的SentenceSplitter()
是什么?
使用了LlamaIndex的库,
执行转换,将文档转换为节点
from_objs
类方法
@classmethod
def from_objs(
cls,
objs: Optional[list[RAGObject]] = None,
transformations: Optional[list[TransformComponent]] = None,
embed_model: BaseEmbedding = None,
llm: LLM = None,
retriever_configs: list[BaseRetrieverConfig] = None,
ranker_configs: list[BaseRankerConfig] = None,
) -> "SimpleEngine":
"""From objs.
Args:
objs: List of RAGObject.
transformations: Parse documents to nodes. Default [SentenceSplitter].
embed_model: Parse nodes to embedding. Must supported by llama index. Default OpenAIEmbedding.
llm: Must supported by llama index. Default OpenAI.
retriever_configs: Configuration for retrievers. If more than one config, will use SimpleHybridRetriever.
ranker_configs: Configuration for rankers.
"""
objs = objs or []
retriever_configs = retriever_configs or []
if not objs and any(isinstance(config, BM25RetrieverConfig) for config in retriever_configs):
raise ValueError("In BM25RetrieverConfig, Objs must not be empty.")
nodes = [ObjectNode(text=obj.rag_key(), metadata=ObjectNode.get_obj_metadata(obj)) for obj in objs]
#
return cls._from_nodes(
nodes=nodes,
transformations=transformations,
embed_model=embed_model,
llm=llm,
retriever_configs=retriever_configs,
ranker_configs=ranker_configs,
)
if not objs and any(isinstance(config, BM25RetrieverConfig) for config in retriever_configs):
raise ValueError("In BM25RetrieverConfig, Objs must not be empty.")
-
any(isinstance(config, BM25RetrieverConfig) for config in retriever_configs)
是一个生成器表达式,它遍历retriever_configs
列表,并检查其中的每个元素是否是BM25RetrieverConfig
类型。isinstance(config, BM25RetrieverConfig)
用于检查当前元素config
是否是BM25RetrieverConfig
类型。BM25算法:
BM25https://www.elastic.co/cn/blog/practical-bm25-part-2-the-bm25-algorithm-and-its-variables
-
对于
objs
列表中的每个Player
对象,生成一个ObjectNode
对象,并将这些ObjectNode
对象组成一个列表赋值给nodes
。-
ObjectNode的类定义和初始化方法:
class ObjectNode(TextNode): """RAG add object.""" def __init__(self, **kwargs): super().__init__(**kwargs) self.excluded_llm_metadata_keys = list(ObjectNodeMetadata.model_fields.keys()) self.excluded_embed_metadata_keys = self.excluded_llm_metadata_keys
-
ObjectNode
继承自TextNode
类(llama_index.core.schema
),并添加了特定的功能以支持在 RAG 系统中处理对象。 -
self.excluded_llm_metadata_keys
:初始化一个列表,包含ObjectNodeMetadata
的所有字段名。 -
self.excluded_embed_metadata_keys
:将嵌入元数据排除键设置为与excluded_llm_metadata_keys
相同的值。
-
静态方法 get_obj_metadata
@staticmethod
def get_obj_metadata(obj: RAGObject) -> dict:
metadata = ObjectNodeMetadata(
obj_json=obj.model_dump_json(), obj_cls_name=obj.__class__.__name__, obj_mod_name=obj.__class__.__module__
)
return metadata.model_dump()
@staticmethod
:这是一个静态方法,它不依赖于类实例,可以直接通过类名调用。
get_obj_metadata(obj: RAGObject) -> dict
:这个方法接受一个 RAGObject
类型的对象,并返回一个字典类型的元数据。
metadata = ObjectNodeMetadata(...)
:
-
创建一个
ObjectNodeMetadata
实例,并填充以下字段:-
obj_json
:调用对象的model_dump_json
方法,获取对象的 JSON 表示。 -
obj_cls_name
:获取对象的类名。 -
obj_mod_name
:获取对象类所在的模块名。
-
return metadata.model_dump()
:
-
调用
metadata
的model_dump
方法,将ObjectNodeMetadata
实例转换为字典,并返回这个字典。