import gzip def gzip_search(query: str, candidate_chunks: list[str], top_k: int=1): """ 文字列ベースで類似したテキストチャンクを推定するアルゴリズム. `query`, `chunk`, および`query + " " + chunk`をそれぞれgzipで圧縮し、編集距離のようなものをベースに評価する. Parameters: query (str): 検索クエリとして使用する文字列. top_k (int, optional): 返される類似チャンクの上位k個を指定する (default: 1). Returns: List[str]: 最も類似したテキストチャンクのリスト. --- Reference: - “Low-Resource” Text Classification: A Parameter-Free Classification Method with Compressors (Jiang et al., Findings 2023) https://aclanthology.org/2023.findings-acl.426/ """ # 圧縮: query => Q Q = gzip.compress(query.encode()) distance_from_Q = {} for chunk in candidate_chunks: # 圧縮: chunk => C (上記のquery => Qと同様) C = gzip.compress(chunk. encode()) # queryとchunkを連結する query_chunk = query + " " + chunk # 共通事項をまとめて表現できるため、この値が小さいほど意味が近いということになる Q_C = gzip.compress(query_chunk. encode()) # 編集距離の計算と似た形で、比較する文字列の長さを正規化する normalized_distance = (len(Q_C) - min(len(Q), len(C))) / max(len(Q), len(C)) distance_from_Q[chunk] = normalized_distance # 最も近い`top_k`個までのチャンクを取得する return sorted(distance_from_Q, key=distance_from_Q.get)[:top_k] # 疑似ローカルデータ candidate_chunks = [ "『北斗の拳』(ほくとのけん)は、武論尊(原作)、原哲夫(作画)による日本の漫画作品。", "『ちいかわ なんか小さくてかわいいやつ』(通称「ちいかわ」)は、稀代の天才漫画家ナガノによる作品。", "国会議事堂(こっかいぎじどう、英: National Diet Building)は、日本の国会が開催される議事堂。", "色覚異常(しきかくいじょう)とは、ヒトの色覚が正常色覚ではない事を示す診断名である。", "ライツアウトは、5×5の形に並んだライトをある法則にしたがってすべて消灯 (lights out) させることを目的としたパズル。" ] query = "ちいかわって誰の作品ですか?" closest = gzip_search(query, candidate_chunks, top_k=1) print(closest) # => ['『ちいかわ なんか小さくてかわいいやつ』(通称「ちいかわ」)は、稀代の天才漫画家ナガノによる作品。'] """ 表現「ちい」「かわ」「作品」などが共通して頻出するため、うまく検索できる """ query = "ルービックキューブとはどういうものですか?" closest = gzip_search(query, candidate_chunks, top_k=1) print(closest) # => ['色覚異常(しきかくいじょう)とは、ヒトの色覚が正常色覚ではない事を示す診断名である。'] """ 最も関連しそうなのはパズルという同カテゴリにある「ライツアウト」に関するチャンクだが、 gzipによる検索は文字列ベースであり、潜在的な意味は拾えないため失敗する。 """