Skip to content

Commit 1df1a71

Browse files
authored
Merge pull request #11 from imigueldiaz/technical-parameters
Technical parameters
2 parents c46df6f + 1717bfa commit 1df1a71

File tree

10 files changed

+259
-76
lines changed

10 files changed

+259
-76
lines changed

_locales/en/messages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@
132132
"perplexityTrademarkLabel": {
133133
"message": "Perplexity AI is a trademark of Perplexity AI, Inc.",
134134
"description": "Label for the Perplexity AI trademark."
135+
},
136+
"errorFrequencyPresence": {
137+
"message": "frequencyPenalty and presencePenalty are mutually exclusive.",
138+
"description": "Error message when frequency and presence are not between 0 and 1."
139+
},
140+
"errorTopkTopp": {
141+
"message": "topK and topP are mutually exclusive.",
142+
"description": "Error message when topK and topP are not between 0 and 1."
135143
}
136144

137145
}

_locales/es/messages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,13 @@
132132
"perplexityTrademarkLabel": {
133133
"message": "Perplexity AI es una marca registrada de Perplexity Inc.",
134134
"description": "Etiqueta de marca registrada para Perplexity AI."
135+
},
136+
"errorFrequencyPresence": {
137+
"message": "frequencyPenalty y presencePenalty son mutuamente exclusivos.",
138+
"description": "Mensaje de error para la frecuencia de presencia de la palabra clave."
139+
},
140+
"errorTopkTopp": {
141+
"message": "topK y topP son mutuamente exclusivos.",
142+
"description": "Mensaje de error para topK y topP."
135143
}
136144
}

_locales/fr/messages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,13 @@
132132
"perplexityTrademarkLabel": {
133133
"message": "Perplexity AI est une marque déposée de Perplexity Inc.",
134134
"description": "Libellé pour la marque Perplexity AI."
135+
},
136+
"errorFrequencyPresence": {
137+
"message": "frequencyPenalty et presencePenalty ne peuvent pas être définis en même temps.",
138+
"description": "Message d'erreur pour la fréquence de mots-clés."
139+
},
140+
"errorTopkTopp": {
141+
"message": "top_k et top_p ne peuvent pas être définis en même temps.",
142+
"description": "Message d'erreur pour top_k et top_p."
135143
}
136144
}

