feat: +unit test

This commit is contained in:
莘权 马 2023-12-26 13:31:50 +08:00
parent 339714261a
commit 6512f40ddd
27 changed files with 333 additions and 151 deletions

View file

@ -6,6 +6,7 @@
@File : text_to_image.py
@Desc : Text-to-Image skill, which provides text-to-image functionality.
"""
import base64
from metagpt.config import CONFIG
from metagpt.const import BASE64_FORMAT
@ -25,11 +26,12 @@ async def text_to_image(text, size_type: str = "512x512", openai_api_key="", mod
"""
image_declaration = "data:image/png;base64,"
if CONFIG.METAGPT_TEXT_TO_IMAGE_MODEL_URL or model_url:
base64_data = await oas3_metagpt_text_to_image(text, size_type, model_url)
binary_data = await oas3_metagpt_text_to_image(text, size_type, model_url)
elif CONFIG.OPENAI_API_KEY or openai_api_key:
base64_data = await oas3_openai_text_to_image(text, size_type)
binary_data = await oas3_openai_text_to_image(text, size_type)
else:
raise ValueError("Missing necessary parameters.")
base64_data = base64.b64encode(binary_data).decode("utf-8")
s3 = S3()
url = await s3.cache(data=base64_data, file_ext=".png", format=BASE64_FORMAT) if s3.is_valid else ""

View file

