Creating Custom Skills in Pymirokai
Pymirokai allows you to create custom skills to enhance its capabilities according to your needs.
How to Create a Custom Skill
1. Use the @custom_skill Decorator
The @custom_skill decorator is required to register the function as a valid skill.
2. Define Access Level
Specify who can use the skill with the access_level parameter.
3. Describe the Skill for Natural Language Interaction
To allow natural triggering of the skill, define verbal_descriptions with example phrases in multiple languages.
Example:
verbal_descriptions={
"en": ["find rhymes", "words that rhyme", "rhyme finder"],
"fr": ["trouver des rimes", "mots qui riment", "rime"],
}
4. Define Input Parameters
Each parameter must be described so the LLM understands what values to provide.
Example:
parameters=[
ParameterDescription(name="word", description="The word to find rhymes for."),
ParameterDescription(name="max_results", description="Maximum number of rhymes to retrieve."),
]
5. Use Proper Function Signatures
Include type annotations for all parameters.
If interacting with Pymirokai’s built-in functions, add
robotas a parameter.
Correct:
async def fetch_rhymes(robot: Robot, word: str, max_results: int = 5, timeout: int = 5) -> dict:
Incorrect (missing type annotations):
async def fetch_rhymes(word, max_results=5, timeout=5): # Incorrect
6. Interacting with the Robot
If your skill interacts with Pymirokai functionalities, include the robot parameter:
async def fetch_rhymes(robot: Robot, word: str, max_results: int = 5, timeout: int = 5) -> dict:
This allows using robot actions such as:
await robot.wave().completed() # Make the robot wave
await robot.say("Here are some rhymes!") # Make the robot speak
7. Returning the Response
A skill can return:
Nothing
A string
A list
A dictionary
Or anything else that is JSON-serializable
However, if you want the LLM to reformulate the response, you must return a dictionary with the key "llm_output".
✅ Correct Example (LLM can process and reformulate):
return {"llm_output": "Words that rhyme with 'fun': sun, run, gun, bun, pun."}
❌ Incorrect Example for LLM: (LLM won’t reformulate)
return "Words that rhyme with 'fun': sun, run, gun, bun, pun." # Just a string
Example: Fetch Rhymes Skill
Here is a complete example of a skill that finds rhyming words for a given input.
graph TD;
A["User request"] --> B["Skill receives input"];
B --> C["Fetch rhymes from API"];
C -->|"Success"| D["Extract API response"];
C -->|"Failure"| E["Handle error and output"];
D --> F["Format response"];
F --> G["Robot announces rhymes"];
G --> H["Return structured response"];
E --> H;
import requests
from pymirokai.decorators.skill import custom_skill, ParameterDescription
from pymirokai.enums.enums import AccessLevel
@custom_skill(
access_level=AccessLevel.USER, # Defines access level for the skill
verbal_descriptions={
"en": ["find rhymes", "words that rhyme", "rhyme finder"],
"fr": ["trouver des rimes", "mots qui riment", "rime"],
},
parameters=[
ParameterDescription(name="word", description="The word to find rhymes for."),
ParameterDescription(name="max_results", description="Maximum number of rhymes to retrieve."),
],
)
async def fetch_rhymes(robot: Robot, word: str, max_results: int = 5, timeout: int = 5) -> dict:
"""Fetch words that rhyme with the given input word.
Args:
robot (Robot): The robot instance to interact with.
word (str): The word to find rhymes for.
max_results (int, optional): The maximum number of rhyming words to retrieve. Defaults to 5.
timeout (int, optional): The timeout duration for the API request in seconds. Defaults to 5.
Returns:
dict: A dictionary containing the response output for the robot to announce.
"""
try:
# Fetch rhymes from the Datamuse API
url = f"https://api.datamuse.com/words?rel_rhy={word}&max={max_results}"
response = requests.get(url, timeout=timeout)
response.raise_for_status()
rhyme_data = response.json()
if rhyme_data:
rhymes = [entry["word"] for entry in rhyme_data]
answer = f"Words that rhyme with '{word}': {', '.join(rhymes)}"
else:
answer = f"No rhymes found for '{word}'."
except requests.RequestException:
answer = "Couldn't fetch rhymes at this moment."
await robot.play_face_reaction("amused").completed()
return {"llm_output": answer} # if you want the LLM to reformulate the answer
Final Notes
Ensure all arguments have type annotations.
If using
robot, it must be included as a parameter.Properly define verbal descriptions and parameter descriptions for better integration.