テキスト検索ランダム応答.py
bsahd.icon
主な動作
1. テキストをプロンプトで検索する
2. 検索結果をランダムに選ぶ
3. ランダムに選んだものの次の文字をプロンプトに追加する
使い方
1. コーパスを準備する
2. クローンしたテキストをcorpus.txtに結合する
$ find /path/to/クローン先ディレクトリ -name text.txt -exec echo "<EOF>" \; -exec cat {} \; > corpus.txt
2. 実行する
1. 下に書かれてるpythonコードをコピペしてcorpus.txtとtextgen.pyという名前で保存する
2. 実行する
$ python3 textgen.py "プロンプト"
多分コーパスファイルの大きさの2倍くらいメモリ食う
高速に動くように設計している(検索部分がライブラリ内のネイティブコード)だが、PythonがPythonなので遅いかも
238MBのコーパスで482MBメモリ使用
fab-wiki, forum-jp, help-jp, masui, nishio, plurality-japanese, shiology, shokai, stao, suto3, takker, tanehouse, villagepump, work4ai, arpla をクローンして結合した
プロンプトが1文字など極端に短い場合は一時的に大食いします
スライディング曖昧検索を実装したい
速度的に遅すぎた
機能詳細
--maxchar バイト数
指定したバイト数生成して終了する
標準では無制限
--ctx バイト数
最大のコンテキスト長
指定しない場合無制限
--bpi バイト数
1回の検索で指定したバイト数応答する
標準で1
--randomness X
X=1だと既存の文章をなぞることが多い
そのためソースを明示できる
X=2以上の場合、既存の文章をなぞりにくくなる
支離滅裂な文章が相当増える
ソースの絞り込みが困難
bpi 2以上との併用は推奨しない
標準では1
--stop 文字列
指定した文字列が出現したときに終了
空文字列で永久動作
maxcharも指定している場合、どちらかの条件に達したときに終了される
標準で<EOF>
code:textgen.py
import time
bootstart=time.perf_counter()
import re,random,sys,argparse,json
parser = argparse.ArgumentParser()
parser.add_argument('prompt', type=str, help='prompt to start generating')
parser.add_argument('--maxchar', type=int, help='max generate bytes')
parser.add_argument('--ctx', type=int, help='ctx bytes length')
parser.add_argument('--bpi', type=int, help='bytes per iteration',default=1)
parser.add_argument('--randomness', type=int, help='minimum pplx',default=1)
parser.add_argument('--stop', type=str, help='Stop string', default="<EOF>")
parser.add_argument('--verbose', action='store_true')
args = parser.parse_args()
prompt=str(args.prompt).encode()
stop = str(args.stop).encode()
with open("corpus.txt","rb") as f:
s = f.read()
stext = s.lower()
charcount = 0
if args.verbose:
print("起動時間:",time.perf_counter() - bootstart,"秒")
print("byte\tpplx\tctx")
else:
print(prompt.decode(),end="",flush=True)
def trydecode(baito):
decodepattern = [
(0,-1),(0,-2),(0,-3),(0,-4),(0,-5),
(1,-1),(1,-2),(1,-3),(1,-4),(1,-5),
(2,-1),(2,-2),(2,-3),(2,-4),(2,-5),
(3,-1),(3,-2),(3,-3),(3,-4),(3,-5),
(4,-1),(4,-2),(4,-3),(4,-4),(4,-5),
]
for a in decodepattern:
try:
return ("?"*a0)+baito[a0:a1].decode()+("?"*(-1-a1)) except UnicodeDecodeError:
continue
return "ERROR"
while True:
if prompt==b"":
prompt=b"\n"
if len(result) < args.randomness:
if args.verbose:
print("\t"+str(len(result))+"\t"+json.dumps(trydecode(prompt),ensure_ascii=False))
continue
ncpos = random.choice(result)1 prompt=prompt + nextchar
charcount += 1
if args.ctx:
if args.verbose:
print(nextchar.hex()+"\t"+str(len(result))+"\t"+json.dumps(trydecode(prompt),ensure_ascii=False))
else:
sys.stdout.buffer.write(nextchar)
sys.stdout.buffer.flush()
if (stop != "" and stop in prompt) or (args.maxchar and args.maxchar < charcount):
break