mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-23 15:48:11 +02:00
Merge branch 'main' into feature/json_write_prd
This commit is contained in:
commit
7b34c433cd
69 changed files with 1911 additions and 56 deletions
65
metagpt/actions/clone_function.py
Normal file
65
metagpt/actions/clone_function.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
from pathlib import Path
|
||||
import traceback
|
||||
|
||||
from metagpt.actions.write_code import WriteCode
|
||||
from metagpt.logs import logger
|
||||
from metagpt.schema import Message
|
||||
from metagpt.utils.highlight import highlight
|
||||
|
||||
CLONE_PROMPT = """
|
||||
*context*
|
||||
Please convert the function code ```{source_code}``` into the the function format: ```{template_func}```.
|
||||
*Please Write code based on the following list and context*
|
||||
1. Write code start with ```, and end with ```.
|
||||
2. Please implement it in one function if possible, except for import statements. for exmaple:
|
||||
```python
|
||||
import pandas as pd
|
||||
def run(*args) -> pd.DataFrame:
|
||||
...
|
||||
```
|
||||
3. Do not use public member functions that do not exist in your design.
|
||||
4. The output function name, input parameters and return value must be the same as ```{template_func}```.
|
||||
5. Make sure the results before and after the code conversion are required to be exactly the same.
|
||||
6. Don't repeat my context in your replies.
|
||||
7. Return full results, for example, if the return value has df.head(), please return df.
|
||||
8. If you must use a third-party package, use the most popular ones, for example: pandas, numpy, ta, ...
|
||||
"""
|
||||
|
||||
|
||||
class CloneFunction(WriteCode):
|
||||
def __init__(self, name="CloneFunction", context: list[Message] = None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
def _save(self, code_path, code):
|
||||
if isinstance(code_path, str):
|
||||
code_path = Path(code_path)
|
||||
code_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
code_path.write_text(code)
|
||||
logger.info(f"Saving Code to {code_path}")
|
||||
|
||||
async def run(self, template_func: str, source_code: str) -> str:
|
||||
"""将source_code转换成template_func一样的入参和返回类型"""
|
||||
prompt = CLONE_PROMPT.format(source_code=source_code, template_func=template_func)
|
||||
logger.info(f"query for CloneFunction: \n {prompt}")
|
||||
code = await self.write_code(prompt)
|
||||
logger.info(f'CloneFunction code is \n {highlight(code)}')
|
||||
return code
|
||||
|
||||
|
||||
def run_function_code(func_code: str, func_name: str, *args, **kwargs):
|
||||
"""Run function code from string code."""
|
||||
try:
|
||||
locals_ = {}
|
||||
exec(func_code, locals_)
|
||||
func = locals_[func_name]
|
||||
return func(*args, **kwargs), ""
|
||||
except Exception:
|
||||
return "", traceback.format_exc()
|
||||
|
||||
|
||||
def run_function_script(code_script_path: str, func_name: str, *args, **kwargs):
|
||||
"""Run function code from script."""
|
||||
if isinstance(code_script_path, str):
|
||||
code_path = Path(code_script_path)
|
||||
code = code_path.read_text(encoding='utf-8')
|
||||
return run_function_code(code, func_name, *args, **kwargs)
|
||||
17
metagpt/actions/execute_task.py
Normal file
17
metagpt/actions/execute_task.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/9/13 12:26
|
||||
@Author : femto Zheng
|
||||
@File : execute_task.py
|
||||
"""
|
||||
from metagpt.actions import Action
|
||||
from metagpt.schema import Message
|
||||
|
||||
|
||||
class ExecuteTask(Action):
|
||||
def __init__(self, name="ExecuteTask", context: list[Message] = None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
pass
|
||||
41
metagpt/actions/prepare_interview.py
Normal file
41
metagpt/actions/prepare_interview.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/9/19 15:02
|
||||
@Author : DevXiaolan
|
||||
@File : prepare_interview.py
|
||||
"""
|
||||
from metagpt.actions import Action
|
||||
|
||||
PROMPT_TEMPLATE = """
|
||||
# Context
|
||||
{context}
|
||||
|
||||
## Format example
|
||||
---
|
||||
Q1: question 1 here
|
||||
References:
|
||||
- point 1
|
||||
- point 2
|
||||
|
||||
Q2: question 2 here...
|
||||
---
|
||||
|
||||
-----
|
||||
Role: You are an interviewer of our company who is well-knonwn in frontend or backend develop;
|
||||
Requirement: Provide a list of questions for the interviewer to ask the interviewee, by reading the resume of the interviewee in the context.
|
||||
Attention: Provide as markdown block as the format above, at least 10 questions.
|
||||
"""
|
||||
|
||||
# prepare for a interview
|
||||
|
||||
|
||||
class PrepareInterview(Action):
|
||||
def __init__(self, name, context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
async def run(self, context):
|
||||
prompt = PROMPT_TEMPLATE.format(context=context)
|
||||
question_list = await self._aask_v1(prompt)
|
||||
return question_list
|
||||
|
||||
|
|
@ -13,6 +13,7 @@ from metagpt.config import CONFIG
|
|||
from metagpt.logs import logger
|
||||
from metagpt.tools.search_engine import SearchEngine
|
||||
from metagpt.tools.web_browser_engine import WebBrowserEngine, WebBrowserEngineType
|
||||
from metagpt.utils.common import OutputParser
|
||||
from metagpt.utils.text import generate_prompt_chunk, reduce_message_length
|
||||
|
||||
LANG_PROMPT = "Please respond in {language}."
|
||||
|
|
@ -110,7 +111,7 @@ class CollectLinks(Action):
|
|||
system_text = system_text if system_text else RESEARCH_TOPIC_SYSTEM.format(topic=topic)
|
||||
keywords = await self._aask(SEARCH_TOPIC_PROMPT, [system_text])
|
||||
try:
|
||||
keywords = json.loads(keywords)
|
||||
keywords = OutputParser.extract_struct(keywords, list)
|
||||
keywords = parse_obj_as(list[str], keywords)
|
||||
except Exception as e:
|
||||
logger.exception(f"fail to get keywords related to the research topic \"{topic}\" for {e}")
|
||||
|
|
@ -130,7 +131,7 @@ class CollectLinks(Action):
|
|||
logger.debug(prompt)
|
||||
queries = await self._aask(prompt, [system_text])
|
||||
try:
|
||||
queries = json.loads(queries)
|
||||
queries = OutputParser.extract_struct(queries, list)
|
||||
queries = parse_obj_as(list[str], queries)
|
||||
except Exception as e:
|
||||
logger.exception(f"fail to break down the research question due to {e}")
|
||||
|
|
@ -158,7 +159,7 @@ class CollectLinks(Action):
|
|||
logger.debug(prompt)
|
||||
indices = await self._aask(prompt)
|
||||
try:
|
||||
indices = json.loads(indices)
|
||||
indices = OutputParser.extract_struct(indices, list)
|
||||
assert all(isinstance(i, int) for i in indices)
|
||||
except Exception as e:
|
||||
logger.exception(f"fail to rank results for {e}")
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
@File : tutorial_assistant.py
|
||||
@Describe : Actions of the tutorial assistant, including writing directories and document content.
|
||||
"""
|
||||
import json
|
||||
|
||||
from typing import Dict
|
||||
|
||||
from metagpt.actions import Action
|
||||
from metagpt.logs import logger
|
||||
from metagpt.prompts.tutorial_assistant import DIRECTORY_PROMPT, CONTENT_PROMPT
|
||||
from metagpt.utils.common import OutputParser
|
||||
|
||||
|
||||
class WriteDirectory(Action):
|
||||
|
|
@ -26,33 +26,6 @@ class WriteDirectory(Action):
|
|||
super().__init__(name, *args, **kwargs)
|
||||
self.language = language
|
||||
|
||||
@staticmethod
|
||||
async def _handle_resp(resp: str) -> Dict:
|
||||
"""Process string results and convert them to JSON format.
|
||||
|
||||
Args:
|
||||
resp: The directory results returned by gpt.
|
||||
|
||||
Returns:
|
||||
The parsed dictionary, such as {"title": "xxx", "directory": [{"dir 1": ["sub dir 1", "sub dir 2"]}]}.
|
||||
|
||||
Raises:
|
||||
Exception: If no matching dictionary section is found.
|
||||
json.JSONDecodeError: If the dictionary part cannot be parsed as JSON.
|
||||
"""
|
||||
start = resp.find('{')
|
||||
end = resp.rfind('}')
|
||||
if start != -1 and end != -1 and end > start:
|
||||
directory_str = resp[start:end + 1]
|
||||
logger.info(f"Successfully parsed json: {str(directory_str)}")
|
||||
try:
|
||||
return json.loads(directory_str)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"Json parsing error: {e}")
|
||||
raise e
|
||||
else:
|
||||
raise Exception("No matching dictionary section found.")
|
||||
|
||||
async def run(self, topic: str, *args, **kwargs) -> Dict:
|
||||
"""Execute the action to generate a tutorial directory according to the topic.
|
||||
|
||||
|
|
@ -64,7 +37,7 @@ class WriteDirectory(Action):
|
|||
"""
|
||||
prompt = DIRECTORY_PROMPT.format(topic=topic, language=self.language)
|
||||
resp = await self._aask(prompt=prompt)
|
||||
return await self._handle_resp(resp)
|
||||
return OutputParser.extract_struct(resp, dict)
|
||||
|
||||
|
||||
class WriteContent(Action):
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ def get_project_root():
|
|||
"""Search upwards to find the project root directory."""
|
||||
current_path = Path.cwd()
|
||||
while True:
|
||||
if (current_path / '.git').exists() or \
|
||||
(current_path / '.project_root').exists() or \
|
||||
(current_path / '.gitignore').exists():
|
||||
if (
|
||||
(current_path / ".git").exists()
|
||||
or (current_path / ".project_root").exists()
|
||||
or (current_path / ".gitignore").exists()
|
||||
):
|
||||
return current_path
|
||||
parent_path = current_path.parent
|
||||
if parent_path == current_path:
|
||||
|
|
@ -23,16 +25,18 @@ def get_project_root():
|
|||
|
||||
|
||||
PROJECT_ROOT = get_project_root()
|
||||
DATA_PATH = PROJECT_ROOT / 'data'
|
||||
WORKSPACE_ROOT = PROJECT_ROOT / 'workspace'
|
||||
PROMPT_PATH = PROJECT_ROOT / 'metagpt/prompts'
|
||||
UT_PATH = PROJECT_ROOT / 'data/ut'
|
||||
DATA_PATH = PROJECT_ROOT / "data"
|
||||
WORKSPACE_ROOT = PROJECT_ROOT / "workspace"
|
||||
PROMPT_PATH = PROJECT_ROOT / "metagpt/prompts"
|
||||
UT_PATH = PROJECT_ROOT / "data/ut"
|
||||
SWAGGER_PATH = UT_PATH / "files/api/"
|
||||
UT_PY_PATH = UT_PATH / "files/ut/"
|
||||
API_QUESTIONS_PATH = UT_PATH / "files/question/"
|
||||
YAPI_URL = "http://yapi.deepwisdomai.com/"
|
||||
TMP = PROJECT_ROOT / 'tmp'
|
||||
TMP = PROJECT_ROOT / "tmp"
|
||||
RESEARCH_PATH = DATA_PATH / "research"
|
||||
TUTORIAL_PATH = DATA_PATH / "tutorial_docx"
|
||||
|
||||
SKILL_DIRECTORY = PROJECT_ROOT / "metagpt/skills"
|
||||
|
||||
MEM_TTL = 24 * 30 * 3600
|
||||
|
|
|
|||
76
metagpt/roles/sk_agent.py
Normal file
76
metagpt/roles/sk_agent.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/9/13 12:23
|
||||
@Author : femto Zheng
|
||||
@File : sk_agent.py
|
||||
"""
|
||||
from semantic_kernel.planning import SequentialPlanner
|
||||
from semantic_kernel.planning.action_planner.action_planner import ActionPlanner
|
||||
from semantic_kernel.planning.basic_planner import BasicPlanner
|
||||
|
||||
from metagpt.actions import BossRequirement
|
||||
from metagpt.actions.execute_task import ExecuteTask
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles import Role
|
||||
from metagpt.schema import Message
|
||||
from metagpt.utils.make_sk_kernel import make_sk_kernel
|
||||
|
||||
|
||||
class SkAgent(Role):
|
||||
"""
|
||||
Represents an SkAgent implemented using semantic kernel
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the SkAgent.
|
||||
profile (str): Role profile, default is 'sk_agent'.
|
||||
goal (str): Goal of the SkAgent.
|
||||
constraints (str): Constraints for the SkAgent.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "Sunshine",
|
||||
profile: str = "sk_agent",
|
||||
goal: str = "Execute task based on passed in task description",
|
||||
constraints: str = "",
|
||||
planner_cls=BasicPlanner,
|
||||
) -> None:
|
||||
"""Initializes the Engineer role with given attributes."""
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
self._init_actions([ExecuteTask()])
|
||||
self._watch([BossRequirement])
|
||||
self.kernel = make_sk_kernel()
|
||||
|
||||
# how funny the interface is inconsistent
|
||||
if planner_cls == BasicPlanner:
|
||||
self.planner = planner_cls()
|
||||
elif planner_cls in [SequentialPlanner, ActionPlanner]:
|
||||
self.planner = planner_cls(self.kernel)
|
||||
else:
|
||||
raise f"Unsupported planner of type {planner_cls}"
|
||||
|
||||
self.import_semantic_skill_from_directory = self.kernel.import_semantic_skill_from_directory
|
||||
self.import_skill = self.kernel.import_skill
|
||||
|
||||
async def _think(self) -> None:
|
||||
self._set_state(0)
|
||||
# how funny the interface is inconsistent
|
||||
if isinstance(self.planner, BasicPlanner):
|
||||
self.plan = await self.planner.create_plan_async(self._rc.important_memory[-1].content, self.kernel)
|
||||
logger.info(self.plan.generated_plan)
|
||||
elif any(isinstance(self.planner, cls) for cls in [SequentialPlanner, ActionPlanner]):
|
||||
self.plan = await self.planner.create_plan_async(self._rc.important_memory[-1].content)
|
||||
|
||||
async def _act(self) -> Message:
|
||||
# how funny the interface is inconsistent
|
||||
if isinstance(self.planner, BasicPlanner):
|
||||
result = await self.planner.execute_plan_async(self.plan, self.kernel)
|
||||
elif any(isinstance(self.planner, cls) for cls in [SequentialPlanner, ActionPlanner]):
|
||||
result = (await self.plan.invoke_async()).result
|
||||
logger.info(result)
|
||||
|
||||
msg = Message(content=result, role=self.profile, cause_by=type(self._rc.todo))
|
||||
self._rc.memory.add(msg)
|
||||
# logger.debug(f"{response}")
|
||||
return msg
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Given a scientific white paper abstract, rewrite it to make it more readable",
|
||||
"completion": {
|
||||
"max_tokens": 4000,
|
||||
"temperature": 0.0,
|
||||
"top_p": 1.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 2.0
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{{$input}}
|
||||
|
||||
==
|
||||
Summarize, using a user friendly, using simple grammar. Don't use subjects like "we" "our" "us" "your".
|
||||
==
|
||||
12
metagpt/skills/SummarizeSkill/Notegen/config.json
Normal file
12
metagpt/skills/SummarizeSkill/Notegen/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Automatically generate compact notes for any text or text document.",
|
||||
"completion": {
|
||||
"max_tokens": 256,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
21
metagpt/skills/SummarizeSkill/Notegen/skprompt.txt
Normal file
21
metagpt/skills/SummarizeSkill/Notegen/skprompt.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Analyze the following extract taken from a document.
|
||||
- Produce key points for memory.
|
||||
- Give memory a name.
|
||||
- Extract only points worth remembering.
|
||||
- Be brief. Conciseness is very important.
|
||||
- Use broken English.
|
||||
You will use this memory to analyze the rest of this document, and for other relevant tasks.
|
||||
|
||||
[Input]
|
||||
My name is Macbeth. I used to be King of Scotland, but I died. My wife's name is Lady Macbeth and we were married for 15 years. We had no children. Our beloved dog Toby McDuff was a famous hunter of rats in the forest.
|
||||
My story was immortalized by Shakespeare in a play.
|
||||
+++++
|
||||
Family History
|
||||
- Macbeth, King Scotland
|
||||
- Wife Lady Macbeth, No Kids
|
||||
- Dog Toby McDuff. Hunter, dead.
|
||||
- Shakespeare play
|
||||
|
||||
[Input]
|
||||
[[{{$input}}]]
|
||||
+++++
|
||||
21
metagpt/skills/SummarizeSkill/Summarize/config.json
Normal file
21
metagpt/skills/SummarizeSkill/Summarize/config.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Summarize given text or any text document",
|
||||
"completion": {
|
||||
"max_tokens": 512,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
},
|
||||
"input": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "input",
|
||||
"description": "Text to summarize",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
23
metagpt/skills/SummarizeSkill/Summarize/skprompt.txt
Normal file
23
metagpt/skills/SummarizeSkill/Summarize/skprompt.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
[SUMMARIZATION RULES]
|
||||
DONT WASTE WORDS
|
||||
USE SHORT, CLEAR, COMPLETE SENTENCES.
|
||||
DO NOT USE BULLET POINTS OR DASHES.
|
||||
USE ACTIVE VOICE.
|
||||
MAXIMIZE DETAIL, MEANING
|
||||
FOCUS ON THE CONTENT
|
||||
|
||||
[BANNED PHRASES]
|
||||
This article
|
||||
This document
|
||||
This page
|
||||
This material
|
||||
[END LIST]
|
||||
|
||||
Summarize:
|
||||
Hello how are you?
|
||||
+++++
|
||||
Hello
|
||||
|
||||
Summarize this
|
||||
{{$input}}
|
||||
+++++
|
||||
12
metagpt/skills/SummarizeSkill/Topics/config.json
Normal file
12
metagpt/skills/SummarizeSkill/Topics/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Analyze given text or document and extract key topics worth remembering",
|
||||
"completion": {
|
||||
"max_tokens": 128,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
28
metagpt/skills/SummarizeSkill/Topics/skprompt.txt
Normal file
28
metagpt/skills/SummarizeSkill/Topics/skprompt.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
Analyze the following extract taken from a document and extract key topics.
|
||||
- Topics only worth remembering.
|
||||
- Be brief. Short phrases.
|
||||
- Can use broken English.
|
||||
- Conciseness is very important.
|
||||
- Topics can include names of memories you want to recall.
|
||||
- NO LONG SENTENCES. SHORT PHRASES.
|
||||
- Return in JSON
|
||||
[Input]
|
||||
My name is Macbeth. I used to be King of Scotland, but I died. My wife's name is Lady Macbeth and we were married for 15 years. We had no children. Our beloved dog Toby McDuff was a famous hunter of rats in the forest.
|
||||
My tragic story was immortalized by Shakespeare in a play.
|
||||
[Output]
|
||||
{
|
||||
"topics": [
|
||||
"Macbeth",
|
||||
"King of Scotland",
|
||||
"Lady Macbeth",
|
||||
"Dog",
|
||||
"Toby McDuff",
|
||||
"Shakespeare",
|
||||
"Play",
|
||||
"Tragedy"
|
||||
]
|
||||
}
|
||||
+++++
|
||||
[Input]
|
||||
{{$input}}
|
||||
[Output]
|
||||
12
metagpt/skills/WriterSkill/Acronym/config.json
Normal file
12
metagpt/skills/WriterSkill/Acronym/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Generate an acronym for the given concept or phrase",
|
||||
"completion": {
|
||||
"max_tokens": 100,
|
||||
"temperature": 0.5,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
25
metagpt/skills/WriterSkill/Acronym/skprompt.txt
Normal file
25
metagpt/skills/WriterSkill/Acronym/skprompt.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Generate a suitable acronym pair for the concept. Creativity is encouraged, including obscure references.
|
||||
The uppercase letters in the acronym expansion must agree with the letters of the acronym
|
||||
|
||||
Q: A technology for detecting moving objects, their distance and velocity using radio waves.
|
||||
A: R.A.D.A.R: RAdio Detection And Ranging.
|
||||
|
||||
Q: A weapon that uses high voltage electricity to incapacitate the target
|
||||
A. T.A.S.E.R: Thomas A. Swift’s Electric Rifle
|
||||
|
||||
Q: Equipment that lets a diver breathe underwater
|
||||
A: S.C.U.B.A: Self Contained Underwater Breathing Apparatus.
|
||||
|
||||
Q: Reminder not to complicated subject matter.
|
||||
A. K.I.S.S: Keep It Simple Stupid
|
||||
|
||||
Q: A national organization for investment in space travel, rockets, space ships, space exploration
|
||||
A. N.A.S.A: National Aeronautics Space Administration
|
||||
|
||||
Q: Agreement that governs trade among North American countries.
|
||||
A: N.A.F.T.A: North American Free Trade Agreement.
|
||||
|
||||
Q: Organization to protect the freedom and security of its member countries in North America and Europe.
|
||||
A: N.A.T.O: North Atlantic Treaty Organization.
|
||||
|
||||
Q:{{$input}}
|
||||
15
metagpt/skills/WriterSkill/AcronymGenerator/config.json
Normal file
15
metagpt/skills/WriterSkill/AcronymGenerator/config.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Given a request to generate an acronym from a string, generate an acronym and provide the acronym explanation.",
|
||||
"completion": {
|
||||
"max_tokens": 256,
|
||||
"temperature": 0.7,
|
||||
"top_p": 1.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0,
|
||||
"stop_sequences": [
|
||||
"#"
|
||||
]
|
||||
}
|
||||
}
|
||||
54
metagpt/skills/WriterSkill/AcronymGenerator/skprompt.txt
Normal file
54
metagpt/skills/WriterSkill/AcronymGenerator/skprompt.txt
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Name of a super artificial intelligence
|
||||
J.A.R.V.I.S. = Just A Really Very Intelligent System.
|
||||
# Name for a new young beautiful assistant
|
||||
F.R.I.D.A.Y. = Female Replacement Intelligent Digital Assistant Youth.
|
||||
# Mirror to check what's behind
|
||||
B.A.R.F. = Binary Augmented Retro-Framing.
|
||||
# Pair of powerful glasses created by a genius that is now dead
|
||||
E.D.I.T.H. = Even Dead I’m The Hero.
|
||||
# A company building and selling computers
|
||||
I.B.M. = Intelligent Business Machine.
|
||||
# A super computer that is sentient.
|
||||
H.A.L = Heuristically programmed ALgorithmic computer.
|
||||
# an intelligent bot that helps with productivity.
|
||||
C.O.R.E. = Central Optimization Routines and Efficiency.
|
||||
# an intelligent bot that helps with productivity.
|
||||
P.A.L. = Personal Assistant Light.
|
||||
# an intelligent bot that helps with productivity.
|
||||
A.I.D.A. = Artificial Intelligence Digital Assistant.
|
||||
# an intelligent bot that helps with productivity.
|
||||
H.E.R.A. = Human Emulation and Recognition Algorithm.
|
||||
# an intelligent bot that helps with productivity.
|
||||
I.C.A.R.U.S. = Intelligent Control and Automation of Research and Utility Systems.
|
||||
# an intelligent bot that helps with productivity.
|
||||
N.E.M.O. = Networked Embedded Multiprocessor Orchestration.
|
||||
# an intelligent bot that helps with productivity.
|
||||
E.P.I.C. = Enhanced Productivity and Intelligence through Computing.
|
||||
# an intelligent bot that helps with productivity.
|
||||
M.A.I.A. = Multipurpose Artificial Intelligence Assistant.
|
||||
# an intelligent bot that helps with productivity.
|
||||
A.R.I.A. = Artificial Reasoning and Intelligent Assistant.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
O.M.E.G.A. = Optimized Mathematical Entity for Generalized Artificial intelligence.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
P.Y.T.H.O.N. = Precise Yet Thorough Heuristic Optimization Network.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
A.P.O.L.L.O. = Adaptive Probabilistic Optimization Learning Library for Online Applications.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
S.O.L.I.D. = Self-Organizing Logical Intelligent Data-base.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
D.E.E.P. = Dynamic Estimation and Prediction.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
B.R.A.I.N. = Biologically Realistic Artificial Intelligence Network.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
C.O.G.N.I.T.O. = COmputational and Generalized INtelligence TOolkit.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
S.A.G.E. = Symbolic Artificial General Intelligence Engine.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
Q.U.A.R.K. = Quantum Universal Algorithmic Reasoning Kernel.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
S.O.L.V.E. = Sophisticated Operational Logic and Versatile Expertise.
|
||||
# An incredibly smart entity developed with complex math, that helps me being more productive.
|
||||
C.A.L.C.U.L.U.S. = Cognitively Advanced Logic and Computation Unit for Learning and Understanding Systems.
|
||||
|
||||
# {{$INPUT}}
|
||||
15
metagpt/skills/WriterSkill/AcronymReverse/config.json
Normal file
15
metagpt/skills/WriterSkill/AcronymReverse/config.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Given a single word or acronym, generate the expanded form matching the acronym letters.",
|
||||
"completion": {
|
||||
"max_tokens": 256,
|
||||
"temperature": 0.5,
|
||||
"top_p": 1.0,
|
||||
"presence_penalty": 0.8,
|
||||
"frequency_penalty": 0.0,
|
||||
"stop_sequences": [
|
||||
"#END#"
|
||||
]
|
||||
}
|
||||
}
|
||||
24
metagpt/skills/WriterSkill/AcronymReverse/skprompt.txt
Normal file
24
metagpt/skills/WriterSkill/AcronymReverse/skprompt.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# acronym: Devis
|
||||
Sentences matching the acronym:
|
||||
1. Dragons Eat Very Interesting Snacks
|
||||
2. Develop Empathy and Vision to Increase Success
|
||||
3. Don't Expect Vampires In Supermarkets
|
||||
#END#
|
||||
|
||||
# acronym: Christmas
|
||||
Sentences matching the acronym:
|
||||
1. Celebrating Harmony and Respect in a Season of Togetherness, Merriment, and True joy
|
||||
2. Children Have Real Interest Since The Mystery And Surprise Thrills
|
||||
3. Christmas Helps Reduce Inner Stress Through Mistletoe And Sleigh excursions
|
||||
#END#
|
||||
|
||||
# acronym: noWare
|
||||
Sentences matching the acronym:
|
||||
1. No One Wants an App that Randomly Erases everything
|
||||
2. Nourishing Oatmeal With Almond, Raisin, and Egg toppings
|
||||
3. Notice Opportunity When Available and React Enthusiastically
|
||||
#END#
|
||||
|
||||
Reverse the following acronym back to a funny sentence. Provide 3 examples.
|
||||
# acronym: {{$INPUT}}
|
||||
Sentences matching the acronym:
|
||||
22
metagpt/skills/WriterSkill/Brainstorm/config.json
Normal file
22
metagpt/skills/WriterSkill/Brainstorm/config.json
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Given a goal or topic description generate a list of ideas",
|
||||
"completion": {
|
||||
"max_tokens": 2000,
|
||||
"temperature": 0.5,
|
||||
"top_p": 1.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0,
|
||||
"stop_sequences": ["##END##"]
|
||||
},
|
||||
"input": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "input",
|
||||
"description": "A topic description or goal.",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
8
metagpt/skills/WriterSkill/Brainstorm/skprompt.txt
Normal file
8
metagpt/skills/WriterSkill/Brainstorm/skprompt.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Must: brainstorm ideas and create a list.
|
||||
Must: use a numbered list.
|
||||
Must: only one list.
|
||||
Must: end list with ##END##
|
||||
Should: no more than 10 items.
|
||||
Should: at least 3 items.
|
||||
Topic: {{$INPUT}}
|
||||
Start.
|
||||
12
metagpt/skills/WriterSkill/EmailGen/config.json
Normal file
12
metagpt/skills/WriterSkill/EmailGen/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Write an email from the given bullet points",
|
||||
"completion": {
|
||||
"max_tokens": 256,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
16
metagpt/skills/WriterSkill/EmailGen/skprompt.txt
Normal file
16
metagpt/skills/WriterSkill/EmailGen/skprompt.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
Rewrite my bullet points into complete sentences. Use a polite and inclusive tone.
|
||||
|
||||
[Input]
|
||||
- Macbeth, King Scotland
|
||||
- Married, Wife Lady Macbeth, No Kids
|
||||
- Dog Toby McDuff. Hunter, dead.
|
||||
- Shakespeare play
|
||||
+++++
|
||||
The story of Macbeth
|
||||
My name is Macbeth. I used to be King of Scotland, but I died. My wife's name is Lady Macbeth and we were married for 15 years. We had no children. Our beloved dog Toby McDuff was a famous hunter of rats in the forest.
|
||||
My story was immortalized by Shakespeare in a play.
|
||||
|
||||
+++++
|
||||
[Input]
|
||||
{{$input}}
|
||||
+++++
|
||||
12
metagpt/skills/WriterSkill/EmailTo/config.json
Normal file
12
metagpt/skills/WriterSkill/EmailTo/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Turn bullet points into an email to someone, using a polite tone",
|
||||
"completion": {
|
||||
"max_tokens": 256,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
31
metagpt/skills/WriterSkill/EmailTo/skprompt.txt
Normal file
31
metagpt/skills/WriterSkill/EmailTo/skprompt.txt
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
Rewrite my bullet points into an email featuring complete sentences. Use a polite and inclusive tone.
|
||||
|
||||
[Input]
|
||||
Toby,
|
||||
|
||||
- Macbeth, King Scotland
|
||||
- Married, Wife Lady Macbeth, No Kids
|
||||
- Dog Toby McDuff. Hunter, dead.
|
||||
- Shakespeare play
|
||||
|
||||
Thanks,
|
||||
Dexter
|
||||
|
||||
+++++
|
||||
Hi Toby,
|
||||
|
||||
The story of Macbeth
|
||||
My name is Macbeth. I used to be King of Scotland, but I died. My wife's name is Lady Macbeth and we were married for 15 years. We had no children. Our beloved dog Toby McDuff was a famous hunter of rats in the forest.
|
||||
My story was immortalized by Shakespeare in a play.
|
||||
|
||||
Thanks,
|
||||
Dexter
|
||||
|
||||
+++++
|
||||
[Input]
|
||||
{{$to}}
|
||||
{{$input}}
|
||||
|
||||
Thanks,
|
||||
{{$sender}}
|
||||
+++++
|
||||
12
metagpt/skills/WriterSkill/EnglishImprover/config.json
Normal file
12
metagpt/skills/WriterSkill/EnglishImprover/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Translate text to English and improve it",
|
||||
"completion": {
|
||||
"max_tokens": 3000,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
11
metagpt/skills/WriterSkill/EnglishImprover/skprompt.txt
Normal file
11
metagpt/skills/WriterSkill/EnglishImprover/skprompt.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
I want you to act as an English translator, spelling corrector and improver.
|
||||
I will speak to you in any language and you will detect the language, translate it and answer in the corrected and improved version of my text, in English.
|
||||
I want you to replace my simplified A0-level words and sentences with more beautiful and elegant, upper level English words and sentences.
|
||||
Keep the meaning same, but make them more literary.
|
||||
I want you to only reply the correction, the improvements and nothing else, do not write explanations.
|
||||
|
||||
Sentence: """
|
||||
{{$INPUT}}
|
||||
"""
|
||||
|
||||
Translation:
|
||||
36
metagpt/skills/WriterSkill/NovelChapter/config.json
Normal file
36
metagpt/skills/WriterSkill/NovelChapter/config.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Write a chapter of a novel.",
|
||||
"completion": {
|
||||
"max_tokens": 2048,
|
||||
"temperature": 0.3,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
},
|
||||
"input": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "input",
|
||||
"description": "A synopsis of what the chapter should be about.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "theme",
|
||||
"description": "The theme or topic of this novel.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "previousChapter",
|
||||
"description": "The synopsis of the previous chapter.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "chapterIndex",
|
||||
"description": "The number of the chapter to write.",
|
||||
"defaultValue": "<!--===ENDPART===-->"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
20
metagpt/skills/WriterSkill/NovelChapter/skprompt.txt
Normal file
20
metagpt/skills/WriterSkill/NovelChapter/skprompt.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[CONTEXT]
|
||||
|
||||
THEME OF STORY:
|
||||
{{$theme}}
|
||||
|
||||
PREVIOUS CHAPTER:
|
||||
{{$previousChapter}}
|
||||
|
||||
[END CONTEXT]
|
||||
|
||||
|
||||
WRITE THIS CHAPTER USING [CONTEXT] AND
|
||||
CHAPTER SYNOPSIS. DO NOT REPEAT SYNOPSIS IN THE OUTPUT
|
||||
|
||||
Chapter Synopsis:
|
||||
{{$input}}
|
||||
|
||||
Chapter {{$chapterIndex}}
|
||||
|
||||
|
||||
41
metagpt/skills/WriterSkill/NovelChapterWithNotes/config.json
Normal file
41
metagpt/skills/WriterSkill/NovelChapterWithNotes/config.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Write a chapter of a novel using notes about the chapter to write.",
|
||||
"completion": {
|
||||
"max_tokens": 1024,
|
||||
"temperature": 0.5,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
},
|
||||
"input": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "input",
|
||||
"description": "What the novel should be about.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "theme",
|
||||
"description": "The theme of this novel.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "notes",
|
||||
"description": "Notes useful to write this chapter.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "previousChapter",
|
||||
"description": "The previous chapter synopsis.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "chapterIndex",
|
||||
"description": "The number of the chapter to write.",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
[CONTEXT]
|
||||
|
||||
THEME OF STORY:
|
||||
{{$theme}}
|
||||
|
||||
NOTES OF STORY SO FAR - USE AS REFERENCE
|
||||
{{$notes}}
|
||||
|
||||
PREVIOUS CHAPTER, USE AS REFERENCE:
|
||||
{{$previousChapter}}
|
||||
|
||||
[END CONTEXT]
|
||||
|
||||
|
||||
WRITE THIS CHAPTER CONTINUING STORY, USING [CONTEXT] AND CHAPTER SYNOPSIS BELOW. DO NOT REPEAT SYNOPSIS IN THE CHAPTER. DON'T REPEAT PREVIOUS CHAPTER.
|
||||
|
||||
{{$input}}
|
||||
|
||||
Chapter {{$chapterIndex}}
|
||||
31
metagpt/skills/WriterSkill/NovelOutline/config.json
Normal file
31
metagpt/skills/WriterSkill/NovelOutline/config.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Generate a list of chapter synopsis for a novel or novella",
|
||||
"completion": {
|
||||
"max_tokens": 2048,
|
||||
"temperature": 0.1,
|
||||
"top_p": 0.5,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
},
|
||||
"input": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "input",
|
||||
"description": "What the novel should be about.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "chapterCount",
|
||||
"description": "The number of chapters to generate.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "endMarker",
|
||||
"description": "The marker to use to end each chapter.",
|
||||
"defaultValue": "<!--===ENDPART===-->"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
12
metagpt/skills/WriterSkill/NovelOutline/skprompt.txt
Normal file
12
metagpt/skills/WriterSkill/NovelOutline/skprompt.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
I want to write a {{$chapterCount}} chapter novella about:
|
||||
{{$input}}
|
||||
|
||||
There MUST BE {{$chapterCount}} CHAPTERS.
|
||||
|
||||
INVENT CHARACTERS AS YOU SEE FIT. BE HIGHLY CREATIVE AND/OR FUNNY.
|
||||
WRITE SYNOPSIS FOR EACH CHAPTER. INCLUDE INFORMATION ABOUT CHARACTERS ETC. SINCE EACH
|
||||
CHAPTER WILL BE WRITTEN BY A DIFFERENT WRITER, YOU MUST INCLUDE ALL PERTINENT INFORMATION
|
||||
IN EACH SYNOPSIS
|
||||
|
||||
YOU MUST END EACH SYNOPSIS WITH {{$endMarker}}
|
||||
|
||||
12
metagpt/skills/WriterSkill/Rewrite/config.json
Normal file
12
metagpt/skills/WriterSkill/Rewrite/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Automatically generate compact notes for any text or text document",
|
||||
"completion": {
|
||||
"max_tokens": 256,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
6
metagpt/skills/WriterSkill/Rewrite/skprompt.txt
Normal file
6
metagpt/skills/WriterSkill/Rewrite/skprompt.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Rewrite the given text like it was written in this style or by: {{$style}}.
|
||||
MUST RETAIN THE MEANING AND FACTUAL CONTENT AS THE ORIGINAL.
|
||||
|
||||
|
||||
{{$input}}
|
||||
|
||||
21
metagpt/skills/WriterSkill/ShortPoem/config.json
Normal file
21
metagpt/skills/WriterSkill/ShortPoem/config.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Turn a scenario into a short and entertaining poem.",
|
||||
"completion": {
|
||||
"max_tokens": 60,
|
||||
"temperature": 0.5,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
},
|
||||
"input": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "input",
|
||||
"description": "The scenario to turn into a poem.",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
2
metagpt/skills/WriterSkill/ShortPoem/skprompt.txt
Normal file
2
metagpt/skills/WriterSkill/ShortPoem/skprompt.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
Generate a short funny poem or limerick to explain the given event. Be creative and be funny. Let your imagination run wild.
|
||||
Event:{{$input}}
|
||||
12
metagpt/skills/WriterSkill/StoryGen/config.json
Normal file
12
metagpt/skills/WriterSkill/StoryGen/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Generate a list of synopsis for a novel or novella with sub-chapters",
|
||||
"completion": {
|
||||
"max_tokens": 250,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
10
metagpt/skills/WriterSkill/StoryGen/skprompt.txt
Normal file
10
metagpt/skills/WriterSkill/StoryGen/skprompt.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
ONLY USE XML TAGS IN THIS LIST:
|
||||
[XML TAG LIST]
|
||||
list: Surround any lists with this tag
|
||||
synopsis: An outline of the chapter to write
|
||||
[END LIST]
|
||||
|
||||
EMIT WELL FORMED XML ALWAYS. Code should be CDATA.
|
||||
|
||||
|
||||
{{$input}}
|
||||
12
metagpt/skills/WriterSkill/TellMeMore/config.json
Normal file
12
metagpt/skills/WriterSkill/TellMeMore/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Summarize given text or any text document",
|
||||
"completion": {
|
||||
"max_tokens": 500,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
7
metagpt/skills/WriterSkill/TellMeMore/skprompt.txt
Normal file
7
metagpt/skills/WriterSkill/TellMeMore/skprompt.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
>>>>>The following is part of a {{$conversationtype}}.
|
||||
{{$input}}
|
||||
|
||||
>>>>>The following is an overview of a previous part of the {{$conversationtype}}, focusing on "{{$focusarea}}".
|
||||
{{$previousresults}}
|
||||
|
||||
>>>>>In 250 words or less, write a verbose and detailed overview of the {{$conversationtype}} focusing solely on "{{$focusarea}}".
|
||||
15
metagpt/skills/WriterSkill/Translate/config.json
Normal file
15
metagpt/skills/WriterSkill/Translate/config.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Translate the input into a language of your choice",
|
||||
"completion": {
|
||||
"max_tokens": 2000,
|
||||
"temperature": 0.7,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0,
|
||||
"stop_sequences": [
|
||||
"[done]"
|
||||
]
|
||||
}
|
||||
}
|
||||
7
metagpt/skills/WriterSkill/Translate/skprompt.txt
Normal file
7
metagpt/skills/WriterSkill/Translate/skprompt.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Translate the input below into {{$language}}
|
||||
|
||||
MAKE SURE YOU ONLY USE {{$language}}.
|
||||
|
||||
{{$input}}
|
||||
|
||||
Translation:
|
||||
12
metagpt/skills/WriterSkill/TwoSentenceSummary/config.json
Normal file
12
metagpt/skills/WriterSkill/TwoSentenceSummary/config.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"type": "completion",
|
||||
"description": "Summarize given text in two sentences or less",
|
||||
"completion": {
|
||||
"max_tokens": 100,
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Summarize the following text in two sentences or less.
|
||||
[BEGIN TEXT]
|
||||
{{$input}}
|
||||
[END TEXT]
|
||||
129
metagpt/tools/code_interpreter.py
Normal file
129
metagpt/tools/code_interpreter.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
import re
|
||||
from typing import List, Callable
|
||||
from pathlib import Path
|
||||
|
||||
import wrapt
|
||||
import textwrap
|
||||
import inspect
|
||||
from interpreter.interpreter import Interpreter
|
||||
|
||||
from metagpt.logs import logger
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.utils.highlight import highlight
|
||||
from metagpt.actions.clone_function import CloneFunction, run_function_code, run_function_script
|
||||
|
||||
|
||||
def extract_python_code(code: str):
|
||||
"""Extract code blocks: If the code comments are the same, only the last code block is kept."""
|
||||
# Use regular expressions to match comment blocks and related code.
|
||||
pattern = r'(#\s[^\n]*)\n(.*?)(?=\n\s*#|$)'
|
||||
matches = re.findall(pattern, code, re.DOTALL)
|
||||
|
||||
# Extract the last code block when encountering the same comment.
|
||||
unique_comments = {}
|
||||
for comment, code_block in matches:
|
||||
unique_comments[comment] = code_block
|
||||
|
||||
# concatenate into functional form
|
||||
result_code = '\n'.join([f"{comment}\n{code_block}" for comment, code_block in unique_comments.items()])
|
||||
header_code = code[:code.find("#")]
|
||||
code = header_code + result_code
|
||||
|
||||
logger.info(f"Extract python code: \n {highlight(code)}")
|
||||
|
||||
return code
|
||||
|
||||
|
||||
class OpenCodeInterpreter(object):
|
||||
"""https://github.com/KillianLucas/open-interpreter"""
|
||||
def __init__(self, auto_run: bool = True) -> None:
|
||||
interpreter = Interpreter()
|
||||
interpreter.auto_run = auto_run
|
||||
interpreter.model = CONFIG.openai_api_model or "gpt-3.5-turbo"
|
||||
interpreter.api_key = CONFIG.openai_api_key
|
||||
interpreter.api_base = CONFIG.openai_api_base
|
||||
self.interpreter = interpreter
|
||||
|
||||
def chat(self, query: str, reset: bool = True):
|
||||
if reset:
|
||||
self.interpreter.reset()
|
||||
return self.interpreter.chat(query, return_messages=True)
|
||||
|
||||
@staticmethod
|
||||
def extract_function(query_respond: List, function_name: str, *, language: str = 'python',
|
||||
function_format: str = None) -> str:
|
||||
"""create a function from query_respond."""
|
||||
if language not in ('python'):
|
||||
raise NotImplementedError(f"Not support to parse language {language}!")
|
||||
|
||||
# set function form
|
||||
if function_format is None:
|
||||
assert language == 'python', f"Expect python language for default function_format, but got {language}."
|
||||
function_format = """def {function_name}():\n{code}"""
|
||||
# Extract the code module in the open-interpreter respond message.
|
||||
code = [item['function_call']['parsed_arguments']['code'] for item in query_respond
|
||||
if "function_call" in item
|
||||
and "parsed_arguments" in item["function_call"]
|
||||
and 'language' in item["function_call"]['parsed_arguments']
|
||||
and item["function_call"]['parsed_arguments']['language'] == language]
|
||||
# add indent.
|
||||
indented_code_str = textwrap.indent("\n".join(code), ' ' * 4)
|
||||
# Return the code after deduplication.
|
||||
if language == "python":
|
||||
return extract_python_code(function_format.format(function_name=function_name, code=indented_code_str))
|
||||
|
||||
|
||||
def gen_query(func: Callable, args, kwargs) -> str:
|
||||
# Get the annotation of the function as part of the query.
|
||||
desc = func.__doc__
|
||||
signature = inspect.signature(func)
|
||||
# Get the signature of the wrapped function and the assignment of the input parameters as part of the query.
|
||||
bound_args = signature.bind(*args, **kwargs)
|
||||
bound_args.apply_defaults()
|
||||
query = f"{desc}, {bound_args.arguments}, If you must use a third-party package, use the most popular ones, for example: pandas, numpy, ta, ..."
|
||||
return query
|
||||
|
||||
|
||||
def gen_template_fun(func: Callable) -> str:
|
||||
return f"def {func.__name__}{str(inspect.signature(func))}\n # here is your code ..."
|
||||
|
||||
|
||||
class OpenInterpreterDecorator(object):
|
||||
def __init__(self, save_code: bool = False, code_file_path: str = None, clear_code: bool = False) -> None:
|
||||
self.save_code = save_code
|
||||
self.code_file_path = code_file_path
|
||||
self.clear_code = clear_code
|
||||
|
||||
def __call__(self, wrapped):
|
||||
@wrapt.decorator
|
||||
async def wrapper(wrapped: Callable, instance, args, kwargs):
|
||||
# Get the decorated function name.
|
||||
func_name = wrapped.__name__
|
||||
# If the script exists locally and clearcode is not required, execute the function from the script.
|
||||
if Path(self.code_file_path).is_file() and not self.clear_code:
|
||||
return run_function_script(self.code_file_path, func_name, *args, **kwargs)
|
||||
|
||||
# Auto run generate code by using open-interpreter.
|
||||
interpreter = OpenCodeInterpreter()
|
||||
query = gen_query(wrapped, args, kwargs)
|
||||
logger.info(f"query for OpenCodeInterpreter: \n {query}")
|
||||
respond = interpreter.chat(query)
|
||||
# Assemble the code blocks generated by open-interpreter into a function without parameters.
|
||||
func_code = interpreter.extract_function(respond, func_name)
|
||||
# Clone the `func_code` into wrapped, that is,
|
||||
# keep the `func_code` and wrapped functions with the same input parameter and return value types.
|
||||
template_func = gen_template_fun(wrapped)
|
||||
cf = CloneFunction()
|
||||
code = await cf.run(template_func=template_func, source_code=func_code)
|
||||
# Display the generated function in the terminal.
|
||||
logger_code = highlight(code, "python")
|
||||
logger.info(f"Creating following Python function:\n{logger_code}")
|
||||
# execute this function.
|
||||
try:
|
||||
res = run_function_code(code, func_name, *args, **kwargs)
|
||||
if self.save_code:
|
||||
cf._save(self.code_file_path, code)
|
||||
except Exception as e:
|
||||
raise Exception("Could not evaluate Python code", e)
|
||||
return res
|
||||
return wrapper(wrapped)
|
||||
|
|
@ -5,15 +5,32 @@
|
|||
@Author : alexanderwu
|
||||
@File : search_engine.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
# from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
from typing import Callable, Coroutine, Literal, overload
|
||||
|
||||
from semantic_kernel.skill_definition import sk_function
|
||||
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.tools import SearchEngineType
|
||||
|
||||
|
||||
class SkSearchEngine:
|
||||
def __init__(self):
|
||||
self.search_engine = SearchEngine()
|
||||
|
||||
@sk_function(
|
||||
description="searches results from Google. Useful when you need to find short "
|
||||
"and succinct answers about a specific topic. Input should be a search query.",
|
||||
name="searchAsync",
|
||||
input_description="search",
|
||||
)
|
||||
async def run(self, query: str) -> str:
|
||||
result = await self.search_engine.run(query)
|
||||
return result
|
||||
|
||||
|
||||
class SearchEngine:
|
||||
"""Class representing a search engine.
|
||||
|
||||
|
|
@ -25,6 +42,7 @@ class SearchEngine:
|
|||
run_func: The function to run the search.
|
||||
engine: The search engine type.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
engine: SearchEngineType | None = None,
|
||||
|
|
@ -33,7 +51,7 @@ class SearchEngine:
|
|||
engine = engine or CONFIG.search_engine
|
||||
if engine == SearchEngineType.SERPAPI_GOOGLE:
|
||||
module = "metagpt.tools.search_engine_serpapi"
|
||||
run_func = importlib.import_module(module).SerpAPIWrapper().run
|
||||
run_func = importlib.import_module(module).SerpAPIWrapper().run
|
||||
elif engine == SearchEngineType.SERPER_GOOGLE:
|
||||
module = "metagpt.tools.search_engine_serper"
|
||||
run_func = importlib.import_module(module).SerperWrapper().run
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import inspect
|
|||
import os
|
||||
import platform
|
||||
import re
|
||||
from typing import List, Tuple
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
from metagpt.logs import logger
|
||||
|
||||
|
|
@ -150,6 +150,53 @@ class OutputParser:
|
|||
parsed_data[block] = content
|
||||
return parsed_data
|
||||
|
||||
@classmethod
|
||||
def extract_struct(cls, text: str, data_type: Union[type(list), type(dict)]) -> Union[list, dict]:
|
||||
"""Extracts and parses a specified type of structure (dictionary or list) from the given text.
|
||||
The text only contains a list or dictionary, which may have nested structures.
|
||||
|
||||
Args:
|
||||
text: The text containing the structure (dictionary or list).
|
||||
data_type: The data type to extract, can be "list" or "dict".
|
||||
|
||||
Returns:
|
||||
- If extraction and parsing are successful, it returns the corresponding data structure (list or dictionary).
|
||||
- If extraction fails or parsing encounters an error, it throw an exception.
|
||||
|
||||
Examples:
|
||||
>>> text = 'xxx [1, 2, ["a", "b", [3, 4]], {"x": 5, "y": [6, 7]}] xxx'
|
||||
>>> result_list = OutputParser.extract_struct(text, "list")
|
||||
>>> print(result_list)
|
||||
>>> # Output: [1, 2, ["a", "b", [3, 4]], {"x": 5, "y": [6, 7]}]
|
||||
|
||||
>>> text = 'xxx {"x": 1, "y": {"a": 2, "b": {"c": 3}}} xxx'
|
||||
>>> result_dict = OutputParser.extract_struct(text, "dict")
|
||||
>>> print(result_dict)
|
||||
>>> # Output: {"x": 1, "y": {"a": 2, "b": {"c": 3}}}
|
||||
"""
|
||||
# Find the first "[" or "{" and the last "]" or "}"
|
||||
start_index = text.find("[" if data_type is list else "{")
|
||||
end_index = text.rfind("]" if data_type is list else "}")
|
||||
|
||||
if start_index != -1 and end_index != -1:
|
||||
# Extract the structure part
|
||||
structure_text = text[start_index:end_index + 1]
|
||||
|
||||
try:
|
||||
# Attempt to convert the text to a Python data type using ast.literal_eval
|
||||
result = ast.literal_eval(structure_text)
|
||||
|
||||
# Ensure the result matches the specified data type
|
||||
if isinstance(result, list) or isinstance(result, dict):
|
||||
return result
|
||||
|
||||
raise ValueError(f"The extracted structure is not a {data_type}.")
|
||||
|
||||
except (ValueError, SyntaxError) as e:
|
||||
raise Exception(f"Error while extracting and parsing the {data_type}: {e}")
|
||||
else:
|
||||
raise Exception(f"No {data_type} found in the text.")
|
||||
|
||||
|
||||
class CodeParser:
|
||||
@classmethod
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ from metagpt.logs import logger
|
|||
class File:
|
||||
"""A general util for file operations."""
|
||||
|
||||
CHUNK_SIZE = 64 * 1024
|
||||
|
||||
@classmethod
|
||||
async def write(cls, root_path: Path, filename: str, content: bytes) -> Path:
|
||||
"""Write the file content to the local specified path.
|
||||
|
|
@ -35,8 +37,39 @@ class File:
|
|||
full_path = root_path / filename
|
||||
async with aiofiles.open(full_path, mode="wb") as writer:
|
||||
await writer.write(content)
|
||||
logger.info(f"Successfully write file: {full_path}")
|
||||
logger.debug(f"Successfully write file: {full_path}")
|
||||
return full_path
|
||||
except Exception as e:
|
||||
logger.error(f"Error writing file: {e}")
|
||||
raise e
|
||||
raise e
|
||||
|
||||
@classmethod
|
||||
async def read(cls, file_path: Path, chunk_size: int = None) -> bytes:
|
||||
"""Partitioning read the file content from the local specified path.
|
||||
|
||||
Args:
|
||||
file_path: The full file name of file, such as "/data/test.txt".
|
||||
chunk_size: The size of each chunk in bytes (default is 64kb).
|
||||
|
||||
Returns:
|
||||
The binary content of file.
|
||||
|
||||
Raises:
|
||||
Exception: If an unexpected error occurs during the file reading process.
|
||||
"""
|
||||
try:
|
||||
chunk_size = chunk_size or cls.CHUNK_SIZE
|
||||
async with aiofiles.open(file_path, mode="rb") as reader:
|
||||
chunks = list()
|
||||
while True:
|
||||
chunk = await reader.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
chunks.append(chunk)
|
||||
content = b''.join(chunks)
|
||||
logger.debug(f"Successfully read file, the path of file: {file_path}")
|
||||
return content
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading file: {e}")
|
||||
raise e
|
||||
|
||||
|
|
|
|||
25
metagpt/utils/highlight.py
Normal file
25
metagpt/utils/highlight.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# 添加代码语法高亮显示
|
||||
from pygments import highlight as highlight_
|
||||
from pygments.lexers import PythonLexer, SqlLexer
|
||||
from pygments.formatters import TerminalFormatter, HtmlFormatter
|
||||
|
||||
|
||||
def highlight(code: str, language: str = 'python', formatter: str = 'terminal'):
|
||||
# 指定要高亮的语言
|
||||
if language.lower() == 'python':
|
||||
lexer = PythonLexer()
|
||||
elif language.lower() == 'sql':
|
||||
lexer = SqlLexer()
|
||||
else:
|
||||
raise ValueError(f"Unsupported language: {language}")
|
||||
|
||||
# 指定输出格式
|
||||
if formatter.lower() == 'terminal':
|
||||
formatter = TerminalFormatter()
|
||||
elif formatter.lower() == 'html':
|
||||
formatter = HtmlFormatter()
|
||||
else:
|
||||
raise ValueError(f"Unsupported formatter: {formatter}")
|
||||
|
||||
# 使用 Pygments 高亮代码片段
|
||||
return highlight_(code, lexer, formatter)
|
||||
34
metagpt/utils/make_sk_kernel.py
Normal file
34
metagpt/utils/make_sk_kernel.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/9/13 12:29
|
||||
@Author : femto Zheng
|
||||
@File : make_sk_kernel.py
|
||||
"""
|
||||
import semantic_kernel as sk
|
||||
from semantic_kernel.connectors.ai.open_ai.services.azure_chat_completion import (
|
||||
AzureChatCompletion,
|
||||
)
|
||||
from semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion import (
|
||||
OpenAIChatCompletion,
|
||||
)
|
||||
|
||||
from metagpt.config import CONFIG
|
||||
|
||||
|
||||
def make_sk_kernel():
|
||||
kernel = sk.Kernel()
|
||||
if CONFIG.openai_api_type == "azure":
|
||||
kernel.add_chat_service(
|
||||
"chat_completion",
|
||||
AzureChatCompletion(CONFIG.deployment_name, CONFIG.openai_api_base, CONFIG.openai_api_key),
|
||||
)
|
||||
else:
|
||||
kernel.add_chat_service(
|
||||
"chat_completion",
|
||||
OpenAIChatCompletion(
|
||||
CONFIG.openai_api_model, CONFIG.openai_api_key, org_id=None, endpoint=CONFIG.openai_api_base
|
||||
),
|
||||
)
|
||||
|
||||
return kernel
|
||||
Loading…
Add table
Add a link
Reference in a new issue