踩坑记录:大模型输出JSON格式错误怎么办?我用Go写了个修复工具
通过这个工具,我基本解决了大模型输出JSON格式错误的问题。现在在项目中使用大模型API时,再也不用担心JSON格式问题了。如果你也遇到类似的问题,可以试试这个工具。当然,最好的解决方案还是在prompt中明确要求模型输出标准JSON格式,但有个兜底的修复工具总是好的。
前言
最近在做一个项目,需要调用各种大模型API来生成结构化数据。本来以为很简单,让大模型输出JSON格式就行了,结果发现这是个大坑!
不管是GPT、Claude还是国产大模型,经常会输出一些格式不完整的JSON:
- 有时候少个括号
- 有时候字符串没闭合
- 有时候直接截断了
- 有时候还会在JSON前面加一些"思考过程"
每次都要手动处理这些错误,实在太麻烦了。于是我决定写个工具来自动修复这些问题。
遇到的典型问题
1. 最常见:缺少结尾括号
{"name": "张三", "age": 30, "skills": ["Go", "Python"
这种情况特别常见,特别是当模型输出被截断时。
2. 键缺少引号
{name: "张三", age: 30}
有些模型会输出这种JavaScript风格的对象,但这不是合法的JSON。
3. 字符串未正确闭合
{"message": "他说:"这是一个测试", "status": "ok"}
当字符串中包含引号时,经常会出现这种问题。
4. 深度嵌套结构错误
{"user": {"name": "张三", "profile": {"email": "test@example.com", "tags": ["tag1", "tag2"
嵌套越深,出错的概率越大。
5. 多JSON对象流被截断
{"event": "start", "id": 1}{"event": "update", "id": 1, "data": {"status": "processing"
当模型输出多个JSON对象时,经常在中间被截断。
解决方案
经过一番研究,我决定用Go语言写一个专门的JSON修复工具。主要思路是:
- 智能解析:逐字符分析JSON结构,理解当前的解析状态
- 上下文推断:根据已解析的内容推断缺失的结构
- 容错处理:对各种异常情况进行兼容处理
- 格式化输出:修复后输出标准的JSON格式
核心实现思路
状态机设计
我设计了一个状态机来跟踪JSON解析的状态:
type ParseState int
const (
StateStart ParseState = iota
StateObject
StateArray
StateString
StateNumber
// ... 其他状态
)
智能修复逻辑
func repairJSON(input string) (string, error) {
// 1. 预处理:去除非JSON前缀
cleanInput := removeNonJSONPrefix(input)
// 2. 逐字符解析,维护状态栈
stack := make([]ParseState, 0)
// 3. 遇到错误时智能修复
// 4. 返回修复后的JSON
}
使用效果
安装使用
go get github.com/qdxiao/llmjsonrepair
简单示例
package main
import (
"fmt"
"log"
"github.com/qdxiao/llmjsonrepair/pkg"
)
func main() {
// 原始的错误JSON
malformedJSON := `{"name": "张三", "age": 30, "skills": ["Go", "Python"`
// 修复并返回格式化的JSON字符串
repairedJSON, err := pkg.Repair(malformedJSON)
if err != nil {
log.Fatal(err)
}
fmt.Println("修复后的JSON:")
fmt.Println(repairedJSON)
// 直接解析为Go数据结构
data, err := pkg.Loads(malformedJSON)
if err != nil {
log.Fatal(err)
}
fmt.Printf("解析后的数据: %+v\n", data)
}
修复效果对比
修复前:
{"name": "张三", "age": 30, "skills": ["Go", "Python"
修复后:
{
"name": "张三",
"age": 30,
"skills": [
"Go",
"Python"
]
}
实际应用场景
1. 大模型API调用
// 调用大模型API
response := callLLMAPI("请生成用户信息的JSON")
// 直接修复并解析,不用担心格式问题
userData, err := pkg.Loads(response)
if err != nil {
log.Printf("修复失败: %v", err)
return
}
// 正常使用数据
fmt.Printf("用户姓名: %s\n", userData.(map[string]interface{})["name"])
2. 批量数据处理
// 处理多个可能有问题的JSON
jsonList := []string{
`{"id": 1, "name": "用户1"`, // 缺少结尾括号
`{id: 2, name: "用户2"}`, // 键缺少引号
`{"id": 3, "name": "用户3"}`, // 正常JSON
}
for i, jsonStr := range jsonList {
data, err := pkg.Loads(jsonStr)
if err != nil {
log.Printf("第%d个JSON修复失败: %v", i+1, err)
continue
}
fmt.Printf("第%d个用户: %+v\n", i+1, data)
}
性能表现
经过测试,这个工具在处理各种错误JSON时表现不错:
- 修复成功率:对常见错误类型的修复成功率达到95%以上
- 性能:单个JSON修复耗时通常在1ms以内
- 内存占用:相比原始JSON大小,内存开销很小
局限性和注意事项
- 极度损坏的JSON:如果JSON损坏程度太严重,可能无法修复
- 语义理解:工具只能修复格式问题,无法理解JSON的业务语义
- 复杂嵌套:对于特别复杂的嵌套结构,修复效果可能不理想
总结
通过这个工具,我基本解决了大模型输出JSON格式错误的问题。现在在项目中使用大模型API时,再也不用担心JSON格式问题了。
如果你也遇到类似的问题,可以试试这个工具。当然,最好的解决方案还是在prompt中明确要求模型输出标准JSON格式,但有个兜底的修复工具总是好的。
项目地址
GitHub: https://github.com/qdxiao/llmjsonrepair
欢迎大家试用和反馈!如果觉得有用的话,给个star支持一下~
相关技术标签: #Go语言 #JSON解析 #大模型 #API开发 #数据处理
遇到问题欢迎交流讨论!
更多推荐
所有评论(0)