Untitled

 avatar
unknown
plain_text
23 days ago
4.3 kB
4
Indexable
from typing import List
from pydantic import BaseModel, Field

# Pydantic model for email creation
class EmailCreation(BaseModel):
    """
    Model for capturing the necessary details to compose and send an email.

    Attributes:
        to (List[str]): List of primary recipients.
        cc (List[str]): List of optional CC recipients.
        email_subject (str): Subject of the email.
        email_body (str): Main body (reply content) of the email.
    """
    to: List[str] = Field(description="List of email addresses for primary recipients.")
    cc: List[str] = Field(description="List of email addresses for CC recipients (optional).")
    email_subject: str = Field(description="Subject of the email.")
    email_body: str = Field(description="Main body of the email.")

@tool
def create_email_tool(user_query, state: Annotated[dict, InjectedState], config: RunnableConfig) -> str:
    """
    Tool that composes a new email once the user has confirmed all required details.

    This tool:
    1. Parses the user's conversation and extracts four keys for email composition:
       "to", "cc", "email_subject", and "email_body".
    2. Ensures any missing or ambiguous data (e.g., no recipients, unspecified subject) 
       can be handled or clarified by the user prior to finalizing the email.
    3. Returns or utilizes the parsed details to create the final email payload for sending.

    Args:
        user_query (str): The user's request to compose or send an email.
        state (dict): The current conversation state, which includes relevant messages.
        config (RunnableConfig): Configuration details (e.g., auth tokens, if needed),
                                 though no initial API call is made here.

    Returns:
        str: A response reflecting the status of the composed email request 
             or containing parsed email details.
    """

    # Example LLM and JSON parser setup (adjust as needed for your environment)
    llm = model_categories["l_model"]
    parser = JsonOutputParser(pydantic_object=EmailCreation)

    # Prompt template focusing on extracting the four required fields:
    # 1. "to"
    # 2. "cc"
    # 3. "email_subject"
    # 4. "email_body"
    email_creation_prompt = PromptTemplate(
        template="""
        You are a system that parses a user's request to create and send an email: {query}
        based on the conversation {conversation_history}.

        You must return valid JSON with these exact keys:
        1. "to" (a list of email addresses)
        2. "cc" (a list of email addresses, can be empty if no CC)
        3. "email_subject"
        4. "email_body"

        Requirements:
        - If the user did not provide any "to" addresses, you must still output "to" as an empty list.
        - If the user did not mention CC, output "cc" as an empty list.
        - If "email_subject" was not provided, generate one based on the conversation.
        - If "email_body" was not provided, generate a brief body based on the conversation.

        No additional keys beyond these four should be in your output.

        {format_instructions}
        """,
        input_variables=["query", "conversation_history"],
        partial_variables={"format_instructions": parser.get_format_instructions()},
    )

    chain = email_creation_prompt | llm | parser

    # Invoke the chain to parse user input into the defined EmailCreation schema
    response = chain.invoke({
        "query": user_query,
        "conversation_history": state["messages"],
    })

    # Construct the email payload for sending (if you choose to call an API here).
    # For demonstration, we'll just create a JSON payload and return it.
    email_details_payload = json.dumps({
        "to": response["to"],
        "cc": response["cc"],
        "subject": response["email_subject"],
        "reply_content": response["email_body"],
        # Additional fields can be added as needed (e.g., attachments)
    }, indent=2)

    # If you do not wish to make an actual API call in this tool, simply return the payload 
    # or a success message. Below is an example that just returns the constructed payload.
    return f"Email details successfully parsed:\n{email_details_payload}"
Leave a Comment