mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-12-27 19:14:52 +03:00
Got asking GPT questions working.
This commit is contained in:
parent
71acb26bbc
commit
33f8257549
@ -1,14 +1,24 @@
|
|||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
|
||||||
module Wasp.Cli.Command.AI.New
|
module Wasp.Cli.Command.AI.New
|
||||||
( new,
|
( new,
|
||||||
|
queryChatGpt,
|
||||||
|
sayHiToChatGpt,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
import Control.Arrow ()
|
import Control.Arrow ()
|
||||||
import Control.Monad.Except (MonadIO (liftIO))
|
import Control.Monad.Except (MonadIO (liftIO))
|
||||||
|
import Data.Aeson ((.=))
|
||||||
|
import qualified Data.Aeson as Aeson
|
||||||
|
import Data.ByteString.UTF8 as BSU
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
|
import GHC.Generics (Generic)
|
||||||
|
import qualified Network.HTTP.Simple as HTTP
|
||||||
import StrongPath (Abs, Dir, Path', fromAbsDir, fromRelFile, relfile, (</>))
|
import StrongPath (Abs, Dir, Path', fromAbsDir, fromRelFile, relfile, (</>))
|
||||||
import StrongPath.Operations ()
|
import StrongPath.Operations ()
|
||||||
import System.Directory (getFileSize, setCurrentDirectory)
|
import System.Directory (getFileSize, setCurrentDirectory)
|
||||||
|
import qualified System.Environment as System.Environment
|
||||||
import qualified Wasp.AppSpec.Valid as ASV
|
import qualified Wasp.AppSpec.Valid as ASV
|
||||||
import Wasp.Cli.Command (Command)
|
import Wasp.Cli.Command (Command)
|
||||||
import Wasp.Cli.Command.Common (findWaspProjectRootDirFromCwd, readWaspCompileInfo)
|
import Wasp.Cli.Command.Common (findWaspProjectRootDirFromCwd, readWaspCompileInfo)
|
||||||
@ -77,8 +87,91 @@ new = do
|
|||||||
aiWriteWaspOperations absWaspProjectDir waspFileContent = do
|
aiWriteWaspOperations absWaspProjectDir waspFileContent = do
|
||||||
error "TODO"
|
error "TODO"
|
||||||
|
|
||||||
sendPromptToGpt :: String -> IO ()
|
-- In general, gpt-3.5-turbo-0301 does not pay strong attention to the system message, and therefore important instructions are often better placed in a user message.
|
||||||
sendPromptToGpt prompt = do
|
|
||||||
-- TODO: https://platform.openai.com/docs/guides/chat/introduction
|
sayHiToChatGpt :: IO ()
|
||||||
-- TODO: https://www.reddit.com/r/haskell/comments/1263sfl/haskellai_stable_package_set_shell_and/ -> also mentions openai-hs and a fork of it which is more up to date it seems.
|
sayHiToChatGpt = do
|
||||||
undefined
|
apiKey <- System.Environment.getEnv "OPENAI_API_KEY"
|
||||||
|
answer <- queryChatGpt apiKey [ChatMessage {role = User, content = "What is 2 + 2?"}]
|
||||||
|
putStrLn answer
|
||||||
|
|
||||||
|
-- TODO: We will need to have this on a server somewhere, not here, if we want to use our API keys.
|
||||||
|
-- If we let them use their API keys then it can be here.
|
||||||
|
queryChatGpt :: String -> [ChatMessage] -> IO String
|
||||||
|
queryChatGpt apiKey requestMessages = do
|
||||||
|
-- TODO: We could try playing with parameters like temperature, max_tokens, ... .
|
||||||
|
let reqBodyJson =
|
||||||
|
Aeson.object
|
||||||
|
[ "model" .= ("gpt-3.5-turbo" :: String),
|
||||||
|
"messages" .= requestMessages
|
||||||
|
]
|
||||||
|
request =
|
||||||
|
HTTP.setRequestHeader "Authorization" [BSU.fromString $ "Bearer " <> apiKey] $
|
||||||
|
HTTP.setRequestBodyJSON reqBodyJson $
|
||||||
|
HTTP.parseRequest_ "POST https://api.openai.com/v1/chat/completions"
|
||||||
|
|
||||||
|
-- TODO: Consider using httpJSONEither here, so I can handle errors better.
|
||||||
|
response <- HTTP.httpJSON request
|
||||||
|
|
||||||
|
-- TODO: I should probably check status code here, confirm it is 200.
|
||||||
|
let responseStatusCode = HTTP.getResponseStatusCode response
|
||||||
|
(chatResponse :: ChatResponse) = HTTP.getResponseBody response
|
||||||
|
putStrLn $ "Response status code:" <> show responseStatusCode
|
||||||
|
putStrLn $ "Response body:" <> show chatResponse
|
||||||
|
|
||||||
|
return $ content $ message $ head $ choices chatResponse
|
||||||
|
|
||||||
|
data ChatResponse = ChatResponse
|
||||||
|
{ id :: !String,
|
||||||
|
object :: !String,
|
||||||
|
created :: !Int,
|
||||||
|
model :: !String,
|
||||||
|
choices :: ![ChatResponseChoice],
|
||||||
|
usage :: !ChatResponseUsage
|
||||||
|
}
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
instance Aeson.FromJSON ChatResponse
|
||||||
|
|
||||||
|
data ChatResponseUsage = ChatResponseUsage
|
||||||
|
{ prompt_tokens :: !Int,
|
||||||
|
completion_tokens :: !Int,
|
||||||
|
total_tokens :: !Int
|
||||||
|
}
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
instance Aeson.FromJSON ChatResponseUsage
|
||||||
|
|
||||||
|
data ChatResponseChoice = ChatResponseChoice
|
||||||
|
{ index :: !Int,
|
||||||
|
message :: !ChatMessage,
|
||||||
|
finish_reason :: !String
|
||||||
|
}
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
instance Aeson.FromJSON ChatResponseChoice
|
||||||
|
|
||||||
|
data ChatMessage = ChatMessage
|
||||||
|
{ role :: !ChatRole,
|
||||||
|
content :: !String
|
||||||
|
}
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
instance Aeson.ToJSON ChatMessage
|
||||||
|
|
||||||
|
instance Aeson.FromJSON ChatMessage
|
||||||
|
|
||||||
|
data ChatRole = User | System | Assistant
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
instance Aeson.ToJSON ChatRole where
|
||||||
|
toJSON User = "user"
|
||||||
|
toJSON System = "system"
|
||||||
|
toJSON Assistant = "assistant"
|
||||||
|
|
||||||
|
instance Aeson.FromJSON ChatRole where
|
||||||
|
parseJSON = Aeson.withText "ChatRole" $ \case
|
||||||
|
"user" -> return User
|
||||||
|
"system" -> return System
|
||||||
|
"assistant" -> return Assistant
|
||||||
|
other -> fail $ "Invalid ChatRole: " <> show other
|
||||||
|
@ -365,6 +365,7 @@ library cli-lib
|
|||||||
exposed-modules:
|
exposed-modules:
|
||||||
Wasp.Cli.Command
|
Wasp.Cli.Command
|
||||||
Wasp.Cli.FileSystem
|
Wasp.Cli.FileSystem
|
||||||
|
Wasp.Cli.Command.AI.New
|
||||||
Wasp.Cli.Command.BashCompletion
|
Wasp.Cli.Command.BashCompletion
|
||||||
Wasp.Cli.Command.Build
|
Wasp.Cli.Command.Build
|
||||||
Wasp.Cli.Command.Call
|
Wasp.Cli.Command.Call
|
||||||
|
Loading…
Reference in New Issue
Block a user