1
+ {-# LANGUAGE QuasiQuotes #-}
1
2
{-# LANGUAGE ViewPatterns #-}
2
3
3
4
-- | A bot for general interactions with OpenAI's GPT LLM.
10
11
--------------------------------------------------------------------------------
11
12
12
13
import CofreeBot.Bot
14
+ import CofreeBot.Utils ((...) )
13
15
import CofreeBot.Utils.ListT (emptyListT )
14
16
import Control.Monad.IO.Class (MonadIO (.. ))
15
17
import Control.Monad.Reader (ReaderT (.. ), ask )
@@ -19,32 +21,63 @@ import Data.Text (Text)
19
21
import Data.Text qualified as T
20
22
import Data.Vector qualified as V
21
23
import OpenAI.Client qualified as OpenAI
24
+ import Text.QuasiText qualified as QT
22
25
23
26
--------------------------------------------------------------------------------
24
27
25
- openAIBot :: Bot (ReaderT OpenAI. OpenAIClient IO ) () Text Text
28
+ data Interaction = Interaction { prompt :: Text , completion :: Text }
29
+ deriving (Show , Read )
30
+
31
+ prettyInteraction :: Interaction -> Text
32
+ prettyInteraction Interaction {.. } =
33
+ [QT. embed |
34
+ User: $prompt
35
+ Cofree-bot: $completion
36
+
37
+ |]
38
+
39
+ prettyHistory :: [Interaction ] -> Text
40
+ prettyHistory = foldMap prettyInteraction
41
+
42
+ openAIBot :: Bot (ReaderT OpenAI. OpenAIClient IO ) [Interaction ] Text Text
26
43
openAIBot =
27
44
contraMapMaybeBot (either (const Nothing ) Just . parseOnly openAIBotParser) $
28
- Bot $ \ () (buildPrompt -> i) -> do
45
+ Bot $ \ history i -> do
46
+ let prompt = buildPrompt i history
29
47
client <- lift ask
30
- liftIO (callOpenAI client i ) >>= \ case
48
+ liftIO (callOpenAI client prompt ) >>= \ case
31
49
Left err -> liftIO (print err) >> emptyListT
32
50
Right OpenAI. TextCompletion {tcChoices} ->
33
51
let OpenAI. TextCompletionChoice {.. } = V. head tcChoices
34
- in pure (T. strip tccText, () )
52
+ response = T. strip tccText
53
+ in pure (response, Interaction i response : history)
35
54
36
55
runOpenAIBot :: Functor m => r -> Bot (ReaderT r m ) s i o -> Bot m s i o
37
56
runOpenAIBot r bot = hoistBot (`runReaderT` r) bot
38
57
39
58
callOpenAI :: OpenAI. OpenAIClient -> OpenAI. TextCompletionCreate -> IO (Either OpenAI. ClientError OpenAI. TextCompletion )
40
59
callOpenAI client i = OpenAI. completeText client (OpenAI. EngineId " text-davinci-003" ) (i {OpenAI. tccrMaxTokens = Just 2096 })
41
60
42
- buildPrompt :: Text -> OpenAI. TextCompletionCreate
43
- buildPrompt input =
44
- let preamble = " You are a friendly chat bot named Cofree-Bot on a server dedicated to functional programming. Please respond to the following prompt:"
45
- in OpenAI. defaultTextCompletionCreate $ preamble <> input
61
+ preamble :: Text -> [Interaction ] -> Text
62
+ preamble prompt (prettyHistory -> history) =
63
+ [QT. embed |
64
+ Chat History:
65
+ ```
66
+ $history
67
+ ```
68
+
69
+ You are a friendly chat bot named Cofree-Bot on a server dedicated to functional programming.
70
+ Given the Chat History defined above, please respond to the following prompt, but do not prepend your statmements with your name:
71
+
72
+ ```
73
+ $prompt
74
+ ```
75
+ |]
76
+
77
+ buildPrompt :: Text -> [Interaction ] -> OpenAI. TextCompletionCreate
78
+ buildPrompt = OpenAI. defaultTextCompletionCreate ... preamble
46
79
47
80
openAIBotParser :: Parser Text
48
81
openAIBotParser = do
49
- _ <- " chat: "
82
+ -- _ <- "chat: "
50
83
T. pack <$> many1 anyChar
0 commit comments