Skip to content

Commit 3efa865

Browse files
authored
Merge pull request #3 from ethmarks/refactor
Refactor JavaScript and update prompts
2 parents 9728170 + ef2c035 commit 3efa865

4 files changed

Lines changed: 446 additions & 426 deletions

File tree

README.md

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
[https://ethmarks.github.io/thessa](https://ethmarks.github.io/thessa)
44

5-
An AI-powered thesaurus that intelligently generates synonyms. Enter any word and discover common alternatives, rare archaisms, and multilingual cognates.
5+
An AI-powered thesaurus that intelligently generates synonyms.
66

77
## What is Thessa?
88

9-
Thessa (derived from "thesaurus") is a vocabulary expansion tool that leverages AI to provide curated synonym enumerations. Unlike traditional thesauruses, Thessa intelligently balances common and esoteric alternatives, making it perfect for anyone seeking to enhance their lexical repertoire.
9+
Thessa (derived from "thesaurus") is an intelligent vocabulary tool that leverages AI to provide relevant synonyms for almost any input. Whether you're trying to mix up your diction, learn new words, or just trying to find that word on the tip of your tongue, Thessa can help.
1010

1111
## Features
1212

1313
- 🤖 **AI-Powered**: Uses [ch.at](https://ch.at/) for free, no-auth AI
14-
- 🌍 **Multilingual Touch**: Always includes a Bulgarian cognate as the 8th synonym
15-
- 📚 **Diverse Vocabulary**: Provides both common and rare, archaic alternatives
14+
- 🧠 **Intelligent Input**: Handles single words, phrases, gibberish, and edge cases
15+
- 🌍 **Diverse Vocabulary**: Provides both common and rare, archaic alternatives
1616
- 🆓 **Free to Use**: No API key required - works out of the box
1717
- 🎨 **Clean Interface**: Minimalist design with smooth interactions
1818
- 📖 **Instant Definitions**: Click any synonym to get AI-generated definitions
@@ -25,11 +25,3 @@ Thessa (derived from "thesaurus") is a vocabulary expansion tool that leverages
2525
2. Type any word into the input box and press the generate button.
2626
3. Thessa will provide an AI-generated definition for a synonym if you click on it. This can be helpful for understanding the nuances in meaning of each synonym.
2727
4. If you double-click a synonym, Thessa will copy it to your clipboard.
28-
29-
## How It Works
30-
31-
### Prompt
32-
33-
Thessa sends carefully crafted prompts to ch.at to generate exactly 8 synonyms:
34-
35-
> Provide a list of diverse English synonyms for "${word}", limited to a maximum of 8. Include some common synonyms as well as rare, esoteric ones. The 8th and final synonym should be in Bulgarian. "${word}" cannot be in your list of synonyms. No repeats. Capitalize the first letter of each synonym. Newline separated. Each line should ONLY include the synonym. NEVER anything other than the synonym on the line. NEVER include parenthesis. Your response should only include the list without any introductory or concluding text. If none, say "No synonyms found for ${word}."

index.html

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<link href="https://fonts.googleapis.com/css2?family=Sen:wght@400;700&display=swap" rel="stylesheet">
99
<link rel="stylesheet" href="https://ethmarks.github.io/css/global.min.css">
1010
<link rel="stylesheet" href="style.css">
11-
<script src="script.js" type="module" defer></script>
1211
<script src="https://ethmarks.github.io/js/ethmarks-components.js" defer></script>
1312
</head>
1413
<body>
@@ -102,8 +101,7 @@ <h3>About Thessa</h3>
102101
<p>Thessa is your AI-powered thesaurus.</p>
103102
<p>
104103
Simply enter a word, and Thessa will provide a curated list of
105-
synonyms, some common substitutes and some rare archaisms. The last
106-
synonym will be a Bulgarian cognate.
104+
synonyms, some common substitutes and some rare archaisms.
107105
</p>
108106
<p>
109107
Click on any synonym to get a concise definition generated by AI.
@@ -124,8 +122,8 @@ <h3>About Thessa</h3>
124122
</p>
125123
</div>
126124
</div>
127-
128-
129125
<ethmarks-footer source="https://github.com/ethmarks/thessa"></ethmarks-footer>
126+
127+
<script src="script.js" type="module"></script>
130128
</body>
131129
</html>

llm.js

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**
2+
* LLM API Module
3+
* Handles all communication with the ch.at API
4+
*/
5+
6+
const API_URL = "https://ch.at/v1/chat/completions";
7+
8+
/**
9+
* Makes a chat completion request to the ch.at API
10+
* @param {string} prompt - The prompt to send to the API
11+
* @returns {Promise<string>} - The API response text
12+
* @throws {Error} - Throws error with message and optional httpStatus property
13+
*/
14+
async function llm(prompt) {
15+
const temperature = 0.65;
16+
const maxTokens = 300;
17+
const response = await fetch(API_URL, {
18+
method: "POST",
19+
headers: { "Content-Type": "application/json" },
20+
body: JSON.stringify({
21+
messages: [{ role: "user", content: prompt }],
22+
temperature,
23+
max_tokens: maxTokens,
24+
}),
25+
});
26+
27+
if (!response.ok) {
28+
const errorData = await response
29+
.json()
30+
.catch(() => ({ error: { message: response.statusText } }));
31+
const err = new Error(
32+
errorData.error?.message || `HTTP error ${response.status}`,
33+
);
34+
err.httpStatus = response.status;
35+
throw err;
36+
}
37+
38+
const data = await response.json();
39+
const textResponse = data.choices?.[0]?.message?.content;
40+
41+
if (!textResponse) {
42+
throw new Error("Could not parse response from API");
43+
}
44+
45+
return textResponse;
46+
}
47+
48+
export async function getSynonyms(word, count = 8) {
49+
const prompt = `You are a sophisticated thesaurus that provides ${count} diverse alternatives for any input.
50+
51+
Input: "${word}"
52+
53+
Instructions:
54+
1. If the input is a SINGLE WORD:
55+
- Provide ${count} diverse synonyms
56+
- Mix common everyday words and rare archaic words
57+
58+
<example>
59+
"happy":
60+
Joyful
61+
Elated
62+
Euphoric
63+
Blissful
64+
Cheerful
65+
Content
66+
Jubilant
67+
Exultant
68+
</example>
69+
70+
2. If the input is a PHRASE or MULTIPLE WORDS:
71+
- Provide ${count} synonymous phrases or expressions
72+
73+
<example>
74+
"break down":
75+
Fall apart
76+
Collapse
77+
Deteriorate
78+
Malfunction
79+
Disintegrate
80+
Deconstruct
81+
Breach
82+
Dissolve
83+
</example>
84+
85+
Always return exactly ${count} synonyms, newline separated. Your response will be interpreted by a script, so include only the newline-separated list without any other text. Do not use commas, asterisks, or dashes.`;
86+
87+
return await llm(prompt);
88+
}
89+
90+
export async function getDefinition(word) {
91+
const prompt = `You are a comprehensive dictionary that defines any input intelligently.
92+
93+
Input: "${word}"
94+
95+
Instructions:
96+
1. If the input is a REAL WORD:
97+
- Provide (part of speech) followed by concise definition
98+
- For multiple meanings, separate with semicolons
99+
- Use clear, accessible language
100+
101+
2. If the input is a PHRASE:
102+
- Provide (phrase) followed by explanation of meaning/usage
103+
- Focus on the overall concept or idiom meaning
104+
105+
Examples:
106+
"bank" → "(noun) A financial institution; the edge of a river"
107+
"sprint" → "(verb) To run at full speed over a short distance; (noun) A short, fast run"
108+
"break down" → "(phrase) To stop functioning; to analyze in detail"
109+
110+
Return only the definition without introductory text.`;
111+
112+
return await llm(prompt);
113+
}
114+
115+
export function formatError(error) {
116+
if (
117+
error.name === "TypeError" &&
118+
error.message.toLowerCase().includes("fetch")
119+
) {
120+
return "Network error. Please check your internet connection.";
121+
}
122+
123+
if (error.httpStatus) {
124+
return `API Error (${error.httpStatus}): ${error.message}`;
125+
}
126+
127+
return `Error: ${error.message || "Unknown API error."}`;
128+
}

0 commit comments

Comments
 (0)