forked from ubiquity/ubiquibot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimilarity.ts
More file actions
104 lines (97 loc) · 3.64 KB
/
Copy pathsimilarity.ts
File metadata and controls
104 lines (97 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { getLogger } from "../bindings";
import axios, { AxiosError } from "axios";
import { ajv } from "../utils";
import { Static, Type } from "@sinclair/typebox";
import { backOff } from "exponential-backoff";
import { Issue } from "../types";
export const extractImportantWords = async (issue: Issue): Promise<string[]> => {
const res = await getAnswerFromChatGPT(
"",
`${
process.env.CHATGPT_USER_PROMPT_FOR_IMPORTANT_WORDS ||
"I need your help to find important words (e.g. unique adjectives) from github issue below and I want to parse them easily so please separate them using #(No other contexts needed). Please separate the words by # so I can parse them easily. Please answer simply as I only need the important words. Here is the issue content.\n"
} '${`Issue title: ${issue.title}\nIssue content: ${issue.body}`}'`,
parseFloat(process.env.IMPORTANT_WORDS_AI_TEMPERATURE || "0")
);
if (res === "") return [];
return res.split(/[,# ]/);
};
export const measureSimilarity = async (first: Issue, second: Issue): Promise<number> => {
const res = await getAnswerFromChatGPT(
"",
`${(
process.env.CHATGPT_USER_PROMPT_FOR_MEASURE_SIMILARITY ||
'I have two github issues and I need to measure the possibility of the 2 issues are the same content (I need to parse the % so other contents are not needed and give me only the number in %).\n Give me in number format and add % after the number.\nDo not tell other things since I only need the number (e.g. 85%). Here are two issues:\n 1. "%first%"\n2. "%second%"'
)
.replace("%first%", `Issue title: ${first.title}\nIssue content: ${first.body}`)
.replace("%second%", `Issue title: ${second.title}\nIssue content: ${second.body}`)}`,
parseFloat(process.env.MEASURE_SIMILARITY_AI_TEMPERATURE || "0")
);
const matches = res.match(/\d+/);
const percent = matches && matches.length > 0 ? parseInt(matches[0]) || 0 : 0;
return percent;
};
const ChatMessageSchema = Type.Object({
content: Type.String(),
});
const ChoiceSchema = Type.Object({
message: ChatMessageSchema,
});
const ChoicesSchema = Type.Object({
choices: Type.Array(ChoiceSchema),
});
type Choices = Static<typeof ChoicesSchema>;
export const getAnswerFromChatGPT = async (systemPrompt: string, userPrompt: string, temperature = 0, max_tokens = 1500): Promise<string> => {
const logger = getLogger();
const body = JSON.stringify({
model: "gpt-3.5-turbo",
messages: [
{
role: "system",
content: systemPrompt,
},
{
role: "user",
content: userPrompt,
},
],
max_tokens,
temperature,
stream: false,
});
const config = {
method: "post",
url: `${process.env.OPENAI_API_HOST || "https://api.openai.com"}/v1/chat/completions`,
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json",
},
data: body,
};
try {
const response = await backOff(() => axios(config), {
startingDelay: 6000,
retry: (e: AxiosError) => {
if (e.response && e.response.status === 429) return true;
return false;
},
});
const data: Choices = response.data;
const validate = ajv.compile(ChoicesSchema);
const valid = validate(data);
if (!valid) {
logger.error(`Error occured from OpenAI`);
return "";
}
const { choices: choice } = data;
if (choice.length <= 0) {
logger.error(`No result from OpenAI`);
return "";
}
const answer = choice[0].message.content;
return answer;
} catch (error) {
logger.error(`Getting response from ChatGPT failed: ${error}`);
return "";
}
};