maxmon commited on
Commit
c6ad667
1 Parent(s): a79752a

feat: 优化NER和分类的格式化结果

Browse files
.gitignore ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ #.idea/
161
+ data/
162
+ doc/
README.md CHANGED
@@ -1,13 +1,7 @@
1
- ---
2
- title: Auto Anno
3
- emoji: 🚀
4
- colorFrom: indigo
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: 3.29.0
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # 项目介绍
2
+ 一个基于大模型的将输入文本做文本分类,实体抽取并翻译成中文的AI辅助自动标注项目。
3
+
4
+ 其中,文本分类包括:情感分类、新闻分类、意图识别;实体抽取包括:name, type, start~end。
5
+
6
+ # 体验地址
 
 
 
 
 
7
 
 
utils/anno/cls/text_classification.py CHANGED
@@ -1,33 +1,38 @@
1
  import openai
2
  import sys
 
3
  sys.path.append('.')
4
  from local_config import openai_key
 
5
 
6
  # Set up your API key
7
  openai.api_key = openai_key
8
 
9
  def text_classification(src_txt, type_arr):
10
- system = f"你是一个聪明而且有百年经验的文本. 你的任务是从一段文本里面提取出相应的分类结果签。你的回答必须用统一的格式。文本用```符号分割。分类类型保存在一个数组里{type_arr}"
11
- user = f"输入|```这个商品真垃圾```输出|"
12
- assistant = "差评"
13
- input = f"输入|```{src_txt}```输出|"
14
  # Call the OpenAI API
15
  completion = openai.ChatCompletion.create(
16
  model="gpt-3.5-turbo",
17
  messages=[
18
- {"role": "system", "content": f"{system}"},
19
  {"role": "user", "content": f"{user}"},
20
- {"role": "assistant", "content": f"{assistant}"},
21
- {"role": "user", "content": f"{input}"}
22
  ]
23
  )
24
 
25
  # Extract the output and parse the JSON array
26
  content = completion.choices[0].message.content
27
- return content
 
 
 
 
 
 
 
28
 
29
  if __name__ == '__main__':
