refine code. move azure tts to tool, refactor actions

This commit is contained in:
geekan 2023-12-19 23:53:04 +08:00 committed by better629
parent a06acbbbe8
commit 4d78dbce40
10 changed files with 32 additions and 108 deletions

View file

@ -13,7 +13,6 @@ from metagpt.actions.add_requirement import UserRequirement
from metagpt.actions.debug_error import DebugError
from metagpt.actions.design_api import WriteDesign
from metagpt.actions.design_api_review import DesignReview
from metagpt.actions.design_filenames import DesignFilenames
from metagpt.actions.project_management import AssignTasks, WriteTasks
from metagpt.actions.research import CollectLinks, WebBrowseAndSummarize, ConductResearch
from metagpt.actions.run_code import RunCode
@ -33,7 +32,6 @@ class ActionType(Enum):
WRITE_PRD_REVIEW = WritePRDReview
WRITE_DESIGN = WriteDesign
DESIGN_REVIEW = DesignReview
DESIGN_FILENAMES = DesignFilenames
WRTIE_CODE = WriteCode
WRITE_CODE_REVIEW = WriteCodeReview
WRITE_TEST = WriteTest

View file

@ -14,6 +14,7 @@ from pydantic import BaseModel, Field
from metagpt.actions.action_node import ActionNode
from metagpt.llm import LLM
from metagpt.provider.base_gpt_api import BaseGPTAPI
from metagpt.schema import CodingContext, CodeSummarizeContext, TestingContext, RunCodeContext
action_subclass_registry = {}
@ -22,7 +23,7 @@ action_subclass_registry = {}
class Action(BaseModel):
name: str = ""
llm: BaseGPTAPI = Field(default_factory=LLM, exclude=True)
context = ""
context: dict | CodingContext | CodeSummarizeContext | TestingContext | RunCodeContext | str | None = ""
prefix = "" # aask*时会加上prefix作为system_message
desc = "" # for skill manager
node: ActionNode = Field(default_factory=ActionNode, exclude=True)

View file

