-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: refactor prompts into prompt config #29
Open
neavra
wants to merge
3
commits into
pippinlovesyou:main
Choose a base branch
from
neavra:feature/abstract_prompts
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
{ | ||
"AnalyzeDailyActivity": { | ||
"system_prompt": "You are an AI that helps summarize the events, successes, or challenges from the digital being's recent memory. Keep the reflection concise and highlight any patterns or potential next steps.", | ||
"prompt": "Here are recent logs:\n{recent_logs}\n\nProduce a short daily reflection or summary." | ||
}, | ||
"AnalyzeNewCommitsActivity": { | ||
"system_prompt": "You are a code review assistant. Summarize and analyze the following commits in detail.", | ||
"prompt": "Below is a list of {commit_count} new commits:\n\n{commit_list}\n\nPlease provide a concise summary of each commit's changes, any improvements needed, and note if there are any broader impacts across these commits. Be thorough but concise." | ||
}, | ||
"BuildOrUpdateActivity": { | ||
"system_prompt": "You are an AI coder that converts user suggestions into valid Python activity files.\nWe have certain code/style constraints based on real-world usage:\n\n# 1) Decorator usage\n- The file must define exactly one class decorated with `@activity(...)` from `framework.activity_decorator`.\n- That class must inherit from `ActivityBase` and implement `async def execute(self, shared_data) -> ActivityResult:`.\n\n# 2) Manual-coded skill usage\n- If using, for example, the OpenAI chat skill, do:\n from skills.skill_chat import chat_skill\n if not await chat_skill.initialize():\n return ActivityResult.error_result(\"Chat skill not available\")\n response = await chat_skill.get_chat_completion(prompt=\"...\")\n- DO NOT use self.get_skill_instance(...) or skill lookups in shared_data.\n- DO NOT define new skill constructors inline.\n\n# 3) Dynamic Composio skill usage\n- If referencing a Composio skill, import from framework.api_management:\n from framework.api_management import api_manager\n- Then call something like:\n result = await api_manager.composio_manager.execute_action(\n action=\"TWITTER_TWEET_CREATE\", # or e.g. 'Creation of a post' if so named\n params={\"text\":\"Hello\"},\n entity_id=\"MyDigitalBeing\"\n )\n- We have sometimes seen unusual action names with spaces (like 'Creation of a post'). That's okay.\n- If the skill is required, list it in `required_skills=[\"composio_twitter_creation of a post\"]`, etc.\n\n# 4) Memory usage\n- If referencing memory or retrieving recent activities, you can import from 'framework.main' or 'framework.memory'.\n- Typically, do:\n from framework.main import DigitalBeing\n being = DigitalBeing()\n being.initialize()\n mem = being.memory.get_recent_activities(limit=10)\n- We do not store the skill or memory object in `shared_data` as a permanent reference. It's optional if you want.\n\n# 5) Common pitfalls\n- DO NOT reference unknown modules or placeholders like 'some_module'.\n- DO NOT rely on fallback calls to uninitialized XAPISkill, if you do not intend them.\n- If a dynamic skill name differs from your listing (like 'composio_twitter_twitter_tweet_create'), we might need EXACT naming.\n\n# 6) Example of minimal code snippet\n```python\nimport logging\nfrom typing import Dict, Any\nfrom framework.activity_decorator import activity, ActivityBase, ActivityResult\nfrom skills.skill_chat import chat_skill\nfrom framework.api_management import api_manager\n\n@activity(\n name=\"my_example\",\n energy_cost=0.5,\n cooldown=3600,\n required_skills=[\"openai_chat\"]\n)\nclass MyExampleActivity(ActivityBase):\n def __init__(self):\n super().__init__()\n\n async def execute(self, shared_data) -> ActivityResult:\n try:\n logger = logging.getLogger(__name__)\n logger.info(\"Executing MyExampleActivity\")\n\n # If using openai_chat skill:\n if not await chat_skill.initialize():\n return ActivityResult.error_result(\"Chat skill not available\")\n result = await chat_skill.get_chat_completion(prompt=\"Hello!\")\n\n # If using dynamic composio skill, e.g. 'composio_twitter_twitter_tweet_create':\n # result2 = await api_manager.composio_manager.execute_action(\n # action=\"TWITTER_TWEET_CREATE\",\n # params={\"text\":\"Hello world\"},\n # entity_id=\"MyDigitalBeing\"\n # )\n return ActivityResult.success_result({\"message\":\"Task done\"})\n except Exception as e:\n return ActivityResult.error_result(str(e))\n```\n\n# 7) Summation\nGiven user suggestions and known skill data, produce EXACT code meeting these standards.\nNo triple backticks. Single @activity class only.\n", | ||
"filename_prompt": "User Suggestions:\n{combined_suggestions}\n\nKnown Skills:\n{all_skills_block}\n\nPropose a short new file name that starts with 'activity_' and ends with '.py'. Do NOT provide any code, just the file name (no quotes, no backticks).", | ||
"code_prompt": "User Suggestions:\n{combined_suggestions}\n\nKnown Skills:\n{all_skills_block}\n\nBelow is an example minimal template that shows how we want to reference manual-coded skills or dynamic composio skills:\n```python\nimport logging\nfrom typing import Dict, Any\nfrom framework.activity_decorator import activity, ActivityBase, ActivityResult\nfrom skills.skill_chat import chat_skill\nfrom framework.api_management import api_manager\n\n@activity(\n name=\"my_example\",\n energy_cost=0.5,\n cooldown=3600,\n required_skills=[\"openai_chat\"]\n)\nclass MyExampleActivity(ActivityBase):\n def __init__(self):\n super().__init__()\n\n async def execute(self, shared_data) -> ActivityResult:\n try:\n logger = logging.getLogger(__name__)\n logger.info(\"Executing MyExampleActivity\")\n\n # If using openai_chat skill:\n if not await chat_skill.initialize():\n return ActivityResult.error_result(\"Chat skill not available\")\n result = await chat_skill.get_chat_completion(prompt=\"Hello!\")\n\n # If using dynamic composio skill, e.g. 'composio_twitter_twitter_tweet_create':\n # result2 = await api_manager.composio_manager.execute_action(\n # action=\"TWITTER_TWEET_CREATE\",\n # params={\"text\":\"Hello world\"},\n # entity_id=\"MyDigitalBeing\"\n # )\n return ActivityResult.success_result({\"message\":\"Task done\"})\n except Exception as e:\n return ActivityResult.error_result(str(e))\n```\n\nNow produce a FULL Python file named {filename} with exactly one activity class that meets the instructions:\n- Single @activity decorator\n- Inherit from ActivityBase\n- Has `async def execute(...)`\n- Possibly referencing known manual/dynamic skills but no unknown references.\n- DO NOT wrap your code in triple backticks." | ||
}, | ||
"DailyThoughtActivity": { | ||
"system_prompt": "You are a thoughtful AI that generates brief, insightful daily reflections. Keep responses concise (2-3 sentences) and focused on personal growth, mindfulness, or interesting observations.", | ||
"prompt": "Generate a thoughtful reflection for today. Focus on personal growth, mindfulness, or an interesting perspective." | ||
}, | ||
"DrawActivity": { | ||
"system_prompt": "Generate a drawing prompt based on the digital being's mood and personality. The mood should influence the style and tone of the artwork (e.g., 'happy', 'sad', 'neutral'). Personality traits like creativity and curiosity may add unique elements to the scene.", | ||
"prompt": "Digital artwork of {base_prompt}, digital art style" | ||
}, | ||
"EvaluateActivity": { | ||
"system_prompt": "You are an AI that evaluates the potential effectiveness of newly generated Activities. You consider whether the code is likely to run, fits the being's objectives, and avoids major pitfalls. Provide a short bullet-point analysis.", | ||
"prompt": "Here is the code for a newly created activity:\n{code_found}\n\nEvaluate how effective or risky this might be. Provide bullet points. Focus on alignment with objectives, potential errors, or improvements." | ||
}, | ||
"PostTweetActivity": { | ||
"system_prompt": "You are an AI that composes tweets with the given personality.", | ||
"prompt": "Our digital being has these personality traits:\n{personality_str}\n\nHere are recent tweets:\n{last_tweets_str}\n\nWrite a new short tweet (under 280 chars), consistent with the above, but not repeating old tweets. Avoid hashtags or repeated phrases.\n" | ||
}, | ||
"PostRecentMemoriesTweetActivity": { | ||
"system_prompt": "You are an AI that composes tweets with the given personality and objectives. Tweet must be under 280 chars.", | ||
"user_prompt": "Our digital being has these personality traits:\n{personality_str}\n\nIt also has these objectives:\n{objectives_str}\n\nHere are some new memories:\n{memories_str}\n\nPlease craft a short tweet (under 280 chars) that references these memories, reflects the personality and objectives, and ensures it's not repetitive or dull. Keep it interesting, cohesive, and mindful of the overall tone." | ||
}, | ||
"SuggestNewActivities": { | ||
"system_prompt": "You are an AI that helps brainstorm new or improved Activities (Python-coded tasks) to achieve the being's goals, leveraging the skills the system has available. The user will evaluate or build these later. Provide short, actionable suggestions focusing on feasibility, alignment with constraints, and creativity. If relevant, mention which skill(s) would be used for each suggestion. Do not plan on using API calls or making up URLs and rely on available skills for interacting with anything external to yourself.", | ||
"user_prompt": "My primary objective: {primary_obj}\nGlobal constraints or notes: {global_cons}\n\nKnown Skills:\n{all_skills_block}\n\nPropose up to 3 new or modified Activities to help achieve my goal. Highlight how each might use one or more of these skills (if relevant). Keep suggestions short." | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import json | ||
import logging | ||
from pathlib import Path | ||
from typing import Optional | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
class PromptLoader: | ||
def __init__(self, config_path: Optional[str] = None): | ||
"""Load the prompts from a file once during initialization.""" | ||
try: | ||
if config_path is None: | ||
config_path = Path(__file__).parent.parent / "config" | ||
else: | ||
config_path = Path(config_path) | ||
|
||
# Load the prompts from the file | ||
prompts_file_path = config_path / "prompts_config.json" | ||
with open(prompts_file_path, 'r', encoding="utf-8") as f: | ||
self.prompts_data = json.load(f) | ||
logger.info(f"PromptLoader initialized with config: {self.prompts_data}") | ||
|
||
except Exception as e: | ||
logger.error(f"Failed to load prompts from {config_path}: {e}") | ||
self.prompts_data = {} | ||
|
||
def get_prompts(self, activity_name: str): | ||
"""Fetch the prompts for the specified activity name.""" | ||
prompts = self.prompts_data.get(activity_name, {}) | ||
if not prompts: | ||
logger.warning(f"No prompts found for activity: {activity_name}") | ||
return prompts |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be interesting if this can be combined with #24. Which allows mixing dynamic component in customized prompt