fix: rewrite tag_assign dspy with explicit return
This commit is contained in:
parent
b322c4533e
commit
5d0ec6f3c4
@ -11,7 +11,6 @@ import json
|
|||||||
base_url = entire_url('/tag_assign/index.dspy')
|
base_url = entire_url('/tag_assign/index.dspy')
|
||||||
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
async with db.sqlorContext(dbname) as sor:
|
||||||
# Handle assign/unassign actions
|
|
||||||
if action and media_id and tag_id:
|
if action and media_id and tag_id:
|
||||||
import uuid
|
import uuid
|
||||||
try:
|
try:
|
||||||
@ -27,37 +26,24 @@ async with db.sqlorContext(dbname) as sor:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Get knowledge bases
|
|
||||||
kbs = await sor.R('knowledge_bases', {})
|
kbs = await sor.R('knowledge_bases', {})
|
||||||
|
|
||||||
# Get media items
|
|
||||||
media_items = []
|
media_items = []
|
||||||
if kb_id:
|
if kb_id:
|
||||||
if media_type == 'document':
|
if media_type == 'document':
|
||||||
recs = await sor.sqlExe(
|
recs = await sor.sqlExe("SELECT id, file_name, file_type FROM documents WHERE kb_id=${kb_id}$ ORDER BY created_at DESC LIMIT 100", {"kb_id": kb_id})
|
||||||
"SELECT id, file_name, file_type FROM documents WHERE kb_id=${kb_id}$ ORDER BY created_at DESC LIMIT 100",
|
|
||||||
{"kb_id": kb_id})
|
|
||||||
media_items = [{"id": r.id, "name": r.file_name, "type": r.file_type} for r in recs]
|
media_items = [{"id": r.id, "name": r.file_name, "type": r.file_type} for r in recs]
|
||||||
elif media_type == 'face':
|
elif media_type == 'face':
|
||||||
recs = await sor.sqlExe(
|
recs = await sor.sqlExe("SELECT id, name, description FROM entities WHERE kb_id=${kb_id}$ AND entity_type='person' AND face_embedding_id IS NOT NULL ORDER BY created_at DESC LIMIT 100", {"kb_id": kb_id})
|
||||||
"SELECT id, name, description FROM entities WHERE kb_id=${kb_id}$ AND entity_type='person' AND face_embedding_id IS NOT NULL ORDER BY created_at DESC LIMIT 100",
|
|
||||||
{"kb_id": kb_id})
|
|
||||||
media_items = [{"id": r.id, "name": r.name or '人脸#'+r.id[:8], "type": "face"} for r in recs]
|
media_items = [{"id": r.id, "name": r.name or '人脸#'+r.id[:8], "type": "face"} for r in recs]
|
||||||
elif media_type == 'voice':
|
elif media_type == 'voice':
|
||||||
recs = await sor.sqlExe(
|
recs = await sor.sqlExe("SELECT id, name, description FROM entities WHERE kb_id=${kb_id}$ AND entity_type='voice' AND voice_embedding_id IS NOT NULL ORDER BY created_at DESC LIMIT 100", {"kb_id": kb_id})
|
||||||
"SELECT id, name, description FROM entities WHERE kb_id=${kb_id}$ AND entity_type='voice' AND voice_embedding_id IS NOT NULL ORDER BY created_at DESC LIMIT 100",
|
|
||||||
{"kb_id": kb_id})
|
|
||||||
media_items = [{"id": r.id, "name": r.name or '声纹#'+r.id[:8], "type": "voice"} for r in recs]
|
media_items = [{"id": r.id, "name": r.name or '声纹#'+r.id[:8], "type": "voice"} for r in recs]
|
||||||
|
|
||||||
# Get current tags for selected media
|
|
||||||
current_tags = []
|
current_tags = []
|
||||||
if media_id:
|
if media_id:
|
||||||
recs = await sor.sqlExe(
|
recs = await sor.sqlExe("SELECT t.id, t.name, t.color FROM media_tags mt JOIN tags t ON mt.tag_id=t.id WHERE mt.media_type=${type}$ AND mt.media_id=${mid}$", {"type": media_type, "mid": media_id})
|
||||||
"SELECT t.id, t.name, t.color FROM media_tags mt JOIN tags t ON mt.tag_id=t.id WHERE mt.media_type=${type}$ AND mt.media_id=${mid}$",
|
|
||||||
{"type": media_type, "mid": media_id})
|
|
||||||
current_tags = [{"id": r.id, "name": r.name, "color": r.color} for r in recs]
|
current_tags = [{"id": r.id, "name": r.name, "color": r.color} for r in recs]
|
||||||
|
|
||||||
# Get all available tags
|
|
||||||
all_tags = []
|
all_tags = []
|
||||||
if kb_id:
|
if kb_id:
|
||||||
tag_recs = await sor.R('tags', {'kb_id': kb_id})
|
tag_recs = await sor.R('tags', {'kb_id': kb_id})
|
||||||
@ -65,93 +51,44 @@ async with db.sqlorContext(dbname) as sor:
|
|||||||
|
|
||||||
current_tag_ids = {t['id'] for t in current_tags}
|
current_tag_ids = {t['id'] for t in current_tags}
|
||||||
|
|
||||||
# Build available tag buttons
|
|
||||||
tag_buttons = []
|
tag_buttons = []
|
||||||
for t in all_tags:
|
for t in all_tags:
|
||||||
is_assigned = t['id'] in current_tag_ids
|
is_assigned = t['id'] in current_tag_ids
|
||||||
if is_assigned:
|
act = 'unassign' if is_assigned else 'assign'
|
||||||
act = 'unassign'
|
lbl = ('✓ ' if is_assigned else '+ ') + t['name']
|
||||||
lbl = '✓ ' + t['name']
|
bg = t['color'] if is_assigned else '#e5e7eb'
|
||||||
bg = t['color']
|
clr = '#fff' if is_assigned else '#666'
|
||||||
clr = '#fff'
|
|
||||||
else:
|
|
||||||
act = 'assign'
|
|
||||||
lbl = '+ ' + t['name']
|
|
||||||
bg = '#e5e7eb'
|
|
||||||
clr = '#666'
|
|
||||||
tag_url = base_url + '?kb_id=' + kb_id + '&media_type=' + media_type + '&media_id=' + media_id + '&action=' + act + '&tag_id=' + t['id']
|
tag_url = base_url + '?kb_id=' + kb_id + '&media_type=' + media_type + '&media_id=' + media_id + '&action=' + act + '&tag_id=' + t['id']
|
||||||
tag_buttons.append({
|
tag_buttons.append({"widgettype": "Button", "options": {"label": lbl, "bgcolor": bg, "color": clr, "cfontsize": 12, "padding": "4px 12px", "marginRight": "6px", "marginBottom": "6px"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": tag_url}}]})
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {"label": lbl, "bgcolor": bg, "color": clr, "cfontsize": 12, "padding": "4px 12px", "marginRight": "6px", "marginBottom": "6px"},
|
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": tag_url}}]
|
|
||||||
})
|
|
||||||
|
|
||||||
# Build media list buttons
|
|
||||||
media_buttons = []
|
media_buttons = []
|
||||||
for m in media_items:
|
for m in media_items:
|
||||||
murl = base_url + '?kb_id=' + kb_id + '&media_type=' + media_type + '&media_id=' + m['id']
|
murl = base_url + '?kb_id=' + kb_id + '&media_type=' + media_type + '&media_id=' + m['id']
|
||||||
is_current = m['id'] == media_id
|
is_current = m['id'] == media_id
|
||||||
media_buttons.append({
|
icon = '📄' if media_type == 'document' else ('👤' if media_type == 'face' else '🎤')
|
||||||
"widgettype": "Button",
|
media_buttons.append({"widgettype": "Button", "options": {"label": icon + ' ' + m['name'], "bgcolor": "#dbeafe" if is_current else "#f9fafb", "color": "#1e40af" if is_current else "#666", "cfontsize": 12, "padding": "6px 12px", "marginBottom": "4px", "halign": "left"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": murl}}]})
|
||||||
"options": {
|
|
||||||
"label": ('📄' if media_type=='document' else ('👤' if media_type=='face' else '🎤')) + ' ' + m['name'],
|
|
||||||
"bgcolor": "#dbeafe" if is_current else "#f9fafb",
|
|
||||||
"color": "#1e40af" if is_current else "#666",
|
|
||||||
"cfontsize": 12,
|
|
||||||
"padding": "6px 12px",
|
|
||||||
"marginBottom": "4px",
|
|
||||||
"halign": "left"
|
|
||||||
},
|
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": murl}}]
|
|
||||||
})
|
|
||||||
|
|
||||||
# KB buttons
|
|
||||||
kb_buttons = []
|
kb_buttons = []
|
||||||
for k in kbs:
|
for k in kbs:
|
||||||
kb_buttons.append({
|
kb_buttons.append({"widgettype": "Button", "options": {"label": k.name, "bgcolor": "#3b82f6" if k.id == kb_id else "#e5e7eb", "color": "#fff" if k.id == kb_id else "#666", "cfontsize": 12, "padding": "6px 14px", "marginRight": "6px", "marginBottom": "4px"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": base_url + '?kb_id=' + k.id + '&media_type=' + media_type}}]})
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {"label": k.name, "bgcolor": "#3b82f6" if k.id==kb_id else "#e5e7eb", "color": "#fff" if k.id==kb_id else "#666", "cfontsize": 12, "padding": "6px 14px", "marginRight": "6px", "marginBottom": "4px"},
|
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace",
|
|
||||||
"options": {"url": base_url + '?kb_id=' + k.id + '&media_type=' + media_type}}]}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Type tabs
|
|
||||||
type_tabs = []
|
type_tabs = []
|
||||||
for mt, mt_label in [('document', '📄 文档'), ('face', '👤 人脸'), ('voice', '🎤 声纹')]:
|
for mt, mt_label in [('document', '📄 文档'), ('face', '👤 人脸'), ('voice', '🎤 声纹')]:
|
||||||
type_tabs.append({
|
type_tabs.append({"widgettype": "Button", "options": {"label": mt_label, "bgcolor": "#3b82f6" if mt == media_type else "#e5e7eb", "color": "#fff" if mt == media_type else "#666", "cfontsize": 12, "padding": "6px 16px", "marginRight": "4px"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": base_url + '?kb_id=' + kb_id + '&media_type=' + mt}}]})
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {"label": mt_label, "bgcolor": "#3b82f6" if mt==media_type else "#e5e7eb", "color": "#fff" if mt==media_type else "#666", "cfontsize": 12, "padding": "6px 16px", "marginRight": "4px"},
|
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace",
|
|
||||||
"options": {"url": base_url + '?kb_id=' + kb_id + '&media_type=' + mt}}]}
|
|
||||||
)
|
|
||||||
|
|
||||||
result = {
|
result = json.dumps({"widgettype": "VBox", "options": {"cheight": 40, "width": "100%", "padding": "16px", "spacing": "12px"}, "subwidgets": [
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {"cheight": 40, "width": "100%", "padding": "16px", "spacing": "12px"},
|
|
||||||
"subwidgets": [
|
|
||||||
{"widgettype": "Text", "options": {"text": "🏷️ 标签分配", "cfontsize": 20, "fontWeight": "bold", "color": "#333"}},
|
{"widgettype": "Text", "options": {"text": "🏷️ 标签分配", "cfontsize": 20, "fontWeight": "bold", "color": "#333"}},
|
||||||
{"widgettype": "Text", "options": {"text": "为文档、人脸、声纹设置标签", "cfontsize": 13, "color": "#888"}},
|
{"widgettype": "Text", "options": {"text": "为文档、人脸、声纹设置标签", "cfontsize": 13, "color": "#888"}},
|
||||||
# KB
|
|
||||||
{"widgettype": "Text", "options": {"text": "知识库:", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
{"widgettype": "Text", "options": {"text": "知识库:", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
||||||
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": kb_buttons},
|
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": kb_buttons},
|
||||||
# Media type
|
|
||||||
{"widgettype": "Text", "options": {"text": "媒体类型:", "cfontsize": 13, "color": "#555", "marginTop": "4px"}},
|
{"widgettype": "Text", "options": {"text": "媒体类型:", "cfontsize": 13, "color": "#555", "marginTop": "4px"}},
|
||||||
{"widgettype": "HBox", "options": {"spacing": "4px"}, "subwidgets": type_tabs},
|
{"widgettype": "HBox", "options": {"spacing": "4px"}, "subwidgets": type_tabs},
|
||||||
# Media list
|
{"widgettype": "Text", "options": {"text": "选择" + ('文档' if media_type == 'document' else ('人脸' if media_type == 'face' else '声纹')) + ":", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
||||||
{"widgettype": "Text", "options": {"text": '选择' + ('文档' if media_type=='document' else ('人脸' if media_type=='face' else '声纹')) + ':', "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
|
||||||
{"widgettype": "VBox", "options": {"cheight": 12, "bgcolor": "#fafafa", "padding": "8px", "border": "1px solid #e0e0e0", "overflowY": "auto"}, "subwidgets": media_buttons},
|
{"widgettype": "VBox", "options": {"cheight": 12, "bgcolor": "#fafafa", "padding": "8px", "border": "1px solid #e0e0e0", "overflowY": "auto"}, "subwidgets": media_buttons},
|
||||||
# Current tags
|
|
||||||
{"widgettype": "Text", "options": {"text": "当前标签:", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
{"widgettype": "Text", "options": {"text": "当前标签:", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
||||||
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": [
|
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": current_tags and [{"widgettype": "Button", "options": {"label": t['name'], "bgcolor": t['color'], "color": "#fff", "cfontsize": 11, "padding": "3px 10px", "marginRight": "4px", "marginBottom": "4px"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": base_url + '?kb_id=' + kb_id + '&media_type=' + media_type + '&media_id=' + media_id + '&action=unassign&tag_id=' + t['id']}}]} for t in current_tags] or [{"widgettype": "Text", "options": {"text": "(无)", "color": "#aaa", "cfontsize": 12}}]},
|
||||||
{"widgettype": "Button", "options": {"label": t['name'], "bgcolor": t['color'], "color": "#fff", "cfontsize": 11, "padding": "3px 10px", "marginRight": "4px", "marginBottom": "4px"},
|
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace",
|
|
||||||
"options": {"url": base_url + '?kb_id=' + kb_id + '&media_type=' + media_type + '&media_id=' + media_id + '&action=unassign&tag_id=' + t['id']}}]}
|
|
||||||
for t in current_tags] if current_tags else [{"widgettype": "Text", "options": {"text": "(无)", "color": "#aaa", "cfontsize": 12}}]},
|
|
||||||
# Available tags
|
|
||||||
{"widgettype": "Text", "options": {"text": "可用标签 (点击切换):", "cfontsize": 13, "color": "#555", "marginTop": "4px"}},
|
{"widgettype": "Text", "options": {"text": "可用标签 (点击切换):", "cfontsize": 13, "color": "#555", "marginTop": "4px"}},
|
||||||
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": tag_buttons} if media_id else [
|
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": tag_buttons} if media_id else [{"widgettype": "Text", "options": {"text": "请先选择媒体文件", "color": "#aaa", "cfontsize": 12, "padding": "12px 0"}}]
|
||||||
{"widgettype": "Text", "options": {"text": "请先选择媒体文件", "color": "#aaa", "cfontsize": 12, "padding": "12px 0"}}
|
]})
|
||||||
]
|
|
||||||
]
|
return json.loads(result)
|
||||||
}
|
|
||||||
result
|
|
||||||
|
|||||||
@ -99,4 +99,4 @@ async with db.sqlorContext(dbname) as sor:
|
|||||||
{"widgettype": "VBox", "options": {"spacing": "4px"}, "subwidgets": results_widgets}
|
{"widgettype": "VBox", "options": {"spacing": "4px"}, "subwidgets": results_widgets}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
result
|
return result
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user