@ -1,37 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/5/19 12:01
@Author : alexanderwu
@File : analyze_dep_libs.py
"""
from metagpt.actions import Action
PROMPT = """You are an AI developer, trying to write a program that generates code for users based on their intentions.
For the user's prompt:
---
The API is: {prompt}
---
We decide the generated files are: {filepaths_string}
Now that we have a file list, we need to understand the shared dependencies they have.
Please list and briefly describe the shared contents between the files we are generating, including exported variables,
data patterns, id names of all DOM elements that javascript functions will use, message names and function names.
Focus only on the names of shared dependencies, do not add any other explanations.
"""
class AnalyzeDepLibs(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
self.desc = "Analyze the runtime dependencies of the program based on the context"
async def run(self, requirement, filepaths_string):
# prompt = f"Below is the product requirement document (PRD):\n\n{prd}\n\n{PROMPT}"
prompt = PROMPT.format(prompt=requirement, filepaths_string=filepaths_string)
design_filenames = await self._aask(prompt)
return design_filenames

View file

@ -1,30 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/5/19 11:50
@Author : alexanderwu
@File : design_filenames.py
"""
from metagpt.actions import Action
from metagpt.logs import logger
PROMPT = """You are an AI developer, trying to write a program that generates code for users based on their intentions.
When given their intentions, provide a complete and exhaustive list of file paths needed to write the program for the user.
Only list the file paths you will write and return them as a Python string list.
Do not add any other explanations, just return a Python string list."""
class DesignFilenames(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
self.desc = (
"Based on the PRD, consider system design, and carry out the basic design of the corresponding "
"APIs, data structures, and database tables. Please give your design, feedback clearly and in detail."
)
async def run(self, prd):
prompt = f"The following is the Product Requirement Document (PRD):\n\n{prd}\n\n{PROMPT}"
design_filenames = await self._aask(prompt)
logger.debug(prompt)
logger.debug(design_filenames)
return design_filenames

View file

@ -3,19 +3,11 @@
"""
@Time : 2023/9/12 17:45
@Author : fisherdeng
@File : detail_mining.py
@File : generate_questions.py
"""
from metagpt.actions import Action
from metagpt.actions.action_node import ActionNode
CONTEXT_TEMPLATE = """
## TOPIC
{topic}
## RECORD
{record}
"""
QUESTIONS = ActionNode(
key="Questions",
expected_type=list[str],
@ -25,11 +17,9 @@ QUESTIONS = ActionNode(
)
class DetailMining(Action):
class GenerateQuestions(Action):
"""This class allows LLM to further mine noteworthy details based on specific "##TOPIC"(discussion topic) and
"##RECORD" (discussion records), thereby deepening the discussion."""
async def run(self, topic, record):
context = CONTEXT_TEMPLATE.format(topic=topic, record=record)
rsp = await QUESTIONS.fill(context=context, llm=self.llm)
return rsp
async def run(self, context):
return await QUESTIONS.fill(context=context, llm=self.llm)

View file

@ -19,6 +19,7 @@ import asyncio
import json
import os.path
import uuid
from abc import ABC
from asyncio import Queue, QueueEmpty, wait_for
from json import JSONDecodeError
from pathlib import Path
@ -281,7 +282,7 @@ class MessageQueue(BaseModel):
T = TypeVar("T", bound="BaseModel")
class BaseContext(BaseModel):
class BaseContext(BaseModel, ABC):
@classmethod
@handle_exception
def loads(cls: Type[T], val: str) -> Optional[T]:

View file

@ -7,19 +7,16 @@
"""
from azure.cognitiveservices.speech import AudioConfig, SpeechConfig, SpeechSynthesizer
from metagpt.actions.action import Action
from metagpt.config import Config
from metagpt.config import CONFIG
class AzureTTS(Action):
def __init__(self, name, context=None, llm=None):
super().__init__(name, context, llm)
self.config = Config()
class AzureTTS:
"""https://learn.microsoft.com/zh-cn/azure/cognitive-services/speech-service/language-support?tabs=tts#voice-styles-and-roles"""
# Parameters reference: https://learn.microsoft.com/zh-cn/azure/cognitive-services/speech-service/language-support?tabs=tts#voice-styles-and-roles
def synthesize_speech(self, lang, voice, role, text, output_file):
subscription_key = self.config.get("AZURE_TTS_SUBSCRIPTION_KEY")
region = self.config.get("AZURE_TTS_REGION")
@classmethod
def synthesize_speech(cls, lang, voice, role, text, output_file):
subscription_key = CONFIG.get("AZURE_TTS_SUBSCRIPTION_KEY")
region = CONFIG.get("AZURE_TTS_REGION")
speech_config = SpeechConfig(subscription=subscription_key, region=region)
speech_config.speech_synthesis_voice_name = voice
@ -41,5 +38,5 @@ class AzureTTS(Action):
if __name__ == "__main__":
azure_tts = AzureTTS("azure_tts")
azure_tts = AzureTTS()
azure_tts.synthesize_speech("zh-CN", "zh-CN-YunxiNeural", "Boy", "Hello, I am Kaka", "output.wav")

View file

@ -5,12 +5,10 @@
import copy
import pickle
<<<<<<< HEAD
from metagpt.utils.common import import_class
=======
from metagpt.actions.action_node import ActionNode
from metagpt.schema import Message
>>>>>>> 09e2f05 (refactor action_output and action_node)
def actionoutout_schema_to_mapping(schema: dict) -> dict:

View file

@ -5,11 +5,11 @@
@Author : alexanderwu
@File : test_azure_tts.py
"""
from metagpt.actions.azure_tts import AzureTTS
from metagpt.tools.azure_tts import AzureTTS
def test_azure_tts():
azure_tts = AzureTTS("azure_tts")
azure_tts = AzureTTS()
azure_tts.synthesize_speech("zh-CN", "zh-CN-YunxiNeural", "Boy", "你好,我是卡卡", "output.wav")
# 运行需要先配置 SUBSCRIPTION_KEY

View file

@ -3,20 +3,26 @@
"""
@Time : 2023/9/13 00:26
@Author : fisherdeng
@File : test_detail_mining.py
@File : test_generate_questions.py
"""
import pytest
from metagpt.actions.detail_mining import DetailMining
from metagpt.actions.generate_questions import GenerateQuestions
from metagpt.logs import logger
context = """
## topic
如何做一个生日蛋糕
## record
我认为应该先准备好材料然后再开始做蛋糕
"""
@pytest.mark.asyncio
async def test_detail_mining():
topic = "如何做一个生日蛋糕"
record = "我认为应该先准备好材料,然后再开始做蛋糕。"
detail_mining = DetailMining("detail_mining")
rsp = await detail_mining.run(topic=topic, record=record)
async def test_generate_questions():
detail_mining = GenerateQuestions()
rsp = await detail_mining.run(context)
logger.info(f"{rsp.content=}")
assert "Questions" in rsp.content