Add simple user interface
This commit is contained in:
parent
2aad09df7d
commit
f84714a726
@ -1 +1 @@
|
||||
[1751004438] warming up the model with an empty run
|
||||
[1751008457] warming up the model with an empty run
|
||||
|
29
pom.xml
29
pom.xml
@ -1,13 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.pablotj</groupId>
|
||||
<artifactId>ia-chat-boot</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
@ -19,15 +23,26 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot Web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Thymeleaf template engine -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- llama-java (IA offline) -->
|
||||
<dependency>
|
||||
<groupId>de.kherud</groupId>
|
||||
<artifactId>llama</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test support -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
@ -1,21 +1,35 @@
|
||||
package com.pablotj.ia.chat.boot;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/chat")
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/")
|
||||
public class ChatController {
|
||||
|
||||
private final List<ChatMessage> messages = new ArrayList<>();
|
||||
private final LlamaService llamaService;
|
||||
|
||||
public ChatController(LlamaService llamaService) {
|
||||
this.llamaService = llamaService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String chat(@RequestParam String prompt) {
|
||||
return llamaService.chat(prompt);
|
||||
@GetMapping("/chat")
|
||||
public String showChat(Model model) {
|
||||
model.addAttribute("messages", messages);
|
||||
return "chat";
|
||||
}
|
||||
|
||||
@PostMapping("/chat")
|
||||
public String handleChat(@RequestParam("prompt") String prompt, Model model) {
|
||||
messages.add(new ChatMessage("user", prompt));
|
||||
String reply = llamaService.chat(prompt);
|
||||
messages.add(new ChatMessage("bot", reply));
|
||||
model.addAttribute("messages", messages);
|
||||
return "chat";
|
||||
}
|
||||
}
|
||||
|
19
src/main/java/com/pablotj/ia/chat/boot/ChatMessage.java
Normal file
19
src/main/java/com/pablotj/ia/chat/boot/ChatMessage.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.pablotj.ia.chat.boot;
|
||||
|
||||
public class ChatMessage {
|
||||
private String role; // "user" o "bot"
|
||||
private String text;
|
||||
|
||||
public ChatMessage(String role, String text) {
|
||||
this.role = role;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
@ -15,7 +15,14 @@ public class LlamaService implements AutoCloseable {
|
||||
public void init() {
|
||||
try {
|
||||
ModelParameters params = new ModelParameters()
|
||||
.setModelFilePath("models/openchat-3.5-0106.Q4_K_M.gguf");
|
||||
.setModelFilePath("models/ggml-model-q3_k.gguf")
|
||||
.setSeed(42)
|
||||
.setNThreads(8) // usa 8 hilos CPU (ajusta según tu CPU)
|
||||
.setNGpuLayers(0) // no usar GPU
|
||||
.setMainGpu(-1) // deshabilitar GPU principal
|
||||
.setNoKvOffload(true) // no descargar KV, evitar errores GPU
|
||||
.setUseMmap(true) // mejorar gestión memoria
|
||||
.setNPredict(128);
|
||||
model = new LlamaModel(params);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error cargando el modelo", e);
|
||||
@ -33,9 +40,11 @@ public class LlamaService implements AutoCloseable {
|
||||
String finalPrompt = chat.build();
|
||||
|
||||
InferenceParameters inf = new InferenceParameters(finalPrompt)
|
||||
.setNPredict(200)
|
||||
.setTemperature(0.7f)
|
||||
.setTopP(0.9f)
|
||||
.setTopK(40);
|
||||
.setTopK(40)
|
||||
.setUseChatTemplate(true);
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -13,21 +13,23 @@ public class PromptBuilder {
|
||||
}
|
||||
|
||||
public void user(String message) {
|
||||
turns.add("GPT4 Correct User: " + message + "<|end_of_turn|>");
|
||||
turns.add("<|im_start|>user\n" + message + "\n<|im_end|>");
|
||||
}
|
||||
|
||||
public void assistant(String message) {
|
||||
turns.add("GPT4 Correct Assistant: " + message + "<|end_of_turn|>");
|
||||
turns.add("<|im_start|>assistant\n" + message + "\n<|im_end|>");
|
||||
}
|
||||
|
||||
public String build() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(systemPrompt).append("<|end_of_turn|>\n");
|
||||
sb.append("<|im_start|>system\n")
|
||||
.append(systemPrompt)
|
||||
.append("\n<|im_end|>\n");
|
||||
for (String turn : turns) {
|
||||
sb.append(turn).append("\n");
|
||||
}
|
||||
// Deja el último turno preparado para que el modelo continúe como "Assistant"
|
||||
sb.append("GPT4 Correct Assistant: ");
|
||||
// Deja listo para que el modelo continúe como assistant generando respuesta:
|
||||
sb.append("<|im_start|>assistant\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
28
src/main/resources/templates/chat.html
Normal file
28
src/main/resources/templates/chat.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Chat con IA Offline</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; max-width: 800px; margin: 2rem auto; }
|
||||
.bubble { margin-bottom: 1rem; }
|
||||
.user { color: #003366; font-weight: bold; }
|
||||
.bot { color: #006600; }
|
||||
textarea { width: 100%; height: 4em; margin-top: 1rem; }
|
||||
button { padding: 0.5rem 1rem; margin-top: 0.5rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Chat con IA Offline</h1>
|
||||
|
||||
<div th:each="msg : ${messages}" class="bubble">
|
||||
<div th:if="${msg.role} == 'user'" class="user">🧑💻: <span th:text="${msg.text}"></span></div>
|
||||
<div th:if="${msg.role} == 'bot'" class="bot">🤖: <span th:text="${msg.text}"></span></div>
|
||||
</div>
|
||||
|
||||
<form method="post" th:action="@{/chat}">
|
||||
<textarea name="prompt" placeholder="Escribe tu mensaje aquí..."></textarea><br>
|
||||
<button type="submit">Enviar</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user