1414#include < iostream>
1515#include < nlohmann/json.hpp>
1616#include < string>
17+ #include < sys/stat.h>
1718#include < unordered_set>
1819
1920using json = nlohmann::json;
@@ -58,6 +59,78 @@ namespace xcpp
5859 }
5960 };
6061
62+ class ChatHistory
63+ {
64+ public:
65+ static std::string chat (const std::string& model, const std::string& user, const std::string& cell)
66+ {
67+ return appendAndReadBack (model, user, " \" " + cell + " \" " );
68+ }
69+
70+ static std::string chat (const std::string& model, const std::string& user, const nlohmann::json& cell)
71+ {
72+ return appendAndReadBack (model, user, cell.dump ());
73+ }
74+
75+ static void refresh (const std::string& model)
76+ {
77+ std::string chatHistoryFilePath = model + " _chat_history.txt" ;
78+ std::ofstream out (chatHistoryFilePath, std::ios::out);
79+ }
80+
81+ private:
82+
83+ static std::string appendAndReadBack (const std::string& model, const std::string& user, const std::string& serializedCell)
84+ {
85+ std::string chatHistoryFilePath = model + " _chat_history.txt" ;
86+ std::ofstream out;
87+ bool isEmpty = isFileEmpty (chatHistoryFilePath);
88+
89+ out.open (chatHistoryFilePath, std::ios::app);
90+ if (!out)
91+ {
92+ std::cerr << " Failed to open file for writing chat history for model " << model << std::endl;
93+ return " " ;
94+ }
95+
96+ if (!isEmpty)
97+ {
98+ out << " , " ;
99+ }
100+
101+ if (model == " gemini" )
102+ {
103+ out << " { \" role\" : \" " << user << " \" , \" parts\" : [ { \" text\" : " << serializedCell << " }]}\n " ;
104+ }
105+ else
106+ {
107+ out << " { \" role\" : \" " << user << " \" , \" content\" : " << serializedCell << " }\n " ;
108+ }
109+
110+ out.close ();
111+
112+ return readFileContent (chatHistoryFilePath);
113+ }
114+
115+ static bool isFileEmpty (const std::string& filePath)
116+ {
117+ std::ifstream file (filePath, std::ios::ate); // Open the file at the end
118+ if (!file) // If the file cannot be opened, it might not exist
119+ {
120+ return true ; // Consider non-existent files as empty
121+ }
122+ return file.tellg () == 0 ;
123+ }
124+
125+ static std::string readFileContent (const std::string& filePath)
126+ {
127+ std::ifstream in (filePath);
128+ std::stringstream bufferStream;
129+ bufferStream << in.rdbuf ();
130+ return bufferStream.str ();
131+ }
132+ };
133+
61134 class CurlHelper
62135 {
63136 private:
@@ -132,9 +205,10 @@ namespace xcpp
132205 std::string gemini (const std::string& cell, const std::string& key)
133206 {
134207 CurlHelper curlHelper;
208+ const std::string chatMessage = xcpp::ChatHistory::chat (" gemini" , " user" , cell);
135209 const std::string url = " https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key="
136210 + key;
137- const std::string postData = R"( {"contents": [{"parts":[{"text": " )" + cell + R"( "}]} ]})" ;
211+ const std::string postData = R"( {"contents": [ )" + chatMessage + R"( ]})" ;
138212
139213 std::string response = curlHelper.performRequest (url, postData);
140214
@@ -145,19 +219,21 @@ namespace xcpp
145219 return " " ;
146220 }
147221
222+ const std::string chat = xcpp::ChatHistory::chat (" gemini" , " model" , j[" candidates" ][0 ][" content" ][" parts" ][0 ][" text" ]);
223+
148224 return j[" candidates" ][0 ][" content" ][" parts" ][0 ][" text" ];
149225 }
150226
151227 std::string openai (const std::string& cell, const std::string& key)
152228 {
153229 CurlHelper curlHelper;
154230 const std::string url = " https://api.openai.com/v1/chat/completions" ;
231+ const std::string chatMessage = xcpp::ChatHistory::chat (" openai" , " user" , cell);
155232 const std::string postData = R"( {
156- "model": "gpt-3.5-turbo-16k",
157- "messages": [{"role": "user", "content": ")"
158- + cell + R"( "}],
159- "temperature": 0.7
160- })" ;
233+ "model": "gpt-3.5-turbo-16k",
234+ "messages": [)" + chatMessage + R"( ],
235+ "temperature": 0.7
236+ })" ;
161237 std::string authHeader = " Authorization: Bearer " + key;
162238
163239 std::string response = curlHelper.performRequest (url, postData, authHeader);
@@ -170,6 +246,8 @@ namespace xcpp
170246 return " " ;
171247 }
172248
249+ const std::string chat = xcpp::ChatHistory::chat (" openai" , " assistant" , j[" choices" ][0 ][" message" ][" content" ]);
250+
173251 return j[" choices" ][0 ][" message" ][" content" ];
174252 }
175253
@@ -192,11 +270,15 @@ namespace xcpp
192270 return ;
193271 }
194272
195- APIKeyManager api;
196273 if (tokens[2 ] == " --save-key" )
197274 {
198275 xcpp::APIKeyManager::saveApiKey (model, cell);
199276 return ;
277+ }
278+ else if (tokens[2 ] == " --refresh" )
279+ {
280+ xcpp::ChatHistory::refresh (model);
281+ return ;
200282 }
201283
202284 std::string key = xcpp::APIKeyManager::loadApiKey (model);
0 commit comments