mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-16 17:31:24 +01:00
Merge pull request #1211 from Azgaar/ollama
Ollama: local AI text generation
This commit is contained in:
commit
d9391d6d97
3 changed files with 57 additions and 16 deletions
11
index.html
11
index.html
|
|
@ -4980,11 +4980,16 @@
|
||||||
</label>
|
</label>
|
||||||
<label for="aiGeneratorKey"
|
<label for="aiGeneratorKey"
|
||||||
>Key:
|
>Key:
|
||||||
<input id="aiGeneratorKey" placeholder="Enter API key" class="icon-key" />
|
<input
|
||||||
|
id="aiGeneratorKey"
|
||||||
|
placeholder="Enter API key"
|
||||||
|
class="icon-key"
|
||||||
|
data-tip="Enter API key. Note: the Generator doesn't store the key or any generated data"
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
id="aiGeneratorKeyHelp"
|
id="aiGeneratorKeyHelp"
|
||||||
class="icon-help-circled"
|
class="icon-help-circled"
|
||||||
data-tip="Open provider's website to get the API key there. Note: the Map Genenerator doesn't store the key or any generated data"
|
data-tip="Click to see the usage instructions"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -8138,7 +8143,7 @@
|
||||||
<script defer src="modules/ui/burg-editor.js?v=1.106.6"></script>
|
<script defer src="modules/ui/burg-editor.js?v=1.106.6"></script>
|
||||||
<script defer src="modules/ui/units-editor.js?v=1.104.0"></script>
|
<script defer src="modules/ui/units-editor.js?v=1.104.0"></script>
|
||||||
<script defer src="modules/ui/notes-editor.js?v=1.107.3"></script>
|
<script defer src="modules/ui/notes-editor.js?v=1.107.3"></script>
|
||||||
<script defer src="modules/ui/ai-generator.js?v=1.105.22"></script>
|
<script defer src="modules/ui/ai-generator.js?v=1.108.8"></script>
|
||||||
<script defer src="modules/ui/diplomacy-editor.js?v=1.99.00"></script>
|
<script defer src="modules/ui/diplomacy-editor.js?v=1.99.00"></script>
|
||||||
<script defer src="modules/ui/zones-editor.js?v=1.105.20"></script>
|
<script defer src="modules/ui/zones-editor.js?v=1.105.20"></script>
|
||||||
<script defer src="modules/ui/burgs-overview.js?v=1.105.15"></script>
|
<script defer src="modules/ui/burgs-overview.js?v=1.105.15"></script>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ const PROVIDERS = {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
keyLink: "https://console.anthropic.com/account/keys",
|
keyLink: "https://console.anthropic.com/account/keys",
|
||||||
generate: generateWithAnthropic
|
generate: generateWithAnthropic
|
||||||
|
},
|
||||||
|
ollama: {
|
||||||
|
keyLink: "https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Ollama-text-generation",
|
||||||
|
generate: generateWithOllama
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -18,11 +22,16 @@ const MODELS = {
|
||||||
"chatgpt-4o-latest": "openai",
|
"chatgpt-4o-latest": "openai",
|
||||||
"gpt-4o": "openai",
|
"gpt-4o": "openai",
|
||||||
"gpt-4-turbo": "openai",
|
"gpt-4-turbo": "openai",
|
||||||
"o1-preview": "openai",
|
o3: "openai",
|
||||||
"o1-mini": "openai",
|
"o3-mini": "openai",
|
||||||
|
"o3-pro": "openai",
|
||||||
|
"o4-mini": "openai",
|
||||||
|
"claude-opus-4-20250514": "anthropic",
|
||||||
|
"claude-sonnet-4-20250514": "anthropic",
|
||||||
"claude-3-5-haiku-latest": "anthropic",
|
"claude-3-5-haiku-latest": "anthropic",
|
||||||
"claude-3-5-sonnet-latest": "anthropic",
|
"claude-3-5-sonnet-latest": "anthropic",
|
||||||
"claude-3-opus-latest": "anthropic"
|
"claude-3-opus-latest": "anthropic",
|
||||||
|
"ollama (local models)": "ollama"
|
||||||
};
|
};
|
||||||
|
|
||||||
const SYSTEM_MESSAGE = "I'm working on my fantasy map.";
|
const SYSTEM_MESSAGE = "I'm working on my fantasy map.";
|
||||||
|
|
@ -76,10 +85,36 @@ async function generateWithAnthropic({key, model, prompt, temperature, onContent
|
||||||
await handleStream(response, getContent);
|
await handleStream(response, getContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function generateWithOllama({key, model, prompt, temperature, onContent}) {
|
||||||
|
const ollamaModelName = key; // for Ollama, 'key' is the actual model name entered by the user
|
||||||
|
|
||||||
|
const response = await fetch("http://localhost:11434/api/generate", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {"Content-Type": "application/json"},
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: ollamaModelName,
|
||||||
|
prompt,
|
||||||
|
system: SYSTEM_MESSAGE,
|
||||||
|
options: {temperature},
|
||||||
|
stream: true
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const getContent = json => {
|
||||||
|
if (json.response) onContent(json.response);
|
||||||
|
};
|
||||||
|
|
||||||
|
await handleStream(response, getContent);
|
||||||
|
}
|
||||||
|
|
||||||
async function handleStream(response, getContent) {
|
async function handleStream(response, getContent) {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const json = await response.json();
|
let errorMessage = `Failed to generate (${response.status} ${response.statusText})`;
|
||||||
throw new Error(json?.error?.message || "Failed to generate");
|
try {
|
||||||
|
const json = await response.json();
|
||||||
|
errorMessage = json.error?.message || json.error || errorMessage;
|
||||||
|
} catch {}
|
||||||
|
throw new Error(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
const reader = response.body.getReader();
|
const reader = response.body.getReader();
|
||||||
|
|
@ -95,13 +130,14 @@ async function handleStream(response, getContent) {
|
||||||
|
|
||||||
for (let i = 0; i < lines.length - 1; i++) {
|
for (let i = 0; i < lines.length - 1; i++) {
|
||||||
const line = lines[i].trim();
|
const line = lines[i].trim();
|
||||||
if (line.startsWith("data: ") && line !== "data: [DONE]") {
|
if (!line) continue;
|
||||||
try {
|
if (line === "data: [DONE]") break;
|
||||||
const json = JSON.parse(line.slice(6));
|
|
||||||
getContent(json);
|
try {
|
||||||
} catch (jsonError) {
|
const parsed = line.startsWith("data: ") ? JSON.parse(line.slice(6)) : JSON.parse(line);
|
||||||
ERROR && console.error(`Failed to parse JSON:`, jsonError, `Line: ${line}`);
|
getContent(parsed);
|
||||||
}
|
} catch (error) {
|
||||||
|
ERROR && console.error("Failed to parse line:", line, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
* Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2
|
* Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const VERSION = "1.108.7";
|
const VERSION = "1.108.8";
|
||||||
if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function");
|
if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function");
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue