Merge pull request #1431 from iorisa/fixbug/1430

fixbug: #1430 DO NOT FORCE VALIDATE '{'Required Python packages'}' by default
This commit is contained in:
Guess 2024-08-07 14:01:47 +08:00 committed by GitHub
commit 833321c7ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 45 additions and 13 deletions

View file

@ -237,12 +237,19 @@ class ActionNode:
"""基于pydantic v2的模型动态生成用来检验结果类型正确性"""
def check_fields(cls, values):
required_fields = set(mapping.keys())
all_fields = set(mapping.keys())
required_fields = set()
for k, v in mapping.items():
type_v, field_info = v
if ActionNode.is_optional_type(type_v):
continue
required_fields.add(k)
missing_fields = required_fields - set(values.keys())
if missing_fields:
raise ValueError(f"Missing fields: {missing_fields}")
unrecognized_fields = set(values.keys()) - required_fields
unrecognized_fields = set(values.keys()) - all_fields
if unrecognized_fields:
logger.warning(f"Unrecognized fields: {unrecognized_fields}")
return values
@ -717,3 +724,12 @@ class ActionNode:
root_node.add_child(child_node)
return root_node
@staticmethod
def is_optional_type(tp) -> bool:
"""Return True if `tp` is `typing.Optional[...]`"""
if typing.get_origin(tp) is Union:
args = typing.get_args(tp)
non_none_types = [arg for arg in args if arg is not type(None)]
return len(non_none_types) == 1 and len(args) == 2
return False

View file

@ -5,7 +5,7 @@
@Author : alexanderwu
@File : design_api_an.py
"""
from typing import List,Optional
from typing import List, Optional
from metagpt.actions.action_node import ActionNode
from metagpt.utils.mermaid import MMC1, MMC2
@ -45,7 +45,7 @@ REFINED_FILE_LIST = ActionNode(
example=["main.py", "game.py", "new_feature.py"],
)
#optional,because low success reproduction of class diagram in non py project.
# optional,because low success reproduction of class diagram in non py project.
DATA_STRUCTURES_AND_INTERFACES = ActionNode(
key="Data structures and interfaces",
expected_type=Optional[str],

View file

@ -12,7 +12,7 @@ from metagpt.actions.action_node import ActionNode
REQUIRED_PACKAGES = ActionNode(
key="Required packages",
expected_type=Optional[List[str]],
instruction="Provide required packages in requirements.txt format.",
instruction="Provide required third-party packages in requirements.txt format.",
example=["flask==1.1.2", "bcrypt==3.2.0"],
)

View file

@ -139,7 +139,7 @@ Language: Please use the same language as the user requirement, but the title an
end", "Anything UNCLEAR": "目前项目要求明确没有不清楚的地方"}
## Tasks
{"Required packages": ["无需Python"], "Required Other language third-party packages": ["vue.js"], "Logic Analysis": [["index.html", "作为游戏的入口文件和主要的HTML结构"], ["styles.css", "包含所有的CSS样式确保游戏界面美观"], ["main.js", "包含Main类负责初始化游戏和绑定事件"], ["game.js", "包含Game类负责游戏逻辑如开始游戏、移动方块等"], ["storage.js", "包含Storage类用于获取和设置玩家的最高分"]], "Task list": ["index.html", "styles.css", "storage.js", "game.js", "main.js"], "Full API spec": "", "Shared Knowledge": "\'game.js\' 包含游戏逻辑相关的函数,被 \'main.js\' 调用。", "Anything UNCLEAR": "目前项目要求明确,没有不清楚的地方。"}
{"Required packages": ["无需第三方"], "Required Other language third-party packages": ["vue.js"], "Logic Analysis": [["index.html", "作为游戏的入口文件和主要的HTML结构"], ["styles.css", "包含所有的CSS样式确保游戏界面美观"], ["main.js", "包含Main类负责初始化游戏和绑定事件"], ["game.js", "包含Game类负责游戏逻辑如开始游戏、移动方块等"], ["storage.js", "包含Storage类用于获取和设置玩家的最高分"]], "Task list": ["index.html", "styles.css", "storage.js", "game.js", "main.js"], "Full API spec": "", "Shared Knowledge": "\'game.js\' 包含游戏逻辑相关的函数,被 \'main.js\' 调用。", "Anything UNCLEAR": "目前项目要求明确,没有不清楚的地方。"}
## Code Files
----- index.html

View file

@ -71,6 +71,9 @@ imap_tools==1.5.0 # Used by metagpt/tools/libs/email_login.py
qianfan~=0.3.16
dashscope~=1.19.3
rank-bm25==0.2.2 # for tool recommendation
jieba==0.42.1 # for tool recommendation
# llama-index-vector-stores-elasticsearch~=0.2.5 # Used by `metagpt/memory/longterm_memory.py`
# llama-index-vector-stores-chroma~=0.1.10 # Used by `metagpt/memory/longterm_memory.py`
gymnasium==0.29.1
boto3~=1.34.69
spark_ai_python~=0.3.30

View file

@ -6,7 +6,7 @@
@File : test_action_node.py
"""
from pathlib import Path
from typing import List, Tuple
from typing import List, Optional, Tuple
import pytest
from pydantic import BaseModel, Field, ValidationError
@ -302,6 +302,19 @@ def test_action_node_from_pydantic_and_print_everything():
assert "tasks" in code, "tasks should be in code"
def test_optional():
mapping = {
"Logic Analysis": (Optional[List[Tuple[str, str]]], Field(default=None)),
"Task list": (Optional[List[str]], None),
"Plan": (Optional[str], ""),
"Anything UNCLEAR": (Optional[str], None),
}
m = {"Anything UNCLEAR": "a"}
t = ActionNode.create_model_class("test_class_1", mapping)
t1 = t(**m)
assert t1
if __name__ == "__main__":
test_create_model_class()
test_create_model_class_with_mapping()
pytest.main([__file__, "-s"])

View file

@ -14,8 +14,8 @@ from tests.metagpt.provider.mock_llm_config import mock_llm_config
def test_config_1():
cfg = Config.default()
llm = cfg.get_openai_llm()
assert llm is not None
assert llm.api_type == LLMType.OPENAI
if cfg.llm.api_type == LLMType.OPENAI:
assert llm is not None
def test_config_from_dict():

View file

@ -53,8 +53,8 @@ def test_context_1():
def test_context_2():
ctx = Context()
llm = ctx.config.get_openai_llm()
assert llm is not None
assert llm.api_type == LLMType.OPENAI
if ctx.config.llm.api_type == LLMType.OPENAI:
assert llm is not None
kwargs = ctx.kwargs
assert kwargs is not None