background/background.js

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,76 @@
22
* @param {string} apiKey
33
* @param {string} model
44
* @param {number} temperature
5+
* @param {number} topk
6+
* @param {number} topp
7+
* @param {number} frequencyPenalty
8+
* @param {number} presencePenalty
9+
* @param {number} maxTokens
510
* @param {string} content
611
* @param {string} language
712
* @returns {Promise<any>}
813
* Call the Perplexity API with the provided parameters.
914
* Return a promise that resolves with the API response.
1015
*/
11-
function callPerplexityAPI(apiKey, model, temperature, content, language) {
16+
function callPerplexityAPI(apiKey, model, temperature, topk, topp, frequencyPenalty, presencePenalty, maxTokens, content, language) {
17+
const API_ENDPOINT = 'https://api.perplexity.ai/chat/completions';
1218
const systemPrompt = `You are an AI assistant that generates concise, high-quality abstracts and keywords for webpage content.
1319
14-
Instructions:
15-
1. Analyze the provided webpage text and identify the main topics, key points and overall meaning. Take account of the language of the webpage. The ISO code of the language should be detected and if it is not it will be '${language}'.
16-
2. Generate an abstract in the SAME LANGUAGE as the webpage content. This is crucial. If the webpage is in Spanish, the abstract MUST be in Spanish. If the webpage is in French, the abstract MUST be in French, and so on.
17-
3. The abstract should:
18-
- Accurately and concisely summarize the key information in 1-2 paragraphs
19-
- Be well-written, precise and easy to understand
20-
- Contain the most important points without extraneous details
21-
- Be formatted as 1-2 easily readable paragraphs of plain text, each formatted as <p class="abstractp">{paragraph text}</p> WITHOUT MARKDOWN OR SPECIAL CHARACTERS
22-
4. Extract the most relevant keywords from the text that capture the main topics and themes.
23-
5. Format the output as follows, including the abstract and keywords, the final output MUST BE a valid HTML node with NO MARKDOWN at all:
24-
<div class="abstract" lang="{ISO code of the detected language}">{abstract}</div>
25-
<div class="keywords">{foreach keyword in keywords: <span class="keyword">{keyword}</span> }</div>
26-
27-
Begin!`;
20+
Instructions:
21+
1. Analyze the provided webpage text and identify the main topics, key points and overall meaning. Take account of the language of the webpage. The ISO code of the language should be detected and if it is not it will be '${language}'.
22+
2. Generate an abstract in the SAME LANGUAGE as the webpage content. This is crucial. If the webpage is in Spanish, the abstract MUST be in Spanish. If the webpage is in French, the abstract MUST be in French, and so on.
23+
3. The abstract should:
24+
- Accurately and concisely summarize the key information in 1-2 paragraphs
25+
- Be well-written, precise and easy to understand
26+
- Contain the most important points without extraneous details
27+
- Be formatted as 1-2 easily readable paragraphs of plain text, each formatted as <p class="abstractp">{paragraph text}</p> WITHOUT MARKDOWN OR SPECIAL CHARACTERS
28+
4. Extract the most relevant keywords from the text that capture the main topics and themes.
29+
5. Format the output as follows, including the abstract and keywords, the final output MUST BE a valid HTML node with NO MARKDOWN at all:
30+
<div class="abstract" lang="{ISO code of the detected language}">{abstract}</div>
31+
<div class="keywords">{foreach keyword in keywords: <span class="keyword">{keyword}</span> }</div>
2832
33+
Begin!`;
2934

3035
// Set the options for the fetch call
31-
const options = {
36+
let options = {
3237
method: 'POST',
3338
headers: {
3439
accept: 'application/json',
3540
'content-type': 'application/json',
3641
authorization: `Bearer ${apiKey}`
37-
},
38-
body: JSON.stringify({
39-
model: model,
40-
messages: [
41-
{role: 'system', content: systemPrompt},
42-
{role: 'user', content: content}
43-
],
44-
temperature: temperature
45-
})
42+
}
4643
};
4744

48-
return fetch('https://api.perplexity.ai/chat/completions', options)
49-
.then(response => response.json())
50-
.catch(err => console.error(err));
45+
let body = {
46+
model: model,
47+
messages: [
48+
{role: 'system', content: systemPrompt},
49+
{role: 'user', content: content}
50+
],
51+
temperature: temperature
52+
};
53+
54+
if (topk !== null) body.top_k = topk;
55+
if (topp !== null) body.top_p = topp;
56+
if (frequencyPenalty !== null) body.frequency_penalty = frequencyPenalty;
57+
if (presencePenalty !== null) body.presence_penalty = presencePenalty;
58+
if (maxTokens !== null) body.max_tokens = maxTokens;
59+
60+
options.body = JSON.stringify(body);
61+
62+
63+
return fetch(API_ENDPOINT, options)
64+
.then(response => response.json())
65+
.catch(err => console.error(err));
5166
}
5267

5368
// Listen for messages from the popup
5469
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
5570
if (message.type === 'CALL_API') {
56-
callPerplexityAPI(message.apiKey, message.model, message.temperature, message.content).then(response => {
71+
callPerplexityAPI(message.apiKey, message.model, message.temperature, message.topk, message.topp, message.frequencyPenalty, message.presencePenalty, message.maxTokens, message.content).then(response => {
5772
sendResponse({data: response});
5873
});
5974
return true; // Return true to indicate async response
6075
}
6176
});
77+

options/options.css

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,23 @@ input[type="number"] {
4444
border-radius: 4px;
4545
margin-bottom: 10px;
4646
}
47-
/* Light Mode */
47+
48+
.input-row {
49+
display: flex;
50+
justify-content: space-between;
51+
margin-bottom: 8px;
52+
}
53+
54+
.input-group {
55+
width: 48%;
56+
}
57+
58+
.button-row {
59+
display: flex;
60+
justify-content: flex-end;
61+
margin-top: 16px;
62+
}
63+
4864
select {
4965
width: 100%;
5066
padding: 8px;

options/options.html

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,58 @@
99
<fieldset role="group" aria-labelledby="api-settings">
1010
<legend id="api-settings"></legend>
1111
<label for="apiKey" id="apiKeyLabel"></label>
12-
<input type="password" id="apiKey" name="apiKey" value="pplx-xxxxxxxxxxx" aria-required="true"><br><br>
13-
<label for="model" id="modelLabel"></label>
14-
<select id="model" name="model" aria-required="true">
15-
<optgroup label="Perplexity Models">
16-
<option value="sonar-small-chat">sonar-small-chat (7B)</option>
17-
<option value="sonar-small-online">sonar-small-online (7B)</option>
18-
<option value="sonar-medium-chat" selected>sonar-medium-chat (8x7B)</option>
19-
<option value="sonar-medium-online">sonar-medium-online (8x7B)</option>
20-
</optgroup>
21-
<optgroup label="Open-Source Models">
22-
<option value="codellama-70b-instruct">codellama-70b-instruct (70B)</option>
23-
<option value="mistral-7b-instruct">mistral-7b-instruct (7B)</option>
24-
<option value="mixtral-8x7b-instruct">mixtral-8x7b-instruct (8x7B)</option>
25-
</optgroup>
26-
</select>
27-
<br><br>
28-
<label for="temperature" id="tempLabel"></label>
29-
<input type="number" id="temperature" name="temperature" value="1" step="0.01" min="0" max="2" aria-required="true"><br><br>
30-
<button type="submit" class="ok" id="save">
31-
<span class="button-text"></span>
32-
<img src="save.svg" width="40" height="40" id="saveImg"/>
33-
</button>
12+
<input type="password" id="apiKey" name="apiKey" value="pplx-xxxxxxxxxxx" aria-required="true"><br>
13+
<label for="model" id="modelLabel"></label>
14+
<select id="model" name="model" aria-required="true">
15+
<optgroup label="Perplexity Models">
16+
<option value="sonar-small-chat">sonar-small-chat (7B)</option>
17+
<option value="sonar-small-online">sonar-small-online (7B)</option>
18+
<option value="sonar-medium-chat" selected>sonar-medium-chat (8x7B)</option>
19+
<option value="sonar-medium-online">sonar-medium-online (8x7B)</option>
20+
</optgroup>
21+
<optgroup label="Open-Source Models">
22+
<option value="codellama-70b-instruct">codellama-70b-instruct (70B)</option>
23+
<option value="mistral-7b-instruct">mistral-7b-instruct (7B)</option>
24+
<option value="mixtral-8x7b-instruct">mixtral-8x7b-instruct (8x7B)</option>
25+
</optgroup>
26+
</select>
27+
28+
<div class="input-row">
29+
<div class="input-group">
30+
<label for="temperature" id="tempLabel"></label>
31+
<input type="number" id="temperature" name="temperature" value="1" step="0.01" min="0" max="2" aria-required="true">
32+
</div>
33+
<div class="input-group">
34+
<label for="maxTokens" id="maxTokensLabel">Max Tokens</label>
35+
<input type="number" id="maxTokens" name="maxTokens" value="" step="1" min="1" max="2048" aria-required="true">
36+
</div>
37+
</div>
38+
<div class="input-row">
39+
<div class="input-group">
40+
<label for="topP" id="topPLabel">Top-p</label>
41+
<input type="number" id="topP" name="topP" value="" step="0.01" min="0" max="1" aria-required="true">
42+
</div>
43+
<div class="input-group">
44+
<label for="topK" id="topKLabel">Top-k</label>
45+
<input type="number" id="topK" name="topK" value="" step="1" min="1" max="2048" aria-required="true">
46+
</div>
47+
</div>
48+
<div class="input-row">
49+
<div class="input-group">
50+
<label for="frequencyPenalty" id="frequencyPenaltyLabel">Frequency penalty</label>
51+
<input type="number" id="frequencyPenalty" name="frequencyPenalty" value="" step="0.1" min="-2" max="2" aria-required="true">
52+
</div>
53+
<div class="input-group">
54+
<label for="presencePenalty" id="presencePenaltyLabel">Presence penalty</label>
55+
<input type="number" id="presencePenalty" name="presencePenalty" value="" step="0.1" min="0" max="2" aria-required="true">
56+
</div>
57+
</div>
58+
<div class="button-row">
59+
<button type="submit" class="ok" id="save">
60+
<span class="button-text"></span>
61+
<img src="save.svg" alt="Save icon" width="20" height="20" id="saveImg"/>
62+
</button>
63+
</div>
3464
</fieldset>
3565
</form>
3666

options/options.js

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,60 @@
1212

1313
function saveOptions(e) {
1414
e.preventDefault(); // Prevent the form from submitting normally
15+
16+
const topk = parseFloatOrDefault(document.querySelector("#topK").value);
17+
const topp = parseFloatOrDefault(document.querySelector("#topP").value);
18+
const frequencyPenalty = parseFloatOrDefault(document.querySelector("#frequencyPenalty").value);
19+
const presencePenalty = parseFloatOrDefault(document.querySelector("#presencePenalty").value);
20+
21+
if (topk !== null && topp !== null) {
22+
console.error("Error: topk and topp are mutually exclusive. Please only set one of them.");
23+
showErrorBadge(browser.i18n.getMessage('errorTopkTopp'));
24+
return;
25+
}
26+
if (frequencyPenalty !== null && presencePenalty !== null) {
27+
console.error("Error: frequencyPenalty and presencePenalty are mutually exclusive. Please only set one of them.");
28+
showErrorBadge(browser.i18n.getMessage('errorFrequencyPresence'))
29+
return;
30+
}
31+
1532
browser.storage.local.set({
1633
apiKey: document.querySelector("#apiKey").value,
1734
model: document.querySelector("#model").value,
18-
temperature: parseFloat(document.querySelector("#temperature").value)
35+
temperature: parseFloatOrDefault(document.querySelector("#temperature").value),
36+
topk: topk,
37+
topp: topp,
38+
frequencyPenalty: frequencyPenalty,
39+
presencePenalty: presencePenalty,
40+
maxTokens: parseFloatOrDefault(document.querySelector("#maxTokens").value),
1941
}).then(() => {
2042
console.log("Settings saved");
2143
showInfoBadge();
2244
}, (error) => {
2345
console.error(`Error saving settings: ${error}`);
24-
showErrorBadge();
46+
showErrorBadge(`Error saving settings: ${error}`);
2547
});
2648
}
2749

50+
function showErrorBadge(message) {
51+
const errorBadge = document.getElementById('saveError');
52+
if (errorBadge) {
53+
errorBadge.textContent = message || browser.i18n.getMessage('saveErrorMessage');
54+
errorBadge.style.opacity = '1';
55+
setTimeout(() => {
56+
errorBadge.style.opacity = '0';
57+
setTimeout(() => errorBadge.remove(), 500);
58+
}, 2000);
59+
}
60+
}
61+
62+
63+
function parseFloatOrDefault(value) {
64+
const parsedValue = parseFloat(value);
65+
return isNaN(parsedValue) ? null : parsedValue;
66+
}
67+
68+
2869
function showInfoBadge() {
2970
const infoBadge = document.getElementById('saveSuccess');
3071
if (infoBadge) {
@@ -37,17 +78,6 @@ function showInfoBadge() {
3778
}
3879
}
3980

40-
function showErrorBadge() {
41-
const errorBadge = document.getElementById('saveError');
42-
if (errorBadge) {
43-
errorBadge.textContent = browser.i18n.getMessage('saveErrorMessage');
44-
errorBadge.style.opacity = '1';
45-
setTimeout(() => {
46-
errorBadge.style.opacity = '0';
47-
setTimeout(() => errorBadge.remove(), 500);
48-
}, 2000);
49-
}
50-
}
5181

5282
/**
5383
* Restore the options to their saved state
@@ -60,6 +90,11 @@ function restoreOptions() {
6090
document.querySelector("#apiKey").value = result.apiKey || 'pplx-xxxxxxxxxxx';
6191
document.querySelector("#model").value = result.model || 'sonar-medium-chat';
6292
document.querySelector("#temperature").value = result.temperature || 1;
93+
document.querySelector("#topK").value = result.topk || '';
94+
document.querySelector("#topP").value = result.topp || '';
95+
document.querySelector("#frequencyPenalty").value = result.frequencyPenalty || '';
96+
document.querySelector("#presencePenalty").value = result.presencePenalty || '';
97+
document.querySelector("#maxTokens").value = result.maxTokens || '';
6398
}
6499

65100
/**
@@ -72,7 +107,7 @@ function restoreOptions() {
72107
console.log(browser.i18n.getMessage('errorLabel') + `: ${error}`);
73108
}
74109

75-
let getting = browser.storage.local.get(["apiKey", "model", "temperature"]);
110+
let getting = browser.storage.local.get(["apiKey", "model", "temperature", "topk", "topp", "frequencyPenalty", "presencePenalty", "maxTokens"]);
76111
getting.then(setCurrentChoice, onError);
77112
}
78113

0 commit comments

Comments
 (0)