30
- type_arr = ['好评', '差评']
 
 
31
  txts = [
32
  '这个商品真不错',
33
  '用着不行',
 
1
  import openai
2
  import sys
3
+ import re
4
  sys.path.append('.')
5
  from local_config import openai_key
6
+ from utils.format.txt_2_list import txt_2_list
7
 
8
  # Set up your API key
9
  openai.api_key = openai_key
10
 
11
  def text_classification(src_txt, type_arr):
12
+ user = f"你是一个聪明而且有百年经验的文本分类器. 你的任务是从一段文本里面提取出相应的分类结果签。你的回答必须用统一的格式。文本用```符号分割。分类类型保存在一个数组里{type_arr}\n输入|```{src_txt}```输出|"
 
 
 
13
  # Call the OpenAI API
14
  completion = openai.ChatCompletion.create(
15
  model="gpt-3.5-turbo",
16
  messages=[
 
17
  {"role": "user", "content": f"{user}"},
 
 
18
  ]
19
  )
20
 
21
  # Extract the output and parse the JSON array
22
  content = completion.choices[0].message.content
23
+ # Check out in type_arr
24
+ result = []
25
+ for type in type_arr:
26
+ if type in content:
27
+ result.append(type)
28
+ # 删去已经匹配的type
29
+ content = content.replace(type, '')
30
+ return result
31
 
32
  if __name__ == '__main__':
33
+ # type_arr = ['好评', '差评']
34
+ type_arr_txt = "是差评、不是差评"
35
+ type_arr = txt_2_list(type_arr_txt)
36
  txts = [
37
  '这个商品真不错',
38
  '用着不行',
utils/anno/ner/entity_extract.py CHANGED
@@ -7,6 +7,9 @@ from local_config import openai_key
7
  # Set up your API key
8
  openai.api_key = openai_key
9
 
 
 
 
10
  def extract_named_entities(src_txt, type_arr):
11
  system = f"你是一个聪明而且有百年经验的命名实体识别(NER)识别器. 你的任务是从一段文本里面提取出相应的实体并且给出标签。你的回答必须用统一的格式。文本用```符号分割。输出采用Json的格式并且标记实体在文本中的位置。实体类型保存在一个数组里{type_arr}"
12
  user = f"输入|```皮卡丘神奇宝贝```输出|"
@@ -27,21 +30,31 @@ def extract_named_entities(src_txt, type_arr):
27
  content = completion.choices[0].message.content
28
  print(content)
29
  j = json.loads(content)
30
- return j
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  if __name__ == '__main__':
33
  # extract_named_entities("```汤姆每天都被杰瑞欺负,皮卡丘越来越想帮忙,竟然还总是被拒绝,心想难道我“皮大仙”这点能力都没有?而且,这货不是被虐狂吧```", ["Person", "物种"])
34
- extract_named_entities('老百姓心新乡新闻网话说这几天新乡天气还好吧偷笑', ['代称', '行政区'])
35
- # Tags: PER(人名), LOC(地点名), GPE(行政区名), ORG(机构名)
36
- # Label Tag Meaning
37
- # PER PER.NAM 名字(张三)
38
- # PER.NOM 代称、类别名(穷人)
39
- # LOC LOC.NAM 特指名称(紫玉山庄)
40
- # LOC.NOM 泛称(大峡谷、宾馆)
41
- # GPE GPE.NAM 行政区的名称(北京)
42
- # ORG ORG.NAM 特定机构名称(通惠医院)
43
- # ORG.NOM 泛指名称、统称(文艺公司)
44
- # 原始标注 老百姓PER.NOM 新乡GPE.NAM
45
- # gpt-3.5-turbo [{"name": "老百姓", "type": "代称", "start": 0, "end": 4}, {"name": "新乡新闻网", "type": "组织机构", "start": 4, "end": 10}, {"name": "新乡", "type": "行政区", "start": 12, "end": 14}, {"name": "天气", "type": "自然现象", "start": 14, "end": 16}]
46
- # ERNIE-UIE {"text":"老百姓心新乡新闻网话说这几天新乡天气还好吧偷笑","result":[{"行政区":[{"text":"新乡","start":4,"end":6,"probability":0.589552328738506}]}]}
47
-
 
7
  # Set up your API key
8
  openai.api_key = openai_key
9
 
10
+ def get_ready_key(name, type, start):
11
+ return f'{name}-{type}-{start}'
12
+
13
  def extract_named_entities(src_txt, type_arr):
14
  system = f"你是一个聪明而且有百年经验的命名实体识别(NER)识别器. 你的任务是从一段文本里面提取出相应的实体并且给出标签。你的回答必须用统一的格式。文本用```符号分割。输出采用Json的格式并且标记实体在文本中的位置。实体类型保存在一个数组里{type_arr}"
15
  user = f"输入|```皮卡丘神奇宝贝```输出|"
 
30
  content = completion.choices[0].message.content
31
  print(content)
32
  j = json.loads(content)
33
+ result = []
34
+ j.sort(key=lambda x: x['start']*1000+x['end'])
35
+ ready_keys = set()
36
+ for item in j:
37
+ s = item['start']
38
+ e = item['end']
39
+ # 修正标注错误的实体坐标
40
+ if src_txt[s:e] != item['name']:
41
+ for i in range(len(src_txt)):
42
+ if src_txt[i:i+len(item['name'])] != item['name']:
43
+ continue
44
+ # 跳过匹配过的实体,防止重复匹配
45
+ ready_key = get_ready_key(item['name'], item['type'], i)
46
+ if ready_keys.__contains__(ready_key):
47
+ continue
48
+ item['start'] = i
49
+ item['end'] = i + len(item['name'])
50
+ break
51
+ # 将在实体类型里的放入结果
52
+ result.append(item)
53
+ ready_key = get_ready_key(item['name'], item['type'], item['start'])
54
+ ready_keys.add(ready_key)
55
+ return result
56
 
57
  if __name__ == '__main__':
58
  # extract_named_entities("```汤姆每天都被杰瑞欺负,皮卡丘越来越想帮忙,竟然还总是被拒绝,心想难道我“皮大仙”这点能力都没有?而且,这货不是被虐狂吧```", ["Person", "物种"])
59
+ result = extract_named_entities('老百姓心新乡新闻网话说这几天新乡天气还好吧偷笑', ['代称', '行政区'])
60
+ print(result)
 
 
 
 
 
 
 
 
 
 
 
 
utils/format/txt_2_list.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ def txt_2_list(txt):
4
+ split_token = r'[ ,、,;;《》<>]'
5
+ rm_token = r'["\'”“‘’。.!!?? 【】\[\]]'
6
+
7
+ arr = re.split(split_token, txt)
8
+ arr = [re.sub(rm_token, '', item) for item in arr if item != '']
9
+ # 从大到小排序
10
+ arr.sort(key=lambda x: len(x), reverse=True)
11
+ return arr
utils/prompts/cls/CYFee.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ 你的任务是实现以下操作:\n1 – 对用<>作为分隔符的一段文本进行情感分类。\n2 – 情感分类标签:{类别} 。\n\n使\nJSON格式,包含以下字段:\ntext:<需要进行分类的文本>\nlabel:< {类别} 中选择一个> \ntext: <{原文}>
2
+ 你的任务是实现以下操作:\n1 – 对用<>作为分隔符的一段文本进行分类。\n2 – 情感分类标签: {类别} 。\n使用JSON格式,包含以下字段:\ntext:<需要进行分类的文本>\nlabel:< {类别} 中选择一个> \ntext: <{原文}>
3
+ 你的任务是实现以下操作:\n1 – 对用<>作为分隔符的一段文本进行分类。\n2 – 情感分类标签: {类别} 。\n使用JSON格式,包含以下字段:\ntext:<需要进行分类的文本>\nlabel:<列出所有满足条件的类别>\n\ntext: :<{原文}>
4
+ # 情感分类 0.75
5
+ # 评论分类 0.83
utils/prompts/cls/S13D.md ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ 【{原文}】,用括号内的一个选项({类型})概括上述文本态度,不需要其它字符。
2
+ 【{原文}】,只输出这段话符合的类型({类型}),不要多余字符
3
+ 【{原文}】,只输括号内符合这段话的选项({类型}),不要多余字符
4
+ # 新闻分类 0.9
utils/prompts/cls/Wal-le.md ADDED
@@ -0,0 +1 @@
 
 
1
+ 你是一个聪明而且有百年经验的文本分类器. 你的任务是从一段文本里面提取出相应的分类结果签。你的回答必须用统一的格式。文本用```符号分割。分类类型保存在一个数组里{类别}\n输入|```{原文}```输出|
utils/prompts/cls/の男.md ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ 以下文本表明哪一种意图({类别})请用简短的格式回答例如 {类别1}。文本:{原文}。
2
+ # 意图识别 0.8/0.6 4.0/bing
utils/prompts/ner/Ken.md ADDED
@@ -0,0 +1 @@
 
 
1
+ 你是一个聪明而且有百年经验的命名实体识别(NER)识别器. 你的任务是从一段文本里面提取出相应的实体并且给出标签。你的回答必须用统一的格式。文本用```符号分割。输出采用Json的格式并且标记实体在文本中的位置。实体类型保存在一个数组里{类别}\n输入|```皮卡丘神奇宝贝```输出|[{"name": "皮卡丘", "type": "Person", "start": 0, "end": 3}, {"name": "神奇宝贝", "type": "物种", "start": 4, "end": 8}]\n输入|```{原文}```输出|
utils/prompts/ner/村头小卖部王老板.md ADDED
@@ -0,0 +1 @@
 
 
1
+ 请忘记前面的对话\n请对文本进行NER,并找到每个实体在原文本中的起始位置。文本之间会用"""分隔。\n要求:只保留实体列表中"type"在选项中给出的实体,选项形式为 (选项:"type")\n对每一个在筛选后实体列表中的实体,请按照我的要求来推断出它们的起始位置。要求1: 我们将句子的第一个字认为是位置0,其后的位置依次递增。要求2: 请你逐步找到每个位置的字,直到找到跟实体的第一个字匹配的位置为止。要求3: 实体在原文本中的起始位置的计算直接使用第一个字在原文中的位置即可,不需要往后数出实体的长度。要求4: 逐步思考后的最终结果以json格式呈现,比如[["name":"奥巴马","type":"人物","start":0,"end":3},["name":"美国","type":"国家","start":4,"end":6}]。\n输入:"""{原文}"""(选项:{类别})\n让我们开始逐步思考,并输出最终结果