refine code. move azure tts to tool, refactor actions

This commit is contained in:
geekan 2023-12-19 23:53:04 +08:00
parent 33c58d97fe
commit 62f34db137
9 changed files with 32 additions and 106 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

@ -13,7 +13,7 @@ from typing import Optional
from metagpt.actions.action_node import ActionNode
from metagpt.llm import LLM
from metagpt.schema import BaseContext
from metagpt.schema import CodingContext, CodeSummarizeContext, TestingContext, RunCodeContext
class Action(ABC):
@ -21,7 +21,8 @@ class Action(ABC):
name: str
llm: LLM
context: dict | BaseContext | str | None
# FIXME: simplify context
context: dict | CodingContext | CodeSummarizeContext | TestingContext | RunCodeContext | str | None
prefix: str
desc: str
node: ActionNode | None

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

@ -18,6 +18,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
@ -265,7 +266,7 @@ class MessageQueue:
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,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