Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions ui/backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,31 @@ def chat_pipeline(name: str):
session_id = payload.get("session_id")
dynamic_params = payload.get("dynamic_params", {})

selected_collection = dynamic_params.get("collection_name")

try:
kb_config = pm.load_kb_config()
milvus_global_config = kb_config.get("milvus", {})

retriever_params = {
"index_backend": "milvus",
"index_backend_configs": {
"milvus": milvus_global_config
}
}

if selected_collection:
retriever_params["collection_name"] = selected_collection
print(f"debug: Chat using collection override: {selected_collection}")

dynamic_params["retriever"] = retriever_params

if "collection_name" in dynamic_params:
del dynamic_params["collection_name"]

except Exception as e:
print(f"Warning: Failed to construct retriever config: {e}")

if not session_id:
return jsonify({"error": "session_id missing. Please start engine first."}), 400

Expand Down
10 changes: 10 additions & 0 deletions ui/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,16 @@ <h2 class="m-0 fs-5 fw-semibold">Parameter Configuration</h2>
<div class="chat-container">
<div class="chat-scroll-area" id="chat-history"></div>
<div class="chat-input-wrapper">
<div class="d-flex justify-content-between align-items-center mb-2 px-1">
<div class="d-flex align-items-center gap-2">
<select id="chat-collection-select" class="form-select form-select-sm" style="width: auto; border-radius: 20px; font-size: 0.8rem; background-color: #f8f9fa;">
<option value="" selected>⚪ No Knowledge Base</option>
</select>
<button class="btn btn-sm btn-icon text-muted" onclick="renderChatCollectionOptions()" title="Refresh Collections">↻</button>
</div>
<span class="text-xs text-muted" id="chat-kb-status"></span>
</div>

<form id="chat-form" class="chat-input-container shadow-sm">
<input type="text" id="chat-input" class="form-control chat-input" placeholder="Message UltraRAG..." autocomplete="off" />

Expand Down
54 changes: 52 additions & 2 deletions ui/frontend/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const els = {
chatNewBtn: document.getElementById("chat-new-btn"),
chatSessionList: document.getElementById("chat-session-list"),
demoToggleBtn: document.getElementById("demo-toggle-btn"), // 引擎开关
chatCollectionSelect: document.getElementById("chat-collection-select"),

// [新增] 视图容器
chatMainView: document.getElementById("chat-main-view"),
Expand Down Expand Up @@ -800,6 +801,41 @@ function updateDemoControls() {

// --- Chat Logic (Updated with Streaming) ---

// [新增] 渲染聊天界面的 Collection 下拉选项
async function renderChatCollectionOptions() {
if (!els.chatCollectionSelect) return;

// 保存当前选中的值,以免刷新后重置
const currentVal = els.chatCollectionSelect.value;

try {
// 复用后端的列表接口
const data = await fetchJSON('/api/kb/files');
const collections = data.index || []; // data.index 存放的是 collection 列表

els.chatCollectionSelect.innerHTML = '<option value="">⚪ No Knowledge Base</option>';

collections.forEach(c => {
const opt = document.createElement("option");
opt.value = c.name;
// 显示名字和数据量
opt.textContent = `${c.name} (${c.count || 0})`;
els.chatCollectionSelect.appendChild(opt);
});

// 尝试恢复选中状态
if (currentVal) {
// 检查新列表里是否还有这个值
const exists = collections.find(c => c.name === currentVal);
if (exists) els.chatCollectionSelect.value = currentVal;
}

} catch (e) {
console.error("Failed to load collections for chat:", e);
// 出错时不覆盖默认选项,或者显示错误
}
}

// [新增] 切换到知识库视图
function openKBView() {
if (!els.chatMainView || !els.kbMainView) return;
Expand Down Expand Up @@ -1211,6 +1247,9 @@ function openChatView() {
if (els.chatPipelineName) els.chatPipelineName.textContent = state.selectedPipeline || "—";

renderChatPipelineMenu();

// [新增] 进入聊天时,加载最新的 Collection 列表
renderChatCollectionOptions();

if (!state.chat.currentSessionId) createNewChatSession();

Expand Down Expand Up @@ -1456,10 +1495,21 @@ async function handleChatSubmit(event) {

try {
if (!state.parametersReady) await persistParameterData({ silent: true });

const selectedCollection = els.chatCollectionSelect ? els.chatCollectionSelect.value : "";

const dynamicParams = {};
if (selectedCollection) {
dynamicParams["collection_name"] = selectedCollection;
}

const endpoint = `/api/pipelines/${encodeURIComponent(state.selectedPipeline)}/chat`;
const body = JSON.stringify({
question, history: state.chat.history, is_demo: true,
session_id: state.chat.engineSessionId, dynamic_params: {}
question,
history: state.chat.history,
is_demo: true,
session_id: state.chat.engineSessionId,
dynamic_params: dynamicParams
});

const response = await fetch(endpoint, {
Expand Down
24 changes: 23 additions & 1 deletion ui/frontend/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -1199,4 +1199,26 @@ body {
display: flex;
justify-content: space-between;
}
.folder-file-row:last-child { border-bottom: none; }
.folder-file-row:last-child { border-bottom: none; }

/* Chat Context Selector */
#chat-collection-select {
border-color: var(--border-subtle);
cursor: pointer;
padding-left: 12px;
padding-right: 32px; /* 留出箭头空间 */
font-weight: 500;
color: var(--text-primary);
box-shadow: none;
transition: all 0.2s;
}

#chat-collection-select:hover {
background-color: #fff;
border-color: var(--accent-blue);
}

#chat-collection-select:focus {
border-color: var(--accent-blue);
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.1);
}