Skip to content

Commit 90cac26

Browse files
committed
refactor(ai-formatter): add performance logging for model responses
1 parent f05c587 commit 90cac26

File tree

1 file changed

+132
-45
lines changed

1 file changed

+132
-45
lines changed

src/utils/ai-formatter.js

Lines changed: 132 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ import { execSync } from "child_process";
22
import fetch from "node-fetch";
33
import { CohereClient } from "cohere-ai";
44
import dotenv from "dotenv";
5+
import fs from "fs/promises";
6+
import path from "path";
57

68
// Load environment variables
79
dotenv.config();
810

911
const DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions";
12+
const PERFORMANCE_LOG_FILE = "model_performance.jsonl";
1013

1114
// Initialize Cohere client if API key is available
1215
let cohereClient = null;
@@ -16,67 +19,131 @@ if (process.env.COHERE_API_KEY) {
1619
});
1720
}
1821

22+
const logPerformance = async (data) => {
23+
try {
24+
const logEntry = {
25+
...data,
26+
timestamp: new Date().toISOString(),
27+
git_hash: execSync("git rev-parse HEAD").toString().trim(),
28+
files_changed: execSync("git diff --staged --name-only")
29+
.toString()
30+
.split("\n")
31+
.filter(Boolean),
32+
};
33+
34+
await fs.appendFile(PERFORMANCE_LOG_FILE, JSON.stringify(logEntry) + "\n");
35+
} catch (error) {
36+
console.error("Failed to log performance:", error);
37+
}
38+
};
39+
1940
const generateWithCohere = async (prompt) => {
2041
if (!cohereClient) {
2142
throw new Error("Cohere API key not configured");
2243
}
2344

24-
const response = await cohereClient.generate({
25-
prompt: prompt,
26-
maxTokens: 50,
27-
temperature: 0.05,
28-
stopSequences: ["\n"],
29-
});
45+
const startTime = Date.now();
46+
try {
47+
const response = await cohereClient.generate({
48+
prompt: prompt,
49+
maxTokens: 50,
50+
temperature: 0.05,
51+
stopSequences: ["\n"],
52+
});
3053

31-
if (!response.generations || response.generations.length === 0) {
32-
throw new Error("No response from Cohere API");
33-
}
54+
if (!response.generations || response.generations.length === 0) {
55+
throw new Error("No response from Cohere API");
56+
}
57+
58+
const message = response.generations[0].text.trim();
59+
const duration = Date.now() - startTime;
3460

35-
return response.generations[0].text.trim();
61+
await logPerformance({
62+
provider: "cohere",
63+
duration_ms: duration,
64+
success: true,
65+
tokens_used: response.generations[0].tokens || 0,
66+
message,
67+
});
68+
69+
return message;
70+
} catch (error) {
71+
const duration = Date.now() - startTime;
72+
await logPerformance({
73+
provider: "cohere",
74+
duration_ms: duration,
75+
success: false,
76+
error: error.message,
77+
});
78+
throw error;
79+
}
3680
};
3781

