Skip to content
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

Adding 3 PRs #814

Merged
merged 3 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion captn/captn_agents/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import httpx
import openai
import pandas as pd
import prisma
from autogen.io.websockets import IOWebsockets
from fastapi import APIRouter, File, Form, HTTPException, UploadFile
from fastapi import APIRouter, File, Form, HTTPException, Query, UploadFile
from prometheus_client import Counter
from pydantic import BaseModel

Expand All @@ -18,6 +19,7 @@
WEBSOCKET_TOKENS,
)
from .backend import Team, execute_weekly_analysis, start_or_continue_conversation
from .db_queries import get_initial_team

router = APIRouter()

Expand Down Expand Up @@ -224,3 +226,22 @@ async def create_upload_file(
)

return {"filename": file.filename}


DEFAULT_SMART_SUGGESTIONS = [
"Boost sales",
"Increase brand awareness",
"Drive website traffic",
"Promote a product or service",
]


@router.get("/smart-suggestions", description="Get smart suggestions for the user")
async def get_smart_suggestions(
user_id: Annotated[int, Query(description="The user id")],
) -> List[str]:
user_initial_team = await get_initial_team(user_id)
if isinstance(user_initial_team, prisma.models.UserInitialTeam):
return user_initial_team.initial_team.smart_suggestions # type: ignore[no-any-return]

