公司动态
GPT-2 输出格式化实战:一键导出 JSON / 纯文本 / Markdown
GPT-2 输出格式化实战一键导出 JSON / 纯文本 / Markdown【免费下载链接】gpt-2Code for the paper Language Models are Unsupervised Multitask Learners项目地址: https://gitcode.com/GitHub_Trending/gp/gpt-2那天我在做一个内容聚合小工具用 GPT-2OpenAI 开源的语言模型核心生成逻辑在src/sample.py的sample_sequence函数里批量生成商品文案打算直接灌进数据库和 Markdown 文档。结果模型跑得很欢我却傻眼了——所有结果一股脑print到终端既没有结构也没有分隔我拿着正则一行行去抠文本抠到怀疑人生。如果你也遇到过模型能出好文本但输出根本没法用的尴尬这篇文章就是为你写的。改造前 vs 改造后先看效果再动手先看改造前的原始输出两个样本之间只有一行分隔机器没法解析人看着也费劲 SAMPLE 1 人工智能是计算机科学的一个分支致力于创造能够模拟人类智能的系统…… SAMPLE 2 改造后同样的生成逻辑加两个命令行参数输出就变成了这样{ text: 人工智能是计算机科学的一个分支致力于创造能够模拟人类智能的系统……, length: 856, tokens: 156, sample_id: 1, prompt: 什么是人工智能, timestamp: 2026-08-13T16:57:55.123456, model_name: 124M, temperature: 0.7, top_k: 40 }想要 Markdown 就换--output_formatmarkdown想要最朴素的纯文本就换--output_formattext还能用--output_file一键落盘。从只能看到直接能用中间只差一个设计。思路拆解一条生成 → 格式化 → 导出的流水线把输出想成一条流水线三个阶段各司其职生成项目自带的sample_sequence负责出 tokenencoder.decode()转成文本这部分我们一行不改格式化新增一个可插拔的镜头文本进来按 JSON / Markdown / 纯文本的规则加工导出把格式化结果打印到终端或追加写入文件。可插拔翻译成代码就是策略模式每种格式一个类都实现同一个format(text, metadata)接口再用一个工厂按名字取类。以后想加 HTML、CSV不用碰生成逻辑加一个类、注册一行就行。分步实现三步跑通多格式导出动手前先准备代码git clone https://gitcode.com/GitHub_Trending/gp/gpt-2。我们全程只碰三个文件新建src/formatter.py微调src/interactive_conditional_samples.py和src/generate_unconditional_samples.py。第一步新建 src/formatter.py装上三支镜头import json import re class OutputFormatter: 所有格式类的基类定义统一接口 def format(self, text, metadataNone): raise NotImplementedError class PlainTextFormatter(OutputFormatter): def format(self, text, metadataNone): return text # 纯文本原样返回 class JsonFormatter(OutputFormatter): def format(self, text, metadataNone): result {text: text, length: len(text), tokens: len(text.split())} result.update(metadata or {}) # 合并样本元信息 return json.dumps(result, ensure_asciiFalse, indent2) class MarkdownFormatter(OutputFormatter): def format(self, text, metadataNone): md # {}\n\n.format((metadata or {}).get(title, GPT-2 Generated Text)) # 把空行分隔的段落整理成连续行顺便压缩多余空白 paragraphs re.split(r\n\s*\n, text.strip()) md \n\n.join( .join(p.split()) for p in paragraphs) if metadata: md \n\n## 生成信息\n for k, v in metadata.items(): md - **{}**: {}\n.format(k, v) return md class FormatterFactory: 按名字返回对应的格式类实例新增格式在这里注册即可 _registry { text: PlainTextFormatter, json: JsonFormatter, markdown: MarkdownFormatter, } staticmethod def get_formatter(format_type): cls FormatterFactory._registry.get(format_type) if cls is None: raise ValueError(Unsupported format: %s % format_type) return cls()单独写个脚本快速验证FormatterFactory.get_formatter(json).format(你好, {sample_id: 1})应输出合法的 JSON 字符串。✅ 镜头装好了。第二步改造交互式脚本加两个参数打开src/interactive_conditional_samples.py在interact_model函数签名里追加两个参数。因为项目用的是fire库参数会自动变成命令行选项我们一行 CLI 解析代码都不用写def interact_model( model_name124M, seedNone, nsamples1, batch_size1, lengthNone, temperature1, top_k0, top_p1, models_dirmodels, output_formattext, # 新增text / json / markdown output_fileNone, # 新增输出文件路径None 则只打印 ):然后在生成循环里把原来直接print(text)的地方换成格式化 打印 落盘formatter FormatterFactory.get_formatter(output_format) while True: raw_text input(Model prompt ) ... for _ in range(nsamples // batch_size): out sess.run(output, feed_dict{ context: [context_tokens for _ in range(batch_size)] })[:, len(context_tokens):] for i in range(batch_size): generated 1 text enc.decode(out[i]) # 组装元信息让每条样本可追溯 metadata { sample_id: generated, prompt: raw_text, timestamp: datetime.datetime.now().isoformat(), model_name: model_name, temperature: temperature, top_k: top_k, } formatted formatter.format(text, metadata) print( * 40 SAMPLE %d % generated * 40) print(formatted) if output_file: write_sample(output_file, formatted, output_format, generated)别忘了文件头部补import datetime和from formatter import FormatterFactory。第三步批量脚本照葫芦画瓢src/generate_unconditional_samples.py的sample_model结构几乎一样唯一区别是它没有 prompt、用start_token|endoftext|起手。把metadata里的prompt字段去掉其余逻辑原样复制即可。改完后# 交互式JSON 直接落到文件 python src/interactive_conditional_samples.py --model_name124M --output_formatjson --output_filegenerated.json # 批量Markdown 输出到终端 python src/generate_unconditional_samples.py --model_name124M --nsamples5 --length300 --output_formatmarkdown真实翻车现场两个必须绕开的坑坑一JSON 追加写入把文件写坏第一次我图省事非 JSON 格式用open(output_file, a)直接追加JSON 也照抄了——结果文件变成[{...}\n{...}\n]json.load()直接报错前一天的样本全废。JSON 数组要求元素之间必须用逗号分隔。正确做法是写一个专用追加函数文件为空时写数组头非空时把新样本插到结尾的]之前def write_sample(path, formatted, fmt, sample_id): if fmt json: if not os.path.exists(path) or os.path.getsize(path) 0: with open(path, w, encodingutf-8) as f: f.write([\n formatted \n]) # 首个样本开数组 else: with open(path, r, encodingutf-8) as f: f.seek(0, os.SEEK_END) f.seek(f.tell() - 1, os.SEEK_SET) # 回退到结尾的 ] f.write(,\n formatted \n]) # 逗号 新样本 收尾 else: with open(path, a, encodingutf-8) as f: f.write(\n * 40 SAMPLE %d % sample_id * 40 \n) f.write(formatted \n)⚠️ 注意这个技巧假设文件永远以]结尾。所以首条写入和后续写入必须用同一套规则中途千万别手改文件。坑二中文全变 \uXXXX 天书第一次跑 JSON 导出文本里全是\u4eba\u5de5\u667a\u80fd虽然合法但完全不可读。原因是json.dumps默认把非 ASCII 字符转义了。解决办法就是第一步代码里的那行json.dumps(result, ensure_asciiFalse, indent2)同时所有文件读写都显式传encodingutf-8避免某些系统默认编码把你坑了。优化与扩展让这套机制更抗造错误兜底。格式化偶发异常比如文本里混入了奇怪的不可见字符不该让整个生成任务崩掉加一层 try/except失败时回退纯文本并记录日志try: formatted formatter.format(text, metadata) except Exception as e: print(格式转换错误: %s % e) with open(format_errors.log, a, encodingutf-8) as f: f.write(%s sample %d: %s\n % (datetime.datetime.now(), generated, e)) formatted text # 回退到纯文本批量缓冲写。批量生成成百上千条时每条都开关一次文件很伤 I/O。可以先把结果攒进列表跑完一次writelines批量落盘写入耗时能降一个数量级。举一反三加 CSV 只要三步。新建CsvFormatter继承OutputFormatter实现format注意把文本里的引号翻倍转义再往FormatterFactory._registry里注册一行完事。HTML、LaTeX、YAML 全是同一个套路——这就是策略模式加功能不改老代码的价值。顺带一提选格式没有银弹按场景对号入座即可格式适合场景代价JSON数据入库、API 对接、训练集构建人眼阅读不友好纯文本日志、快速预览、命令行工具无结构信息Markdown文档生成、博客创作、README下游需支持解析下一步还能往哪走到这里GPT-2 的输出已经能从终端里的一坨字变成随手可用的结构化数据。如果你还想更进一步有几个方向很自然给formatter.py加一个模板文件加载让 Markdown 的标题、章节由用户自定义或者把格式化逻辑包成一个小函数对外提供做成一个转换 API让别的服务也能复用。动手改 50 行代码换来的是从生成完就结束到生成完直接进业务的跨越。要不要现在就给你的 GPT-2 装上这三支镜头【免费下载链接】gpt-2Code for the paper Language Models are Unsupervised Multitask Learners项目地址: https://gitcode.com/GitHub_Trending/gp/gpt-2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考