3882
const generateWithDeepseek = async (prompt) => {
3983
if (!process.env.DEEPSEEK_API_KEY) {
4084
throw new Error("Deepseek API key not configured");
4185
}
4286

43-
const response = await fetch(DEEPSEEK_API_URL, {
44-
method: "POST",
45-
headers: {
46-
"Content-Type": "application/json",
47-
Authorization: `Bearer ${process.env.DEEPSEEK_API_KEY}`,
48-
},
49-
body: JSON.stringify({
50-
model: "deepseek-chat",
51-
messages: [
52-
{
53-
role: "system",
54-
content:
55-
"You are a commit message generator that follows conventional commit format strictly.",
56-
},
57-
{
58-
role: "user",
59-
content: prompt,
60-
},
61-
],
62-
max_tokens: 50,
63-
temperature: 0.05,
64-
stop: ["\n"],
65-
}),
66-
});
87+
const startTime = Date.now();
88+
try {
89+
const response = await fetch(DEEPSEEK_API_URL, {
90+
method: "POST",
91+
headers: {
92+
"Content-Type": "application/json",
93+
Authorization: `Bearer ${process.env.DEEPSEEK_API_KEY}`,
94+
},
95+
body: JSON.stringify({
96+
model: "deepseek-chat",
97+
messages: [
98+
{
99+
role: "system",
100+
content:
101+
"You are a commit message generator that follows conventional commit format strictly.",
102+
},
103+
{
104+
role: "user",
105+
content: prompt,
106+
},
107+
],
108+
max_tokens: 50,
109+
temperature: 0.05,
110+
stop: ["\n"],
111+
}),
112+
});
67113

68-
if (!response.ok) {
69-
throw new Error(
70-
`Deepseek API error: ${response.status} ${response.statusText}`
71-
);
72-
}
114+
if (!response.ok) {
115+
throw new Error(
116+
`Deepseek API error: ${response.status} ${response.statusText}`
117+
);
118+
}
73119

74-
const data = await response.json();
75-
if (!data.choices || data.choices.length === 0) {
76-
throw new Error("No response from Deepseek API");
77-
}
120+
const data = await response.json();
121+
if (!data.choices || data.choices.length === 0) {
122+
throw new Error("No response from Deepseek API");
123+
}
124+
125+
const message = data.choices[0].message.content.trim();
126+
const duration = Date.now() - startTime;
78127

79-
return data.choices[0].message.content.trim();
128+
await logPerformance({
129+
provider: "deepseek",
130+
duration_ms: duration,
131+
success: true,
132+
tokens_used: data.usage?.total_tokens || 0,
133+
message,
134+
});
135+
136+
return message;
137+
} catch (error) {
138+
const duration = Date.now() - startTime;
139+
await logPerformance({
140+
provider: "deepseek",
141+
duration_ms: duration,
142+
success: false,
143+
error: error.message,
144+
});
145+
throw error;
146+
}
80147
};
81148

82149
export const generateAICommitMessage = async (preferredProvider = "cohere") => {
@@ -145,12 +212,17 @@ export const generateAICommitMessage = async (preferredProvider = "cohere") => {
145212

146213
// Try preferred provider first, then fallback
147214
let message;
215+
let usedFallback = false;
216+
let finalProvider = preferredProvider;
217+
148218
try {
149219
message = await (preferredProvider === "deepseek"
150220
? generateWithDeepseek(prompt)
151221
: generateWithCohere(prompt));
152222
} catch (error) {
153223
console.log(`Failed with ${preferredProvider}, trying fallback...`);
224+
usedFallback = true;
225+
finalProvider = preferredProvider === "deepseek" ? "cohere" : "deepseek";
154226
message = await (preferredProvider === "deepseek"
155227
? generateWithCohere(prompt)
156228
: generateWithDeepseek(prompt));
@@ -171,13 +243,28 @@ export const generateAICommitMessage = async (preferredProvider = "cohere") => {
171243
console.log("Cleaned message:", message);
172244

173245
// Validate the message follows conventional commit format
174-
if (!isValidCommitMessage(message)) {
246+
const isValid = isValidCommitMessage(message);
247+
if (!isValid) {
175248
console.log("\nInvalid message generated:", message);
249+
await logPerformance({
250+
provider: finalProvider,
251+
used_fallback: usedFallback,
252+
message_valid: false,
253+
final_message: message,
254+
validation_error: "Does not follow conventional commit format",
255+
});
176256
throw new Error(
177257
"Generated message does not follow conventional commit format"
178258
);
179259
}
180260

261+
await logPerformance({
262+
provider: finalProvider,
263+
used_fallback: usedFallback,
264+
message_valid: true,
265+
final_message: message,
266+
});
267+
181268
return message;
182269
} catch (error) {
183270
console.error("Error generating AI commit message:", error.message);

0 commit comments

Comments
 (0)