From 5f06b5b4820c70545640148bc81199c29a67f8ad Mon Sep 17 00:00:00 2001 From: Michael Peter Christen Date: Sun, 23 Nov 2025 18:34:49 +0100 Subject: [PATCH] added chat front-end (stub, no connection to search yet) --- htroot/LLMSelection_p.html | 2 +- htroot/env/templates/submenuAI.template | 7 + htroot/yacychat.html | 368 ++++++++++++++++++ source/net/yacy/htroot/yacychat.java | 33 ++ .../yacy/http/servlets/RAGProxyServlet.java | 13 +- 5 files changed, 420 insertions(+), 3 deletions(-) create mode 100644 htroot/env/templates/submenuAI.template create mode 100644 htroot/yacychat.html create mode 100644 source/net/yacy/htroot/yacychat.java diff --git a/htroot/LLMSelection_p.html b/htroot/LLMSelection_p.html index 8179abd59..4150549e3 100644 --- a/htroot/LLMSelection_p.html +++ b/htroot/LLMSelection_p.html @@ -7,7 +7,7 @@ #%env/templates/header.template%# - #%env/templates/submenuIndexImport.template%# + #%env/templates/submenuAI.template%# + + #%env/templates/footer.template%# + + diff --git a/source/net/yacy/htroot/yacychat.java b/source/net/yacy/htroot/yacychat.java new file mode 100644 index 000000000..db9d14eee --- /dev/null +++ b/source/net/yacy/htroot/yacychat.java @@ -0,0 +1,33 @@ +package net.yacy.htroot; + +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +import net.yacy.cora.protocol.RequestHeader; +import net.yacy.search.Switchboard; +import net.yacy.server.serverObjects; +import net.yacy.server.serverSwitch; + +public class yacychat { + + public static serverObjects respond(@SuppressWarnings("unused") final RequestHeader header, final serverObjects post, final serverSwitch env) { + // return variable that accumulates replacements + final Switchboard sb = (Switchboard) env; + + final serverObjects prop = new serverObjects(); + String body = post == null ? "" : post.get("BODY", ""); + JSONObject bodyj = new JSONObject(); + if (body.length() > 0) { + try { + bodyj = new JSONObject(new JSONTokener(body)); + } catch (JSONException e) { + // silently catch this + } + } + + // return rewrite properties + return prop; + } + +} \ No newline at end of file diff --git a/source/net/yacy/http/servlets/RAGProxyServlet.java b/source/net/yacy/http/servlets/RAGProxyServlet.java index 5553b75f1..cc1c14514 100644 --- a/source/net/yacy/http/servlets/RAGProxyServlet.java +++ b/source/net/yacy/http/servlets/RAGProxyServlet.java @@ -51,6 +51,7 @@ import org.json.JSONObject; import net.yacy.ai.LLM; import net.yacy.cora.federate.solr.SolrType; import net.yacy.cora.federate.solr.connector.EmbeddedSolrConnector; +import net.yacy.cora.protocol.Domains; import net.yacy.search.Switchboard; import net.yacy.search.schema.CollectionSchema; @@ -88,6 +89,13 @@ public class RAGProxyServlet extends HttpServlet { hresponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); hresponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); + final String clientIP = hrequest.getRemoteAddr(); + final boolean localhostAccess = Domains.isLocalhost(clientIP); + if (!localhostAccess) { + // we will introduce a rate limit for non-localhost later, for now we just don't allow it + hresponse.sendError(HttpServletResponse.SC_FORBIDDEN); + } + final Method reqMethod = Method.getMethod(hrequest.getMethod()); if (reqMethod == Method.OTHER) { // required to handle CORS @@ -157,9 +165,10 @@ public class RAGProxyServlet extends HttpServlet { systemObject.put("content", system); userObject.put("content", user); - // write back modified bodyMap to body - body = bodyObject.toString(); } + + // write back modified bodyMap to body + body = bodyObject.toString(); // Open request to back-end service URL url = new URI(llm4Chat.llm.hoststub + "/v1/chat/completions").toURL();