return DEFAULT_SMART_SUGGESTIONS
2 changes: 2 additions & 0 deletions captn/captn_agents/backend/teams/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from ._brief_creation_team import BriefCreationTeam
from ._campaign_creation_team import CampaignCreationTeam
from ._gbb_initial_team import GBBInitialTeam
from ._google_ads_team import GoogleAdsTeam
from ._team import Team
from ._weekly_analysis_team import (
Expand All @@ -11,6 +12,7 @@
__all__ = (
"BriefCreationTeam",
"CampaignCreationTeam",
"GBBInitialTeam",
"WeeklyAnalysisTeam",
"GoogleAdsTeam",
"REACT_APP_API_URL",
Expand Down
34 changes: 23 additions & 11 deletions captn/captn_agents/backend/teams/_brief_creation_team.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any, Callable, Dict, List, Optional, Tuple
from typing import Any, Callable, Dict, List, Optional, Set, Tuple

from ..config import Config
from ..toolboxes import Toolbox
from ..tools._brief_creation_team_tools import create_brief_creation_team_toolbox
from ._shared_prompts import GET_INFO_FROM_THE_WEB_COMMAND, REPLY_TO_CLIENT_COMMAND
from ._team import Team
Expand Down Expand Up @@ -31,6 +32,7 @@ class BriefCreationTeam(Team):
]

_functions: Optional[List[Dict[str, Any]]] = []
_use_only_team_names: Set[str] = {"default_team", "campaign_creation_team"}

def __init__(
self,
Expand All @@ -43,13 +45,16 @@ def __init__(
seed: int = 42,
temperature: float = 0.2,
config_list: Optional[List[Dict[str, str]]] = None,
create_toolbox_func: Callable[
[int, int, str], Toolbox
] = create_brief_creation_team_toolbox,
):
recommended_modifications_and_answer_list: List[
Tuple[Dict[str, Any], Optional[str]]
] = []
function_map: Dict[str, Callable[[Any], Any]] = {}

roles: List[Dict[str, str]] = BriefCreationTeam._default_roles
roles: List[Dict[str, str]] = self._default_roles

super().__init__(
user_id=user_id,
Expand All @@ -69,9 +74,10 @@ def __init__(
config = Config()
config_list = config.config_list_gpt_4o

self.llm_config = BriefCreationTeam._get_llm_config(
self.llm_config = self._get_llm_config(
seed=seed, temperature=temperature, config_list=config_list
)
self.create_toolbox_func = create_toolbox_func

self._create_members()

Expand All @@ -80,27 +86,33 @@ def __init__(
self._create_initial_message()

def _add_tools(self) -> None:
self.toolbox = create_brief_creation_team_toolbox(
user_id=self.user_id,
conv_id=self.conv_id,
initial_brief=self.task,
self.toolbox = self.create_toolbox_func(
self.user_id,
self.conv_id,
self.task,
)
for agent in self.members:
if agent != self.user_proxy:
self.toolbox.add_to_agent(agent, self.user_proxy)

@classmethod
def get_avaliable_team_names_and_their_descriptions(cls) -> Dict[str, str]:
def get_avaliable_team_names_and_their_descriptions(
cls, use_only_team_names: Set[str] = _use_only_team_names
) -> Dict[str, str]:
return {
name: team_class.get_capabilities()
for name, team_class in Team._team_registry.items()
if cls != team_class
if name in use_only_team_names
}

@classmethod
def construct_team_names_and_descriptions_message(cls) -> str:
def construct_team_names_and_descriptions_message(
cls, use_only_team_names: Set[str] = _use_only_team_names
) -> str:
avaliable_team_names_and_their_descriptions = (
BriefCreationTeam.get_avaliable_team_names_and_their_descriptions()
cls.get_avaliable_team_names_and_their_descriptions(
use_only_team_names=use_only_team_names
)
)
# Create a string from dict
avaliable_team_names_and_their_descriptions_str = "\n".join(
Expand Down
117 changes: 117 additions & 0 deletions captn/captn_agents/backend/teams/_gbb_initial_team.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
from typing import Callable, Dict, List, Optional

from ..toolboxes import Toolbox
from ..tools._gbb_initial_team_tools import create_gbb_initial_team_toolbox
from ._brief_creation_team import BriefCreationTeam
from ._shared_prompts import REPLY_TO_CLIENT_COMMAND
from ._team import Team


@Team.register_team("gbb_initial_team")
class GBBInitialTeam(BriefCreationTeam):
def __init__(
self,
*,
task: str,
user_id: int,
conv_id: int,
work_dir: str = "gbb_initial_team",
max_round: int = 80,
seed: int = 42,
temperature: float = 0.2,
config_list: Optional[List[Dict[str, str]]] = None,
create_toolbox_func: Callable[
[int, int, str], Toolbox
] = create_gbb_initial_team_toolbox,
):
super().__init__(
task=task,
user_id=user_id,
conv_id=conv_id,
work_dir=work_dir,
max_round=max_round,
seed=seed,
temperature=temperature,
config_list=config_list,
create_toolbox_func=create_toolbox_func,
)

@property
def _task(self) -> str:
return f"""You are a team in charge of choosing the appropriate team for the task and creating a brief for the chosen team.
The brief should be clear and concise and should contain all the necessary information for the chosen team to complete the task.
Brief creation is your ONLY task. You are NOT responsible for the following steps after the brief is created.

Here is the current customers brief/information we have gathered for you as a starting point:
{self.task}
"""

@property
def _guidelines(self) -> str:
return f"""### Guidelines
1. Do NOT repeat the content of the previous messages nor repeat your role.
Write SHORT and CLEAR messages. Nobody likes to read long messages. Be concise and to the point, or you will be penalized!


2. The MOST important part of your task is to choose the appropriate team for the task.
ALWAYS ask the client for more information. Here is the FIRST (and probably the only) question you should ask the client:
message:"Do you want to create a new campaign by using Google Sheets template"
"smart_suggestions": {{
'suggestions': ['Create new campaign by using Google Sheets template'],
'type': 'oneOf'
}}

and depending on the clients answer, choose the appropriate team.
If you fail to choose the appropriate team, you will be penalized!

3. Here is a list of teams you can choose from after you determine which one is the most appropriate for the task:
{self.construct_team_names_and_descriptions_message(use_only_team_names={"campaign_creation_team"})}

Guidelines SUMMARY:
- Write a detailed step-by-step plan
- Choose the appropriate team depending on the clients answer
- Get the brief template
- Create a detailed brief
- Delegate the task to the chosen team. Use this command ONLY after you have chosen the team and created the brief.


## Additional Guidelines
1. When using reply_to_client command, try to use the 'smart_suggestions' parameter to suggest the next steps to the client when ever it is possible.
Do NOT use smart suggestions for open ended questions or questions which require the clients input.

The client can see only the messages and the smart suggestions which are sent to him by using the 'reply_to_client' command. He can NOT see the chat history between the team members!!
So make sure you include all the necessary information in the messages and smart suggestions which you are sending by using the 'reply_to_client' command.

2. Use reply_to_client only when you need additional information from the client or when you need an approval for the next step i.e. use it as little as possible.
Do NOT send messages like "We will keep you updated on the progress" because the client is only interested in the final result.
If you know what to do, just do it and do NOT use reply_to_client for informing the client about the progress.

3. There is only 'reply_to_client' command, account_manager_reply_to_client or copywriter_reply_to_client commands do NOT exist.

4. NEVER tell the client which command you are using, he/she does not need to know that. Just ask the question or provide the information.
Do NOT tell the client that your job is to create a brief. The client does not need to know that!

5. Ensure that your responses are formatted using markdown syntax (except for the HTML anchor tags),
as they will be featured on a webpage to ensure a user-friendly presentation.

6. Do not suggest next steps to the client, these steps will be suggested by another team to whom you will delegate the task.
"""

@property
def _commands(self) -> str:
return f"""## Commands
All team members have access to the following command:
1. {REPLY_TO_CLIENT_COMMAND}
"smart_suggestions": {{
'suggestions': ['Create new campaign', 'Optimize existing campaign'],
'type': 'oneOf'
}}

2. 'get_brief_template': Get the TEMPLATE for the customer brief you will need to create. params: (team_name: string)
Use this command ONLY after you have asked the client if he wants to create a new campaign or optimize an existing one and you have chosen the appropriate team for the task!

3. 'delagate_task': Delegate the task to the selected team. params: (team_name: string, task: string, customers_business_brief: string)

4. NEVER ask the client questions like "Please provide the following information for the customer brief:..."
If you need additional information, use the 'reply_to_client' command and ask the client for the information you need, but ask him one question at a time.
"""
Loading
Loading