Using TOON for LLMs

What is TOON?

Toon stands for Token-Oriented Object Notation, you might ask why use this over JSON, well JSON includes some unnecessary syntax – such as commas and curly brackets – that are used separate or enclose blocks of data, but in LLMs these extra characters are counted as additional tokens, which can increase your api calling costs.

TOON solves this problem by providing a more compact, token-efficient format that keeps your data both optimized and human-readable, while using fewer tokens overall.

More detailed article about toon →


Get the Roblox version here:

Source Code
local function _getTableType(t) -- thanks to XAXA for this function
	if next(t) == nil then return "Empty" end
	local isArray = true
	local isDictionary = true
	for k, _ in next, t do
		if typeof(k) == "number" and k%1 == 0 and k > 0 then
			isDictionary = false
		else
			isArray = false
		end
	end
	if isArray then
		return "Array"
	elseif isDictionary then
		return "Dictionary"
	else
		return "Mixed"
	end
end

local function getDictionaryLength(val)
	local count = 0
	for _ in val do
		count += 1
	end
	return count
end

local function _stringify(v)
	if typeof(v) == "string" then
		if string.find(v, " ") or string.find(v, '"') then
			return `"{v}"`
		else
			return v
		end
	elseif typeof(v) == "boolean" then
		return v and "true" or "false"
	else
		return tostring(v)
	end
end

local function trim(s)
	return s:match("^%s*(.-)%s*$")
end

local function _encodeTable(tbl, indent)
	local str = ""
	for key, value in tbl do
		local prefix = string.rep("  ", indent)
		if typeof(value) == "table" then
			local tableType = _getTableType(value)
			if tableType == "Empty" then
				str ..= `{prefix}{key}[0]:\n`
			elseif tableType == "Array" then
				if #value == 0 then
					str ..= `{prefix}{key}[0]:\n`
				elseif typeof(value[1]) == "table" then
					local first = value[1]
					local length = #value
					local keys = {}
					for k in first do
						table.insert(keys, k)
					end
					str ..= prefix .. key .. "[" .. length .. "]{" .. table.concat(keys, ",") .. "}:\n"
					for _, v in value do
						local vals = {}
						for _, k in keys do
							table.insert(vals, _stringify(v[k]))
						end
						str ..= `{prefix}  {table.concat(vals, ",")}\n`
					end
				else
					str ..= `{prefix}{key}[{#value}]: `
					local vals = {}
					for _, v in value do
						table.insert(vals, _stringify(v))
					end
					str ..= `{table.concat(vals, ",")}\n`
				end
			elseif tableType == "Dictionary" then
				if next(value) == nil then
					str ..= `{prefix}{key}[0]:\n`
				else
					str ..= `{prefix}{key}:\n`
					str ..= _encodeTable(value, indent + 1)
				end
			end
		else
			str ..= `{prefix}{key}: {_stringify(value)}\n`
		end
	end
	return str
end

return function(tbl)
	if not tbl then return "" end
	return _encodeTable(tbl, 0)
end

Usage:

local data = {
	name = 'Alice',
	age = 30,
	hobbies = {'reading', 'gaming', 'hiking'},
	results = {
		english = 15,
		spanish = 20,
		maths = 20
	},
	logs = {
		{name = "Gym", timestamp = 1240125920, present = true},
		{name = "English", timestamp = 1240126920, present = false};
	}
}

local encoded = Toon.encode(data)
print(encoded)

Benchmarks

Default json:

TOON:

Hope this module helps, feel free to edit it however you like, you can add support for vectors, color3s cframe and other data types.

6 Likes

is this able to compress things NOT ai related?
i use a serializing system i wanna know if i can compress my JSONEncode data easier using this if i switch to Toon

This is not recommended if you use nested json with large amount of data, its only useful if its a flat json.

You can read the article to learn more.