@ -6,7 +6,6 @@
@File : text_to_speech.py
@Desc : Text-to-Speech skill, which provides text-to-speech functionality
"""
import openai
from metagpt.config import CONFIG
from metagpt.const import BASE64_FORMAT
@ -66,7 +65,6 @@ async def text_to_speech(
return f"[{text}]({url})"
return audio_declaration + base64_data if base64_data else base64_data
raise openai.InvalidRequestError(
message="AZURE_TTS_SUBSCRIPTION_KEY, AZURE_TTS_REGION, IFLYTEK_APP_ID, IFLYTEK_API_KEY, IFLYTEK_API_SECRET error",
param={},
raise ValueError(
"AZURE_TTS_SUBSCRIPTION_KEY, AZURE_TTS_REGION, IFLYTEK_APP_ID, IFLYTEK_API_KEY, IFLYTEK_API_SECRET error"
)

View file

@ -96,9 +96,10 @@ async def oas3_azsure_tts(text, lang="", voice="", style="", role="", subscripti
async with aiofiles.open(filename, mode="rb") as reader:
data = await reader.read()
base64_string = base64.b64encode(data).decode("utf-8")
filename.unlink()
except Exception as e:
logger.error(f"text:{text}, error:{e}")
return ""
finally:
filename.unlink(missing_ok=True)
return base64_string

View file

@ -7,7 +7,7 @@
@Desc : Implement the OpenAPI Specification 3.0 demo and use the following command to test the HTTP service:
curl -X 'POST' \
'http://localhost:8080/openapi/greeting/dave' \
'http://localhost:8082/openapi/greeting/dave' \
-H 'accept: text/plain' \
-H 'Content-Type: application/json' \
-d '{}'
@ -26,4 +26,4 @@ if __name__ == "__main__":
specification_dir = Path(__file__).parent.parent.parent / ".well-known"
app = connexion.AsyncApp(__name__, specification_dir=str(specification_dir))
app.add_api("openapi.yaml", arguments={"title": "Hello World Example"})
app.run(port=8080)
app.run(port=8082)

View file

@ -6,7 +6,6 @@
@File : iflytek_tts.py
@Desc : iFLYTEK TTS OAS3 api, which provides text-to-speech functionality
"""
import asyncio
import base64
import hashlib
import hmac
@ -74,12 +73,13 @@ class IFlyTekTTS(object):
await websocket.send(req)
# receive frames
async with aiofiles.open(str(output_file), "w") as writer:
async with aiofiles.open(str(output_file), "wb") as writer:
while True:
v = await websocket.recv()
rsp = IFlyTekTTSResponse(**json.loads(v))
if rsp.data:
await writer.write(rsp.data.audio)
binary_data = base64.b64decode(rsp.data.audio)
await writer.write(binary_data)
if rsp.data.status != IFlyTekTTSStatus.STATUS_LAST_FRAME.value:
continue
break
@ -140,23 +140,13 @@ async def oas3_iflytek_tts(text: str, voice: str = "", app_id: str = "", api_key
try:
tts = IFlyTekTTS(app_id=app_id, api_key=api_key, api_secret=api_secret)
await tts.synthesize_speech(text=text, output_file=str(filename), voice=voice)
async with aiofiles.open(str(filename), mode="r") as reader:
base64_string = await reader.read()
async with aiofiles.open(str(filename), mode="rb") as reader:
data = await reader.read()
base64_string = base64.b64encode(data).decode("utf-8")
except Exception as e:
logger.error(f"text:{text}, error:{e}")
base64_string = ""
finally:
filename.unlink()
filename.unlink(missing_ok=True)
return base64_string
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(
oas3_iflytek_tts(
text="你好hello",
app_id="f7acef62",
api_key="fda72e3aa286042a492525816a5efa08",
api_secret="ZDk3NjdiMDBkODJlOWQ1NjRjMGI2NDY4",
)
)

View file

@ -6,39 +6,21 @@
@File : metagpt_oas3_api_svc.py
@Desc : MetaGPT OpenAPI Specification 3.0 REST API service
"""
import asyncio
import sys
from pathlib import Path
import connexion
sys.path.append(str(Path(__file__).resolve().parent.parent.parent)) # fix-bug: No module named 'metagpt'
def oas_http_svc():
"""Start the OAS 3.0 OpenAPI HTTP service"""
app = connexion.AioHttpApp(__name__, specification_dir="../../.well-known/")
print("http://localhost:8080/oas3/ui/")
specification_dir = Path(__file__).parent.parent.parent / ".well-known"
app = connexion.AsyncApp(__name__, specification_dir=str(specification_dir))
app.add_api("metagpt_oas3_api.yaml")
app.add_api("openapi.yaml")
app.run(port=8080)
async def async_main():
"""Start the OAS 3.0 OpenAPI HTTP service in the background."""
loop = asyncio.get_event_loop()
loop.run_in_executor(None, oas_http_svc)
# TODO: replace following codes:
while True:
await asyncio.sleep(1)
print("sleep")
def main():
print("http://localhost:8080/oas3/ui/")
oas_http_svc()
if __name__ == "__main__":
# asyncio.run(async_main())
main()
oas_http_svc()

View file

@ -6,7 +6,6 @@
@File : metagpt_text_to_image.py
@Desc : MetaGPT Text-to-Image OAS3 api, which provides text-to-image functionality.
"""
import asyncio
import base64
from typing import Dict, List
@ -14,7 +13,7 @@ import aiohttp
import requests
from pydantic import BaseModel
from metagpt.config import CONFIG, Config
from metagpt.config import CONFIG
from metagpt.logs import logger
@ -75,11 +74,12 @@ class MetaGPTText2Image:
async with session.post(self.model_url, headers=headers, json=data) as response:
result = ImageResult(**await response.json())
if len(result.images) == 0:
return ""
return result.images[0]
return 0
data = base64.b64decode(result.images[0])
return data
except requests.exceptions.RequestException as e:
logger.error(f"An error occurred:{e}")
return ""
return 0
# Export
@ -96,15 +96,3 @@ async def oas3_metagpt_text_to_image(text, size_type: str = "512x512", model_url
if not model_url:
model_url = CONFIG.METAGPT_TEXT_TO_IMAGE_MODEL_URL
return await MetaGPTText2Image(model_url).text_2_image(text, size_type=size_type)
if __name__ == "__main__":
Config()
loop = asyncio.new_event_loop()
task = loop.create_task(oas3_metagpt_text_to_image("Panda emoji"))
v = loop.run_until_complete(task)
print(v)
data = base64.b64decode(v)
with open("tmp.png", mode="wb") as writer:
writer.write(data)
print(v)

View file

@ -5,7 +5,6 @@
@Author : zhanglei
@File : moderation.py
"""
import asyncio
from typing import Union
from metagpt.llm import LLM
@ -15,6 +14,38 @@ class Moderation:
def __init__(self):
self.llm = LLM()
def handle_moderation_results(self, results):
resp = []
for item in results:
categories = item.categories.dict()
true_categories = [category for category, item_flagged in categories.items() if item_flagged]
resp.append({"flagged": item.flagged, "true_categories": true_categories})
return resp
def moderation_with_categories(self, content: Union[str, list[str]]):
resp = []
if content:
moderation_results = self.llm.moderation(content=content)
resp = self.handle_moderation_results(moderation_results.results)
return resp
async def amoderation_with_categories(self, content: Union[str, list[str]]):
resp = []
if content:
moderation_results = await self.llm.amoderation(content=content)
resp = self.handle_moderation_results(moderation_results.results)
return resp
def moderation(self, content: Union[str, list[str]]):
resp = []
if content:
moderation_results = self.llm.moderation(content=content)
results = moderation_results.results
for item in results:
resp.append(item.flagged)
return resp
async def amoderation(self, content: Union[str, list[str]]):
resp = []
if content:
@ -24,15 +55,3 @@ class Moderation:
resp.append(item.flagged)
return resp
async def main():
moderation = Moderation()
rsp = await moderation.amoderation(
content=["I will kill you", "The weather is really nice today", "I want to hit you"]
)
print(rsp)
if __name__ == "__main__":
asyncio.run(main())

View file

@ -7,14 +7,13 @@
@Desc : OpenAI Text-to-Embedding OAS3 api, which provides text-to-embedding functionality.
For more details, checkout: `https://platform.openai.com/docs/api-reference/embeddings/object`
"""
import asyncio
from typing import List
import aiohttp
import requests
from pydantic import BaseModel
from pydantic import BaseModel, Field
from metagpt.config import CONFIG, Config
from metagpt.config import CONFIG
from metagpt.logs import logger
@ -29,15 +28,18 @@ class Embedding(BaseModel):
class Usage(BaseModel):
prompt_tokens: int
total_tokens: int
prompt_tokens: int = 0
total_tokens: int = 0
class ResultEmbedding(BaseModel):
object: str
data: List[Embedding]
model: str
usage: Usage
class Config:
alias = {"object_": "object"}
object_: str = ""
data: List[Embedding] = []
model: str = ""
usage: Usage = Field(default_factory=Usage)
class OpenAIText2Embedding:
@ -45,7 +47,7 @@ class OpenAIText2Embedding:
"""
:param openai_api_key: OpenAI API key, For more details, checkout: `https://platform.openai.com/account/api-keys`
"""
self.openai_api_key = openai_api_key if openai_api_key else CONFIG.OPENAI_API_KEY
self.openai_api_key = openai_api_key or CONFIG.OPENAI_API_KEY
async def text_2_embedding(self, text, model="text-embedding-ada-002"):
"""Text to embedding
@ -55,15 +57,18 @@ class OpenAIText2Embedding:
:return: A json object of :class:`ResultEmbedding` class if successful, otherwise `{}`.
"""
proxies = {"proxy": CONFIG.openai_proxy} if CONFIG.openai_proxy else {}
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {self.openai_api_key}"}
data = {"input": text, "model": model}
url = "https://api.openai.com/v1/embeddings"
try:
async with aiohttp.ClientSession() as session:
async with session.post("https://api.openai.com/v1/embeddings", headers=headers, json=data) as response:
return await response.json()
async with session.post(url, headers=headers, json=data, **proxies) as response:
data = await response.json()
return ResultEmbedding(**data)
except requests.exceptions.RequestException as e:
logger.error(f"An error occurred:{e}")
return {}
return ResultEmbedding()
# Export
@ -80,11 +85,3 @@ async def oas3_openai_text_to_embedding(text, model="text-embedding-ada-002", op
if not openai_api_key:
openai_api_key = CONFIG.OPENAI_API_KEY
return await OpenAIText2Embedding(openai_api_key).text_2_embedding(text, model=model)
if __name__ == "__main__":
Config()
loop = asyncio.new_event_loop()
task = loop.create_task(oas3_openai_text_to_embedding("Panda emoji"))
v = loop.run_until_complete(task)
print(v)

View file

@ -6,13 +6,10 @@
@File : openai_text_to_image.py
@Desc : OpenAI Text-to-Image OAS3 api, which provides text-to-image functionality.
"""
import asyncio
import base64
import aiohttp
import requests
from metagpt.config import Config
from metagpt.llm import LLM
from metagpt.logs import logger
@ -23,7 +20,6 @@ class OpenAIText2Image:
:param openai_api_key: OpenAI API key, For more details, checkout: `https://platform.openai.com/account/api-keys`
"""
self._llm = LLM()
self._client = self._llm.async_client
def __del__(self):
if self._llm:
@ -37,7 +33,7 @@ class OpenAIText2Image:
:return: The image data is returned in Base64 encoding.
"""
try:
result = await self._client.images.generate(prompt=text, n=1, size=size_type)
result = await self._llm.async_client.images.generate(prompt=text, n=1, size=size_type)
except Exception as e:
logger.error(f"An error occurred:{e}")
return ""
@ -57,12 +53,11 @@ class OpenAIText2Image:
async with session.get(url) as response:
response.raise_for_status() # 如果是 4xx 或 5xx 响应,会引发异常
image_data = await response.read()
base64_image = base64.b64encode(image_data).decode("utf-8")
return base64_image
return image_data
except requests.exceptions.RequestException as e:
logger.error(f"An error occurred:{e}")
return ""
return 0
# Export
@ -76,11 +71,3 @@ async def oas3_openai_text_to_image(text, size_type: str = "1024x1024"):
if not text:
return ""
return await OpenAIText2Image().text_2_image(text, size_type=size_type)
if __name__ == "__main__":
Config()
loop = asyncio.new_event_loop()
task = loop.create_task(oas3_openai_text_to_image("Panda emoji"))
v = loop.run_until_complete(task)
print(v)

View file

@ -9,7 +9,7 @@ import asyncio
import importlib
from concurrent import futures
from copy import deepcopy
from typing import Dict, Literal
from typing import Literal
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
@ -33,7 +33,6 @@ class SeleniumWrapper:
def __init__(
self,
options: Dict,
browser_type: Literal["chrome", "firefox", "edge", "ie"] | None = None,
launch_kwargs: dict | None = None,
*,