{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} module Main where import Simplex.Chat.Bot import Simplex.Chat.Controller (versionNumber) import Simplex.Chat.Core import Simplex.Chat.Options import Simplex.Chat.Terminal (terminalChatConfig) import System.Directory (getAppUserDataDirectory) import qualified Data.Text as T import qualified Data.Text.Encoding as TE import Network.HTTP.Simple import Data.Aeson import GHC.Generics import qualified Data.ByteString.Lazy as BL import System.Environment (getEnv) import Control.Monad.IO.Class (liftIO) -- Data types for Venice.ai API data ChatMessage = ChatMessage { role :: String , content :: String } deriving (Show, Generic) data ChatRequest = ChatRequest { model :: String , messages :: [ChatMessage] , temperature :: Float } deriving (Show, Generic) data ChatResponse = ChatResponse { choices :: [Choice] } deriving (Show, Generic) data Choice = Choice { message :: ChatMessage } deriving (Show, Generic) instance ToJSON ChatMessage instance ToJSON ChatRequest instance FromJSON ChatMessage instance FromJSON ChatResponse instance FromJSON Choice -- Venice API client function callVeniceAPI :: String -> String -> IO (Maybe String) callVeniceAPI apiKey userMessage = do let request = ChatRequest { model = "venice-model" -- Replace with actual Venice model name , messages = [ChatMessage "user" userMessage] , temperature = 0.7 } let jsonRequest = encode request initReq <- parseRequest "POST https://api.venice.ai/api/v1/chat/completions" let req = setRequestMethod "POST" . setRequestHeader "Content-Type" ["application/json"] . setRequestHeader "Authorization" ["Bearer " <> TE.encodeUtf8 (T.pack apiKey)] . setRequestBodyLBS jsonRequest $ initReq response <- httpLBS req let decoded = decode (getResponseBody response) :: Maybe ChatResponse return $ case decoded of Just chatResponse -> case choices chatResponse of (choice:_) -> Just $ content (message choice) _ -> Nothing Nothing -> Nothing main :: IO () main = do opts <- welcomeGetOpts apiKey <- getEnv "VENICE_API_KEY" simplexChatCore terminalChatConfig opts $ chatBotRepl welcomeMessage $ \_contact msg -> do case words msg of ("/bot":rest) -> do response <- liftIO $ callVeniceAPI apiKey (unwords rest) pure $ case response of Just reply -> reply Nothing -> "Sorry, I couldn't process that request." _ -> pure "" -- Don't respond to messages without the /bot prefix welcomeMessage :: String welcomeMessage = "Hello! I'm a Venice.ai powered chat bot.\nUse /bot followed by your message to talk to me." welcomeGetOpts :: IO ChatOpts welcomeGetOpts = do appDir <- getAppUserDataDirectory "simplex" opts@ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix}} <- getChatOpts appDir "simplex_bot" putStrLn $ "SimpleX Chat Bot v" ++ versionNumber putStrLn $ "db: " <> dbFilePrefix <> "_chat.db, " <> dbFilePrefix <> "_agent.db" pure opts