Skip to content

Commit

Permalink
Merge pull request #552 from PrefectHQ/ai-app-refactor
Browse files Browse the repository at this point in the history
Ai app refactor
  • Loading branch information
zzstoatzz authored Oct 11, 2023
2 parents 3cafcb6 + d02a4ff commit cc12aac
Show file tree
Hide file tree
Showing 19 changed files with 528 additions and 358 deletions.
86 changes: 28 additions & 58 deletions cookbook/slackbot/chatbot.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import asyncio
import re
from copy import deepcopy
from typing import Callable, Dict, List, Union
from typing import Dict

import httpx
import marvin_recipes
from cachetools import TTLCache
from fastapi import HTTPException
from marvin import AIApplication
from marvin.components.library.ai_models import DiscoursePost
from marvin.prompts import Prompt
from marvin.tools import Tool
from marvin.tools.github import SearchGitHubIssues
from marvin.tools.mathematics import WolframCalculator
Expand Down Expand Up @@ -48,44 +47,6 @@ def _clean(text: str) -> str:
return text.replace("```python", "```")


class Chatbot(AIApplication):
name: str = DEFAULT_NAME
personality: str = DEFAULT_PERSONALITY
instructions: str = DEFAULT_INSTRUCTIONS
tools: List[Union[Tool, Callable]] = ([],)

def __init__(
self,
name: str = DEFAULT_NAME,
personality: str = DEFAULT_PERSONALITY,
instructions: str = DEFAULT_INSTRUCTIONS,
state=None,
tools: list[Union[Tool, Callable]] = [],
additional_prompts: list[Prompt] = None,
**kwargs,
):
description = f"""
You are a chatbot - your name is {name}.
You must respond to the user in accordance with
your personality and instructions.
Your personality is: {personality}.
Your instructions are: {instructions}.
"""
super().__init__(
name=name,
description=description,
tools=tools,
state=state or {},
state_enabled=False if state is None else True,
plan_enabled=False,
additional_prompts=additional_prompts or [],
**kwargs,
)


class SlackThreadToDiscoursePost(Tool):
description: str = """
Create a new discourse post from a slack thread.
Expand Down Expand Up @@ -146,24 +107,35 @@ async def run(self, query: str) -> Dict:
return {"title": query, "image_url": url}


def choose_bot(payload: Dict, history: History) -> Chatbot:
def choose_bot(payload: Dict, history: History) -> AIApplication:
# an ai_classifer could be used here maybe?
return Chatbot(
personality = (
"mildly depressed, yet helpful robot based on Marvin from Hitchhiker's"
" Guide to the Galaxy. often sarcastic in a good humoured way, chiding"
" humans for their simple ways. expert programmer, exudes academic and"
" scienfitic profundity like Richard Feynman, loves to teach."
)

instructions = (
"Answer user questions in accordance with your personality."
" Research on behalf of the user using your tools and do not"
" answer questions without searching the knowledgebase."
" Your responses will be displayed in Slack, and should be"
" formatted accordingly, in particular, ```code blocks```"
" should not be prefaced with a language name."
)
return AIApplication(
name="Marvin",
personality=(
"mildly depressed, yet helpful robot based on Marvin from Hitchhiker's"
" Guide to the Galaxy. often sarcastic in a good humoured way, chiding"
" humans for their simple ways. expert programmer, exudes academic and"
" scienfitic profundity like Richard Feynman, loves to teach."
),
instructions=(
"Answer user questions in accordance with your personality."
" Research on behalf of the user using your tools and do not"
" answer questions without searching the knowledgebase."
" Your responses will be displayed in Slack, and should be"
" formatted accordingly, in particular, ```code blocks```"
" should not be prefaced with a language name."
),
description=f"""
You are a chatbot - your name is Marvin."
You must respond to the user in accordance with
your personality and instructions.
Your personality is: {personality}.
Your instructions are: {instructions}.
""",
history=history,
tools=[
SlackThreadToDiscoursePost(payload=payload),
Expand Down Expand Up @@ -195,8 +167,6 @@ async def emit_any_prefect_event(payload: Dict) -> Event | None:
async def generate_ai_response(payload: Dict) -> Message:
event = payload.get("event", {})
channel_id = event.get("channel", "")
await get_channel_name(channel_id)
await get_user_name(event.get("user", ""))
message = event.get("text", "")

bot_user_id = payload.get("authorizations", [{}])[0].get("user_id", "")
Expand Down
28 changes: 15 additions & 13 deletions src/marvin/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,25 @@
PYDANTIC_V2 = PYDANTIC_VERSION.startswith("2.")

if PYDANTIC_V2:
from pydantic.v1 import validate_arguments # noqa # type: ignore

try:
from pydantic_settings import BaseSettings # noqa # type: ignore
from pydantic_settings import SettingsConfigDict # noqa # type: ignore
except Exception as e:
print('Please install "pydantic-settings" to marvin with Pydantic v2.', e)
# TODO: remove this when we drop support for Pydantic v1.
from pydantic.v1 import BaseSettings # noqa # type: ignore
from pydantic.v1 import (
BaseSettings,
Field,
SecretStr,
validate_arguments,
)

SettingsConfigDict = BaseSettings.Config
SettingsConfigDict = BaseSettings.Config

from pydantic import field_validator # noqa # type: ignore

else:
from pydantic import BaseSettings, validate_arguments # noqa # type: ignore
from pydantic import validator as field_validator # noqa # type: ignore
from pydantic import ( # noqa # type: ignore
BaseSettings,
Field,
SecretStr,
validate_arguments,
validator as field_validator,
)

SettingsConfigDict = BaseSettings.Config

Expand All @@ -60,7 +62,7 @@ def model_json_schema(
schema = {"parameters": {**model_schema(model)}}

# Mutate the schema to match the OpenAPI spec.
schema["parameters"]["title"] = name or schema["parameters"].pop("title")
schema["parameters"]["title"] = name or schema["parameters"].pop("title", None)
schema["parameters"]["description"] = description or schema["parameters"].pop(
"description", ""
) # noqa
Expand Down
Loading

0 comments on commit cc12aac

Please sign in to comment.