fix graph bugs

This commit is contained in:
Wenjie Zhang 2024-09-06 21:30:49 +08:00
parent b7e65fe108
commit f9b8d5b2e9
3 changed files with 110 additions and 84 deletions

View File

@ -6,11 +6,11 @@
<span class="filetag item" <span class="filetag item"
v-for="(results, filename) in message.groupedResults" v-for="(results, filename) in message.groupedResults"
:key="filename" :key="filename"
@click="openDetail = true" @click="toggleDrawer(filename)"
> >
<FileTextOutlined /> {{ filename }} <FileTextOutlined /> {{ filename }}
<a-drawer <a-drawer
v-model:open="openDetail" v-model:open="openDetail[filename]"
title="检索详情" title="检索详情"
width="800" width="800"
:contentWrapperStyle="{ maxWidth: '100%'}" :contentWrapperStyle="{ maxWidth: '100%'}"
@ -19,7 +19,7 @@
rootClassName="root" rootClassName="root"
> >
<div class="fileinfo"> <div class="fileinfo">
<p><strong>文件名:</strong> {{ results[0].file.filename }}</p> <p><strong>文件名:</strong> {{ filename }}</p>
<p><strong>文件类型:</strong> {{ results[0].file.type }}</p> <p><strong>文件类型:</strong> {{ results[0].file.type }}</p>
<p><strong>创建时间:</strong> {{ new Date(results[0].file.created_at * 1000).toLocaleString() }}</p> <p><strong>创建时间:</strong> {{ new Date(results[0].file.created_at * 1000).toLocaleString() }}</p>
</div> </div>
@ -47,7 +47,7 @@
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue' import { ref, computed, reactive } from 'vue'
import { import {
GlobalOutlined, GlobalOutlined,
FileTextOutlined, FileTextOutlined,
@ -59,7 +59,18 @@ const props = defineProps({
const message = ref(props.message) const message = ref(props.message)
const openDetail = ref(false) // 使 reactive
const openDetail = reactive({})
// openDetail
for (const filename in message.value.groupedResults) {
openDetail[filename] = false
}
const toggleDrawer = (filename) => {
openDetail[filename] = !openDetail[filename]
}
const showRefs = computed(() => message.value.role=='received' && message.value.status=='finished') const showRefs = computed(() => message.value.role=='received' && message.value.status=='finished')
</script> </script>

View File

@ -10,18 +10,18 @@
</div> </div>
<div class="graph-container layout-container" v-else> <div class="graph-container layout-container" v-else>
<div class="info"> <div class="info">
<h2>图数据库 {{ graph?.database_name }}</h2> <h2>图数据库 {{ graphInfo?.database_name }}</h2>
<p> <p>
<span v-if="state.graphloading">加载中</span> <span v-if="state.loadingGraphInfo">加载中</span>
<span class="green-dot" v-if="graph?.status == 'open'"></span> <span class="green-dot" v-if="graphInfo?.status == 'open'"></span>
<span class="red-dot" v-else></span> <span class="red-dot" v-else></span>
<span>{{ graph?.status }}</span> · <span>{{ graphInfo?.status }}</span> ·
<span> {{ graph?.entity_count }} 实体{{ graph?.relationship_count }} 个关系</span> <span> {{ graphInfo?.entity_count }} 实体{{ graphInfo?.relationship_count }} 个关系</span>
</p> </p>
</div> </div>
<div class="actions"> <div class="actions">
<div class="actions-left"> <div class="actions-left">
<a-button @click="state.showModal = true">上传文件</a-button> <a-button @click="state.showModal = true"><UploadOutlined /> 上传文件</a-button>
<a-modal <a-modal
:open="state.showModal" title="上传文件" :open="state.showModal" title="上传文件"
@ok="addDocumentByFile" @ok="addDocumentByFile"
@ -42,15 +42,15 @@
> >
<p class="ant-upload-text">点击或者把文件拖拽到这里上传</p> <p class="ant-upload-text">点击或者把文件拖拽到这里上传</p>
<p class="ant-upload-hint"> <p class="ant-upload-hint">
目前仅支持上传文本文件 .pdf, .txt, .md且同名文件无法重复添加 目前仅支持上传 jsonl 文件且同名文件无法重复添加
</p> </p>
</a-upload-dragger> </a-upload-dragger>
</div> </div>
</a-modal> </a-modal>
<input v-model="sampleNodeCount"> <input v-model="sampleNodeCount">
<a-button @click="loadSampleNodes">确定</a-button> <a-button @click="loadSampleNodes">获取节点</a-button>
</div> </div>
<div class="action-right"> <div class="actions-right">
<input <input
v-model="state.searchInput" v-model="state.searchInput"
placeholder="输入要查询的实体" placeholder="输入要查询的实体"
@ -75,21 +75,22 @@ import { Graph } from "@antv/g6";
import { computed, onMounted, reactive, ref } from 'vue'; import { computed, onMounted, reactive, ref } from 'vue';
import { message } from "ant-design-vue"; import { message } from "ant-design-vue";
import { useConfigStore } from '@/stores/config'; import { useConfigStore } from '@/stores/config';
import { UploadOutlined } from '@ant-design/icons-vue';
const configStore = useConfigStore() const configStore = useConfigStore()
let graphInstance let graphInstance
const graph = ref(null) const graphInfo = ref(null)
const container = ref(null); const container = ref(null);
const fileList = ref([]); const fileList = ref([]);
const sampleNodeCount = ref(100); const sampleNodeCount = ref(100);
const subgraph = reactive({ const graphData = reactive({
nodes: [], nodes: [],
edges: [], edges: [],
}); });
const state = reactive({ const state = reactive({
graphloading: false, loadingGraphInfo: false,
searchInput: '', searchInput: '',
searchLoading: false, searchLoading: false,
showModal: false, showModal: false,
@ -98,27 +99,27 @@ const state = reactive({
}) })
const loadGraph = () => { const loadGraphInfo = () => {
state.graphloading = true state.loadingGraphInfo = true
fetch('/api/database/graph', { fetch('/api/database/graph', {
method: "GET", method: "GET",
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
console.log(data) console.log(data)
graph.value = data.graph graphInfo.value = data.graph
state.graphloading = false state.loadingGraphInfo = false
}) })
.catch(error => { .catch(error => {
console.error(error) console.error(error)
message.error(error.message) message.error(error.message)
state.graphloading = false state.loadingGraphInfo = false
}) })
} }
const graphData = computed(() => { const getGraphData = () => {
return { return {
nodes: subgraph.nodes.map(node => { nodes: graphData.nodes.map(node => {
return { return {
id: node.id, id: node.id,
data: { data: {
@ -126,7 +127,7 @@ const graphData = computed(() => {
}, },
} }
}), }),
edges: subgraph.edges.map(edge => { edges: graphData.edges.map(edge => {
return { return {
source: edge.source_id, source: edge.source_id,
target: edge.target_id, target: edge.target_id,
@ -136,7 +137,7 @@ const graphData = computed(() => {
} }
}), }),
} }
}) }
const addDocumentByFile = () => { const addDocumentByFile = () => {
state.precessing = true state.precessing = true
@ -168,13 +169,10 @@ const loadSampleNodes = () => {
} }
}) })
.then((data) => { .then((data) => {
subgraph.nodes = data.result.nodes graphData.nodes = data.result.nodes
subgraph.edges = data.result.edges graphData.edges = data.result.edges
console.log(data) console.log(graphData)
console.log(subgraph) randerGraph()
setTimeout(() => {
randerGraph()
}, 500)
}) })
.catch((error) => { .catch((error) => {
message.error(error.message); message.error(error.message);
@ -197,10 +195,10 @@ const onSearch = () => {
} }
}) })
.then((data) => { .then((data) => {
subgraph.nodes = data.result.nodes graphData.nodes = data.result.nodes
subgraph.edges = data.result.edges graphData.edges = data.result.edges
console.log(data) console.log(data)
console.log(subgraph) console.log(graphData)
randerGraph() randerGraph()
}) })
.catch((error) => { .catch((error) => {
@ -210,54 +208,58 @@ const onSearch = () => {
}; };
const randerGraph = () => { const randerGraph = () => {
graphInstance.setData(graphData.value);
if (graphInstance) {
graphInstance.destroy();
}
initGraph();
graphInstance.setData(getGraphData());
graphInstance.render(); graphInstance.render();
} }
const initGraph = () => {
graphInstance = new Graph({
container: container.value,
width: container.value.offsetWidth,
height: container.value.offsetHeight,
autoFit: true,
autoResize: true,
layout: {
type: 'd3-force',
preventOverlap: true,
kr: 20,
collide: {
strength: 1.0,
},
},
node: {
type: 'circle',
style: {
labelText: (d) => d.data.label,
size: 70,
},
palette: {
field: 'label',
color: 'tableau',
},
},
edge: {
type: 'line',
style: {
labelText: (d) => d.data.label,
labelBackground: '#fff',
endArrow: true,
},
},
behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],
});
window.addEventListener('resize', randerGraph);
}
onMounted(() => { onMounted(() => {
loadGraph(); loadGraphInfo();
loadSampleNodes(); loadSampleNodes();
setTimeout(() => {
if (state.showPage) {
graphInstance = new Graph({
container: container.value,
width: container.value.offsetWidth,
height: container.value.offsetHeight,
autoFit: true,
autoResize: true,
layout: {
type: 'd3-force',
preventOverlap: true,
kr: 100,
collide: {
strength: 0.5,
},
},
node: {
type: 'circle',
style: {
labelText: (d) => d.data.label,
size: 40,
},
palette: {
field: 'label',
color: 'tableau',
},
},
edge: {
type: 'line',
style: {
labelText: (d) => d.data.label,
labelBackground: '#fff',
},
},
behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],
});
graphInstance.setData(graphData.value);
graphInstance.render();
window.addEventListener('resize', randerGraph);
}
}, 400)
}); });
@ -303,7 +305,7 @@ const handleDrop = (event) => {
justify-content: space-between; justify-content: space-between;
margin-bottom: 20px; margin-bottom: 20px;
.actions-left { .actions-left, .actions-right {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
@ -311,7 +313,6 @@ const handleDrop = (event) => {
input { input {
width: 100px; width: 100px;
margin-right: 10px;
border-radius: 8px; border-radius: 8px;
padding: 4px 12px; padding: 4px 12px;
border: 2px solid var(--main-300); border: 2px solid var(--main-300);
@ -324,6 +325,7 @@ const handleDrop = (event) => {
} }
button { button {
border-width: 2px;
height: 40px; height: 40px;
box-shadow: none; box-shadow: none;
} }

View File

@ -42,7 +42,8 @@
</a-select> </a-select>
</div> </div>
<div class="card"> <div class="card">
<span class="label">{{ items?.embed_model.des }} &nbsp; <span class="label">
{{ items?.embed_model.des }} &nbsp;
<a-button small v-if="needRestart.embed_model" @click="sendRestart"> <a-button small v-if="needRestart.embed_model" @click="sendRestart">
<ReloadOutlined />需要重启 <ReloadOutlined />需要重启
</a-button> </a-button>
@ -58,7 +59,8 @@
</a-select> </a-select>
</div> </div>
<div class="card"> <div class="card">
<span class="label">{{ items?.reranker.des }} &nbsp; <span class="label">
{{ items?.reranker.des }} &nbsp;
<a-button small v-if="needRestart.reranker" @click="sendRestart"> <a-button small v-if="needRestart.reranker" @click="sendRestart">
<ReloadOutlined />需要重启 <ReloadOutlined />需要重启
</a-button> </a-button>
@ -89,7 +91,11 @@
/> />
</div> </div>
<div class="card"> <div class="card">
<span class="label">{{ items?.enable_knowledge_graph.des }}</span> <span class="label">{{ items?.enable_knowledge_graph.des }}
<a-button small v-if="needRestart.enable_knowledge_graph" @click="sendRestart">
<ReloadOutlined />需要重启
</a-button>
</span>
<a-switch <a-switch
:checked="configStore.config.enable_knowledge_graph" :checked="configStore.config.enable_knowledge_graph"
@change="handleChange('enable_knowledge_graph', !configStore.config.enable_knowledge_graph)" @change="handleChange('enable_knowledge_graph', !configStore.config.enable_knowledge_graph)"
@ -194,6 +200,13 @@ const sendRestart = () => {
.label { .label {
margin-right: 20px; margin-right: 20px;
button {
margin-left: 10px;
height: 24px;
padding: 0 8px;
font-size: smaller;
}
} }
} }