summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMichael Peter Christen <mc@yacy.net>2025-12-06 19:21:57 +0100
committerMichael Peter Christen <mc@yacy.net>2025-12-06 19:21:57 +0100
commiteed704d23bc53e5d0359072e5e2134b469ae2eef (patch)
tree2518c10e9e478a4c04845db3b81442ee9dfca7cb /source
parented9ea238b1e7d4a89d77acea790b08b6f2b1ed49 (diff)
added RAG configuration page
Diffstat (limited to 'source')
-rw-r--r--source/net/yacy/htroot/AILab.java4
-rw-r--r--source/net/yacy/htroot/RAGConfig_p.java36
-rw-r--r--source/net/yacy/htroot/yacychat.java38
-rw-r--r--source/net/yacy/http/servlets/RAGProxyServlet.java24
4 files changed, 74 insertions, 28 deletions
diff --git a/source/net/yacy/htroot/AILab.java b/source/net/yacy/htroot/AILab.java
index 461a8c32e..e479f4a39 100644
--- a/source/net/yacy/htroot/AILab.java
+++ b/source/net/yacy/htroot/AILab.java
@@ -79,7 +79,9 @@ public class AILab {
prop.put("ailab_index_status", hasIndex ? "ready" : "pending");
prop.putNum("ailab_index_count", indexDocs);
prop.putNum("ailab_index_needed", indexNeeded);
- prop.put("ailab_rag_status", hasRagRole ? "ready" : "pending");
+ // consider the RAG configuration page visit as completing the RAG quest
+ final boolean ragVisited = "true".equalsIgnoreCase(sb.getConfig("ui.RAGConfig_p.visited", "false"));
+ prop.put("ailab_rag_status", (hasRagRole || ragVisited) ? "ready" : "pending");
prop.put("ailab_shield_status", hasShield ? "ready" : "pending");
return prop;
diff --git a/source/net/yacy/htroot/RAGConfig_p.java b/source/net/yacy/htroot/RAGConfig_p.java
new file mode 100644
index 000000000..819d9832d
--- /dev/null
+++ b/source/net/yacy/htroot/RAGConfig_p.java
@@ -0,0 +1,36 @@
+// RAGConfig_p.java
+// Configure RAG prompt strings
+
+package net.yacy.htroot;
+
+import net.yacy.cora.protocol.RequestHeader;
+import net.yacy.search.Switchboard;
+import net.yacy.server.serverObjects;
+import net.yacy.server.serverSwitch;
+
+public class RAGConfig_p {
+
+ public static serverObjects respond(@SuppressWarnings("unused") final RequestHeader header, final serverObjects post, final serverSwitch env) {
+ final Switchboard sb = (Switchboard) env;
+ final serverObjects prop = new serverObjects();
+
+ if (post != null) {
+ final String systemPrompt = post.get("ai.system-prompt", "").trim();
+ final String userPrefix = post.get("ai.llm-user-prefix", "").trim();
+ final String queryPrefix = post.get("ai.llm-query-generator-prefix", "").trim();
+
+ sb.setConfig("ai.system-prompt", systemPrompt);
+ sb.setConfig("ai.llm-user-prefix", userPrefix);
+ sb.setConfig("ai.llm-query-generator-prefix", queryPrefix);
+ }
+
+ // mark page as visited for gamification/quest tracking
+ sb.setConfig("ui.RAGConfig_p.visited", "true");
+
+ prop.put("ai.system-prompt", sb.getConfig("ai.system-prompt", net.yacy.http.servlets.RAGProxyServlet.LLM_SYSTEM_PROMPT_DEFAULT));
+ prop.put("ai.llm-user-prefix", sb.getConfig("ai.llm-user-prefix", "\n\nAdditional Information:\n\nbelow you find a collection of texts that might be useful to generate a response. Do not discuss these documents, just use them to answer the question above.\n\n"));
+ prop.put("ai.llm-query-generator-prefix", sb.getConfig("ai.llm-query-generator-prefix", "Make a list of search words with low document frequency for the following prompt; use a JSON Array: "));
+
+ return prop;
+ }
+}
diff --git a/source/net/yacy/htroot/yacychat.java b/source/net/yacy/htroot/yacychat.java
index db9d14eee..df573c7c1 100644
--- a/source/net/yacy/htroot/yacychat.java
+++ b/source/net/yacy/htroot/yacychat.java
@@ -12,22 +12,26 @@ 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;
+ // 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
+ }
+ }
+
+ // system prompt comes from configuration; default is empty
+ final String systemPrompt = sb.getConfig("ai.system-prompt", net.yacy.http.servlets.RAGProxyServlet.LLM_SYSTEM_PROMPT_DEFAULT);
+ prop.put("system_prompt", systemPrompt);
+
+ // 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 2108f57f2..3c8fe535d 100644
--- a/source/net/yacy/http/servlets/RAGProxyServlet.java
+++ b/source/net/yacy/http/servlets/RAGProxyServlet.java
@@ -87,9 +87,11 @@ public class RAGProxyServlet extends HttpServlet {
private static final long serialVersionUID = 3411544789759643137L;
- private static String LLM_SYSTEM_PREFIX = "\n\nYou may receive additional expert knowledge in the user prompt after a 'Additional Information' headline to enhance your knowledge. Use it only if applicable.";
- private static String LLM_USER_PREFIX = "\n\nAdditional Information:\n\nbelow you find a collection of texts that might be useful to generate a response. Do not discuss these documents, just use them to answer the question above.\n\n";
-
+ public static final String LLM_SYSTEM_PROMPT_DEFAULT = "You are a smart and helpful chatbot. If possible, use friendly emojies.";
+ private static final String LLM_SYSTEM_PREFIX_DEFAULT = "\n\nYou may receive additional expert knowledge in the user prompt after a 'Additional Information' headline to enhance your knowledge. Use it only if applicable.";
+ private static final String LLM_USER_PREFIX_DEFAULT = "\n\nAdditional Information:\n\nbelow you find a collection of texts that might be useful to generate a response. Do not discuss these documents, just use them to answer the question above.\n\n";
+ private static final String LLM_QUERY_GENERATOR_PREFIX_DEFAULT = "Make a list of search words with low document frequency for the following prompt; use a JSON Array: ";
+
@Override
public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
@@ -136,6 +138,7 @@ public class RAGProxyServlet extends HttpServlet {
String body = bodyBuilder.toString();
JSONObject bodyObject;
try {
+ final Switchboard sb = Switchboard.getSwitchboard();
// get system message and user prompt
bodyObject = new JSONObject(body);
// get chat functions
@@ -153,11 +156,13 @@ public class RAGProxyServlet extends HttpServlet {
// get messages and prepare user message attachments
JSONArray messages = bodyObject.optJSONArray("messages");
+ final String systemPrefix = sb.getConfig("ai.llm-system-prefix", LLM_SYSTEM_PREFIX_DEFAULT);
+ final String userPrefix = sb.getConfig("ai.llm-user-prefix", LLM_USER_PREFIX_DEFAULT);
for (int i = 0; i < messages.length(); i++) {
JSONObject message = messages.getJSONObject(i);
if (message.optString("role", "").equals("user")) {
UserObject userObject = new UserObject(message);
- userObject.attachAttachment(LLM_USER_PREFIX);
+ userObject.attachAttachment(userPrefix);
}
}
UserObject userObject = new UserObject(messages.getJSONObject(messages.length() - 1));
@@ -170,9 +175,10 @@ public class RAGProxyServlet extends HttpServlet {
String searchResultMarkdown = "";
if (rag) {
// modify system and user prompt here in bodyObject to enable RAG
- searchResultQuery = this.searchWordsForPrompt(llm4tldr.llm, llm4tldr.model, user);
+ final String queryPrefix = sb.getConfig("ai.llm-query-generator-prefix", LLM_QUERY_GENERATOR_PREFIX_DEFAULT);
+ searchResultQuery = this.searchWordsForPrompt(llm4tldr.llm, llm4tldr.model, queryPrefix + user);
searchResultMarkdown = searchResultsAsMarkdown(searchResultQuery, 10);
- user += LLM_USER_PREFIX;
+ user += userPrefix;
user += searchResultMarkdown;
userObject.setContentText(user);
}
@@ -614,8 +620,6 @@ public class RAGProxyServlet extends HttpServlet {
return this.title;
}
}
-
-
/**
* Creates slices of a given text. We want slices of average same size,
@@ -660,9 +664,9 @@ public class RAGProxyServlet extends HttpServlet {
}
private String searchWordsForPrompt(LLM llm, String model, String prompt) {
- String question = "Make a list of search words with low document frequency for the following prompt; use a JSON Array: " + prompt;
+ String question = LLM_QUERY_GENERATOR_PREFIX_DEFAULT + prompt;
try {
- LLM.Context context = new LLM.Context(LLM_SYSTEM_PREFIX);
+ LLM.Context context = new LLM.Context(LLM_SYSTEM_PREFIX_DEFAULT);
context.addPrompt(question);
Set<String> singlewords = new LinkedHashSet<>();
String[] a = LLM.stringsFromChat(llm.chat(model, context, LLM.listSchema, 200));