feat: 初步接入关系标注

This commit is contained in:
maxmon 2023-04-16 17:49:02 +08:00
parent dec3115831
commit 06d4378c73
4 changed files with 123 additions and 27 deletions

View File

@ -9,6 +9,7 @@ https://tekii.cn/ner
- [x] 命名实体识别
- [x] 文本分类
- [x] 人类反馈强化学习
- [ ] 关系标注
- CV
- [x] 关键点

View File

@ -62,7 +62,13 @@
</span>
<text x="201" y="10" fill="red">关系一</text>
</svg> -->
<div v-if="projectType === '命名实体识别'">
<div v-if="nerProjectType.indexOf(projectType) > -1">
<span class="word" v-for="(word, idx) in nowText" :key="idx" :id="idx" @contextmenu="stopPrev" @mousedown="startSelect(idx, $event)" @touchstart="startSelect(idx, $event)" @touchend="stopSelect()" @mousemove="pointWord(idx)" @touchmove="pointWordByTouch($event)"
>
{{ word }}
</span>
</div>
<div v-if="nerProjectType.indexOf(projectType) > -1">
<div class="word-rect-area">
<span class="rect" v-for="(word, idx) in nowNers" :key="idx">
<span v-for="(w, i) in word.name" :key="`${word}${w}${i}`">
@ -96,12 +102,6 @@
</span>
</div>
</div>
<div v-if="projectType === '命名实体识别'">
<span class="word" v-for="(word, idx) in nowText" :key="idx" :id="idx" @contextmenu="stopPrev" @mousedown="startSelect(idx, $event)" @touchstart="startSelect(idx, $event)" @touchend="stopSelect()" @mousemove="pointWord(idx)" @touchmove="pointWordByTouch($event)"
>
{{ word }}
</span>
</div>
<div v-if="projectType === '文本分类'">
<template v-for="(word, idx) in nowText">
<span class="word" v-if="word !== '\n'" :key="idx" @contextmenu="stopPrev" @mousedown="startSelect(idx, $event)" @mousemove="pointWord(idx)">{{ word }}</span>
@ -110,6 +110,7 @@
</div>
<CVPoint v-if="projectType === '图片点标注'" :fileContent="nowText" :annoDetails="ners" :nowType="nowType" :types="types" :save="save"></CVPoint>
<RLHF v-if="projectType === '人类反馈强化学习'" :fileContent="nowText" :annoDetails="ners" :nowType="nowType" :types="types" :save="save"></RLHF>
<Rel v-if="projectType === '关系标注'" :relDetails="relDetails" :nowType="nowType" :save="save"></Rel>
</div>
<div class="page-btn-box">
<button class="page-btn" @click="changeIdx(-1, $event)" @mouseover="setFocus('page-up')" @mouseleave="setFocus('')">上一个 {{ fastTypeKey['page-up'] ? `${fastTypeKey['page-up']}` : '' }}</button>
@ -136,6 +137,7 @@
import { getColor } from '../../js/color.js'
import CVPoint from '@/components/CV/point.vue'
import RLHF from '@/components/NLP/rlhf.vue'
import Rel from '@/components/NLP/rel.vue'
//
const isLocal = false
@ -192,7 +194,8 @@ export default {
name: 'NER',
components: {
CVPoint,
RLHF
RLHF,
Rel
},
data () {
return {
@ -236,7 +239,10 @@ export default {
wordsOutType: [], //
nersCache: { //
},
mode: '' // 'select'
mode: '', // 'select'
nerProjectType: ['命名实体识别', '关系标注'],
relStartIdx: '',
relDetails: []
}
},
computed: {
@ -319,11 +325,15 @@ export default {
}
const that = this
//
post('/v1/anno/create', {
let annoInfo = {
projectName: that.projectName,
fileName: that.nowFile,
annoDetails: that.ners
})
}
if (that.projectType === '关系标注') {
annoInfo.relDetails = that.relDetails
}
post('/v1/anno/create', annoInfo)
that.$set(that.nersCache, that.nowFile, [...that.ners])
return true
},
@ -419,7 +429,7 @@ export default {
//
return false
}
if (this.projectType === '命名实体识别') {
if (this.nerProjectType.indexOf(this.projectType) > -1) {
this.$set(this, 'nowType', type)
} else if (this.projectType === '文本分类') {
let typeIdx = -1
@ -536,17 +546,19 @@ export default {
}
this.$set(this, 'wordsOutType', this.wordsOutType)
},
delIdx: function (idx) {
getNerIdxByIdx: function (idx) {
const ners = this.ners
for (let i = ners.length - 1; i >= 0; i -= 1) {
const ner = ners[i]
if (idx >= ner.start && idx < ner.end) {
this.del(i)
this.flushWordsType()
return true
return i
}
}
},
delIdx: function (idx) {
const nerIdx = this.getNerIdxByIdx(idx)
this.del(nerIdx)
},
del: function (idx) {
const ners = this.ners
ners.splice(idx, 1)
@ -554,7 +566,21 @@ export default {
this.save() //
},
startSelect: function (idx, event) {
if (this.projectType !== '命名实体识别') return
if (this.nerProjectType.indexOf(this.projectType) === -1) return
if (this.nowType.indexOf('关系-') > -1) {
if (typeof this.relStartIdx === 'number') {
console.log(this.relStartIdx, idx)
this.relDetails.push({
start: this.relStartIdx,
end: idx,
type: this.nowType
})
this.$set(this, 'relStartIdx', undefined)
} else {
this.$set(this, 'relStartIdx', idx)
}
return
}
let that = this
let isNeedDel = false
if (event.touches) {
@ -652,13 +678,7 @@ export default {
outAllNers () {
if (!isLocal) {
// url
if (this.projectType === '命名实体识别') {
window.open(`/v1/files/get_anno_json?projectName=${this.projectName}`, '_self')
} else if (this.projectType === '文本分类') {
window.open(`/v1/files/get_anno_json?projectName=${this.projectName}`, '_self')
} else {
window.open(`/v1/files/get_anno_json?projectName=${this.projectName}`, '_self')
}
window.open(`/v1/files/get_anno_json?projectName=${this.projectName}`, '_self')
return true
}
this.nersCache[this.nowFile] = this.ners
@ -704,7 +724,7 @@ export default {
},
//
isTypeSelected (type) {
if (this.projectType === '命名实体识别') {
if (this.nerProjectType.indexOf(this.projectType) > -1) {
return this.nowType === type
} else if (this.projectType === '文本分类') {
return this.ners.some((ner) => {
@ -717,7 +737,7 @@ export default {
},
watch: {
ners: function () {
if (this.projectType === '命名实体识别') {
if (this.nerProjectType.indexOf(this.projectType) > -1) {
// ner
let nowSmallAreaEnd
for (let i = 0; i < this.ners.length; i++) {
@ -1097,7 +1117,6 @@ export default {
.word-rect-area .rect {
position: absolute;
pointer-events: none;
}
.color-input {

View File

@ -0,0 +1,75 @@
<template>
<div class="rel-box">
<div v-for="(relDetail, idx) in relDetails" :key="idx" class="rel" @click="clickLine(idx)">
<div>{{relDetail}}</div>
</div>
</div>
</template>
<script>
export default ({
name: 'Rel',
props: {
nowType: {
type: String,
default: '1234',
required: true
},
relDetails: {
type: Array,
default: undefined,
required: true
},
save: {
type: Function,
required: true
}
},
data () {
return {
points: [],
width: 0,
height: 0
}
},
methods: {
log (...args) {
console.log(args)
}
},
watch: {
relDetails: {
handler (val) {
console.log(val)
},
deep: true
},
delRel: {
handler (val) {
if (!val) {
return
}
this.relDetails.splice(this.relDetails.indexOf(val), 1)
this.save()
}
},
nowType: {
handler (val) {
if (!val) {
return
}
if (this.annoDetails.indexOf(val) === -1) {
this.annoDetails.push(val)
} else {
this.annoDetails.splice(this.annoDetails.indexOf(val), 1)
}
this.save()
}
}
}
})
</script>
<style scoped>
</style>

View File

@ -29,6 +29,7 @@
<option value ="文本分类">文本分类</option>
<option value ="图片点标注">图片点标注</option>
<option value ="人类反馈强化学习">人类反馈强化学习</option>
<option value ="关系标注">关系标注</option>
</select>
</p>
<div class="title">