Spaces:
Running
Running
#!/usr/bin/python3 | |
# -*- coding: utf-8 -*- | |
import difflib | |
from typing import List, Tuple | |
import editdistance | |
from project_settings import project_path | |
from toolbox.string.tokenization import FastTokenizer | |
class ChunkSearcher(object): | |
def __init__(self, | |
vocab_file: str = (project_path / "data/vocab.txt").as_posix() | |
): | |
# 需要一个多语言的分词器. (找一个多语言 bert 的词汇表). | |
self.tokenizer = self.init_tokenizer(vocab_file) | |
def init_tokenizer(vocab_file): | |
tokenizer = FastTokenizer() | |
with open(vocab_file, "r", encoding="utf-8") as f: | |
for row in f: | |
token = str(row).strip() | |
tokenizer.insert(token) | |
return tokenizer | |
def chunk_search(self, chunk: str, content: str, win_size_radio: float = 1.5): | |
chunk_tokens, _ = self.tokenizer.tokenize(chunk) | |
content_tokens, _ = self.tokenizer.tokenize(content) | |
counter = [0] * len(content_tokens) | |
win_score = [0] * len(content_tokens) | |
for token1 in chunk_tokens: | |
if len(token1.strip()) == 0: | |
continue | |
for idx, token2 in enumerate(content_tokens): | |
if token1 == token2: | |
counter[idx] = 1 | |
win_size = len(chunk_tokens) * win_size_radio | |
win_size = int(win_size) | |
for begin in range(0, len(content_tokens) - win_size, 1): | |
win = counter[begin: begin+win_size] | |
score = sum(win) | |
win_score[begin] = score | |
idx = win_score.index(max(win_score)) | |
match = content_tokens[idx: idx+win_size] | |
match_content = "".join(match) | |
match_content = self.rstrip_match_content(chunk, match_content) | |
match_content = self.rstrip_match_content(chunk[::-1], match_content[::-1]) | |
match_content = match_content[::-1] | |
return match_content | |
def rstrip_match_content(self, chunk: str, match_content: str): | |
differ = difflib.Differ() | |
diff = differ.compare(match_content, chunk) | |
operation_list = list() | |
for d in diff: | |
operation = d[0] | |
operation_list.append(operation) | |
r_strip_count = 0 | |
for operation in reversed(operation_list): | |
if operation != "-": | |
break | |
r_strip_count += 1 | |
if r_strip_count != 0: | |
match_content = match_content[:-r_strip_count].strip() | |
return match_content | |
class ChunkSimilarity(object): | |
def edit_distance(self, chunk: str, match_content: str) -> List[Tuple[str, float, str]]: | |
edit_distance = editdistance.distance(chunk, match_content) | |
chunk_length = len(chunk) | |
content_length = len(match_content) | |
normalized_edit_distance = edit_distance / (chunk_length + content_length) | |
normalized_edit_distance2 = 2 * edit_distance / (chunk_length + content_length) | |
result = [ | |
("edit_distance", edit_distance, ""), | |
( | |
"ed_score", round(1 - normalized_edit_distance, 4), | |
"1 - d / (l1 + l2)" | |
), | |
( | |
"ed_score2", round(1 - normalized_edit_distance2, 4), | |
"1 - 2*d / (l1 + l2)" | |
), | |
] | |
return result | |
def seq_match(self, chunk: str, match_content: str) -> List[Tuple[str, str, str]]: | |
seq_match = difflib.SequenceMatcher() | |
seq_match.set_seqs(chunk, match_content) | |
score = seq_match.ratio() | |
result = [ | |
("seq_match", round(score, 4), "(2.0*M / T) similar to edit_distance"), | |
] | |
return result | |
def similar(self, chunk: str, match_content: str): | |
result = [ | |
("metric", "score", "note") | |
] | |
scores = self.edit_distance(chunk, match_content) | |
result.extend(scores) | |
scores = self.seq_match(chunk, match_content) | |
result.extend(scores) | |
return result | |
PAGE_CONTENT = """ | |
40 | |
麦肯锡中国金融业 CEO季刊 2023年秋季刊 | |
2023年人工智能发展现状: | |
生成式 AI的突破之年 | |
Michael Chui ,Eric Hazan ,Lareina Yee ,Bryce Hall ,Alex Singla | |
和Alexander Sukharevsky如 今 ,生 成 式 AI工具遍地开花, 各组织均在快速部署; 麦肯锡调查的 | |
受访者们预计, 该技术将对自己所在行业及就业产生重大影响。 | |
41 | |
2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年 | |
麦肯锡针对人工智能发展现状的最新年度全球调研结果证实, 生 | |
成式人工智能 (简称 GenAI )工 具 已 出 现 爆 炸 式 增 长 。许 多 此 类 工 | |
具 至 今 推 出 尚 不 满 一 年 ,但 已 有 1/3的 受 访 者 表 示 ,其 所 在 组 织 会 在 | |
至少一项业务职能中经常使 用 GenAI 。 随着这些最新进展, 人工智 | |
能 已 经 从 一 个 技 术 话 题 上 升 为 企 业 领 导 的 关 注 焦 点 :近 1/4受访高 | |
管 表 示 ,他 们 会 在 工 作 中 使 用 GenAI 工具; 而在已应用人工智能的 | |
企 业 中,有 超 过 1/4的受访者表示 GenAI 已 被 列 入 董 事 会 议 程 。此 外 , | |
40% 的受访者表示, 其所在组织将会因 GenAI 的最新进 展而增加对 | |
人工智能的整体投入。 调查结果表明, GenAI 相关风险管理仍处于 | |
早期阶段: 即便是针对受访者眼中最常见的不准确问题, 也只有不 | |
""" | |
CHUNK = """2023年人工智能发展现状:生成式AI的突破之年""" | |
CHUNK1 = """ | |
Among these PEFT methods, the reparameterization-based method low-rank adaptation (LoRA) (Hu et al.,2021) is considered one of the most efficient and effective methods at present. | |
LoRA is especially popular after open-sourced LLMs become ubiquitous (Dettmers et al., 2023). | |
LoRA assumes that the change of the model’s parameters for adaptation is intrinsically low-dimensional and performs adaptation by optimizing the matrix obtained from low-rank decomposition. | |
Since it is in the form of weight matrix reparameterization, LoRA parameters can be merged with the original LLMs and cause no forward propagation latency. | |
""" | |
def main(): | |
from project_settings import project_path | |
searcher = ChunkSearcher() | |
match_content = searcher.chunk_search( | |
CHUNK, | |
PAGE_CONTENT, | |
win_size_radio=1.6, | |
) | |
print(match_content) | |
chunk_similarity = ChunkSimilarity() | |
scores = chunk_similarity.similar(CHUNK, match_content) | |
print(scores) | |
return | |
if __name__ == "__main__": | |
main() | |