Spaces:
Runtime error
Runtime error
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
@Time : 2023/4/29 16:07 | |
@Author : alexanderwu | |
@File : common.py | |
@From : https://github.com/geekan/MetaGPT/blob/main/metagpt/utils/common.py | |
""" | |
import ast | |
import inspect | |
import os | |
import re | |
from typing import List, Tuple | |
from autoagents.system.logs import logger | |
def check_cmd_exists(command) -> int: | |
""" 检查命令是否存在 | |
:param command: 待检查的命令 | |
:return: 如果命令存在,返回0,如果不存在,返回非0 | |
""" | |
check_command = 'command -v ' + command + ' >/dev/null 2>&1 || { echo >&2 "no mermaid"; exit 1; }' | |
result = os.system(check_command) | |
return result | |
class OutputParser: | |
def parse_blocks(cls, text: str): | |
# 首先根据"##"将文本分割成不同的block | |
blocks = text.split("##") | |
# 创建一个字典,用于存储每个block的标题和内容 | |
block_dict = {} | |
# 遍历所有的block | |
for block in blocks: | |
# 如果block不为空,则继续处理 | |
if block.strip() != "": | |
# 将block的标题和内容分开,并分别去掉前后的空白字符 | |
block_title, block_content = block.split("\n", 1) | |
# LLM可能出错,在这里做一下修正 | |
if block_title[-1] == ":": | |
block_title = block_title[:-1] | |
block_dict[block_title.strip()] = block_content.strip() | |
return block_dict | |
def parse_code(cls, text: str, lang: str = "") -> str: | |
pattern = rf'```{lang}.*?\s+(.*?)```' | |
match = re.search(pattern, text, re.DOTALL) | |
if match: | |
code = match.group(1) | |
else: | |
raise Exception | |
return code | |
def parse_str(cls, text: str): | |
text = text.split("=")[-1] | |
text = text.strip().strip("'").strip("\"") | |
return text | |
def parse_file_list(cls, text: str) -> list[str]: | |
# Regular expression pattern to find the tasks list. | |
pattern = r'\s*(.*=.*)?(\[.*\])' | |
# Extract tasks list string using regex. | |
match = re.search(pattern, text, re.DOTALL) | |
if match: | |
tasks_list_str = match.group(2) | |
# Convert string representation of list to a Python list using ast.literal_eval. | |
tasks = ast.literal_eval(tasks_list_str) | |
else: | |
tasks = text.split("\n") | |
return tasks | |
def parse_data(cls, data): | |
block_dict = cls.parse_blocks(data) | |
parsed_data = {} | |
for block, content in block_dict.items(): | |
# 尝试去除code标记 | |
try: | |
content = cls.parse_code(text=content) | |
except Exception: | |
pass | |
# 尝试解析list | |
try: | |
content = cls.parse_file_list(text=content) | |
except Exception: | |
pass | |
parsed_data[block] = content | |
return parsed_data | |
def parse_data_with_mapping(cls, data, mapping): | |
block_dict = cls.parse_blocks(data) | |
parsed_data = {} | |
for block, content in block_dict.items(): | |
# 尝试去除code标记 | |
try: | |
content = cls.parse_code(text=content) | |
except Exception: | |
pass | |
typing_define = mapping.get(block, None) | |
if isinstance(typing_define, tuple): | |
typing = typing_define[0] | |
else: | |
typing = typing_define | |
if typing == List[str] or typing == List[Tuple[str, str]]: | |
# 尝试解析list | |
try: | |
content = cls.parse_file_list(text=content) | |
except Exception: | |
pass | |
# TODO: 多余的引号去除有风险,后期再解决 | |
# elif typing == str: | |
# # 尝试去除多余的引号 | |
# try: | |
# content = cls.parse_str(text=content) | |
# except Exception: | |
# pass | |
parsed_data[block] = content | |
return parsed_data | |
class CodeParser: | |
def parse_block(cls, block: str, text: str) -> str: | |
blocks = cls.parse_blocks(text) | |
for k, v in blocks.items(): | |
if block in k: | |
return v | |
return "" | |
def parse_blocks(cls, text: str): | |
# 首先根据"##"将文本分割成不同的block | |
blocks = text.split("##") | |
# 创建一个字典,用于存储每个block的标题和内容 | |
block_dict = {} | |
# 遍历所有的block | |
for block in blocks: | |
# 如果block不为空,则继续处理 | |
if block.strip() != "": | |
# 将block的标题和内容分开,并分别去掉前后的空白字符 | |
block_title, block_content = block.split("\n", 1) | |
block_dict[block_title.strip()] = block_content.strip() | |
return block_dict | |
def parse_code(cls, block: str, text: str, lang: str = "") -> str: | |
if block: | |
text = cls.parse_block(block, text) | |
pattern = rf'```{lang}.*?\s+(.*?)```' | |
match = re.search(pattern, text, re.DOTALL) | |
if match: | |
code = match.group(1) | |
else: | |
logger.error(f"{pattern} not match following text:") | |
logger.error(text) | |
raise Exception | |
return code | |
def parse_str(cls, block: str, text: str, lang: str = ""): | |
code = cls.parse_code(block, text, lang) | |
code = code.split("=")[-1] | |
code = code.strip().strip("'").strip("\"") | |
return code | |
def parse_file_list(cls, block: str, text: str, lang: str = "") -> list[str]: | |
# Regular expression pattern to find the tasks list. | |
code = cls.parse_code(block, text, lang) | |
print(code) | |
pattern = r'\s*(.*=.*)?(\[.*\])' | |
# Extract tasks list string using regex. | |
match = re.search(pattern, code, re.DOTALL) | |
if match: | |
tasks_list_str = match.group(2) | |
# Convert string representation of list to a Python list using ast.literal_eval. | |
tasks = ast.literal_eval(tasks_list_str) | |
else: | |
raise Exception | |
return tasks | |
class NoMoneyException(Exception): | |
"""Raised when the operation cannot be completed due to insufficient funds""" | |
def __init__(self, amount, message="Insufficient funds"): | |
self.amount = amount | |
self.message = message | |
super().__init__(self.message) | |
def __str__(self): | |
return f'{self.message} -> Amount required: {self.amount}' | |
def print_members(module, indent=0): | |
""" | |
https://stackoverflow.com/questions/1796180/how-can-i-get-a-list-of-all-classes-within-current-module-in-python | |
:param module: | |
:param indent: | |
:return: | |
""" | |
prefix = ' ' * indent | |
for name, obj in inspect.getmembers(module): | |
print(name, obj) | |
if inspect.isclass(obj): | |
print(f'{prefix}Class: {name}') | |
# print the methods within the class | |
if name in ['__class__', '__base__']: | |
continue | |
print_members(obj, indent + 2) | |
elif inspect.isfunction(obj): | |
print(f'{prefix}Function: {name}') | |
elif inspect.ismethod(obj): | |
print(f'{prefix}Method: {name}') | |