docs: add the Laya logo -- SVG sources, PNG renders, README lockup

The mark is one ring in two states: an unbroken stroke that breaks into points,
spirals inward and resolves to a single point. `laya` (लय) is Sanskrit for
dissolution, so the mark reads as that cycle -- becoming and dissolving, neither
one the end -- and doubles as what the model does, a continuous state collapsing
into one typed decision.

  logo-mark.svg/png        blue mark, 512px
  logo-mark-ink.svg/png    same mark in ink, for light print
  logo-mark-mono.svg       currentColor, inherits the surrounding text colour
  logo-lockup.svg/png      mark + wordmark, README header
  logo-lockup-dark.svg/png same with a light wordmark, for GitHub's dark theme

assets/make_logo.py regenerates every file, so the geometry stays editable
rather than being a flattened export.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Nandakishor
2026-09-19 15:22:43 +05:30
co-authored by Claude Opus 5
parent 31280fcfa7
commit f15fe08535
11 changed files with 255 additions and 1 deletions
+10 -1
View File
@@ -1,7 +1,14 @@
# Laya
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/NandhaKishorM/laya/main/assets/logo-lockup-dark.png" />
<img src="https://raw.githubusercontent.com/NandhaKishorM/laya/main/assets/logo-lockup.png" alt="Laya" width="330" />
</picture>
</p>
**Multilingual, non-autoregressive System 1 decision engine.** Typed decisions over 100+ languages in a single forward pass — 33 ms — trained with reinforcement learning against strictly proper scoring rules (RLCD), with a router that picks the right checkpoint per request.
<div align="center">
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/15d4Yv__KHeHjshVb-6PRTfqVllxih2S3?usp=sharing)
[![PyPI version](https://img.shields.io/pypi/v/laya.svg)](https://pypi.org/project/laya/)
[![Hugging Face Model](https://img.shields.io/badge/%F0%9F%A4%97%20Model-convaiinnovations%2Flaya-blue)](https://huggingface.co/convaiinnovations/laya)
@@ -11,6 +18,8 @@
[![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-nandakishorm-FFDD00?logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/nandakishorm)
[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)
</div>
<p align="center">
<img src="https://raw.githubusercontent.com/NandhaKishorM/laya/main/assets/laya_vs_jev_full.png" alt="Laya versus TypeSafe Jev: accuracy on shared public datasets, every application workflow, all 51 languages, speed, calibration, and the cost of not preloading" width="100%" />
</p>
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+22
View File
@@ -0,0 +1,22 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 252 72"
width="252" height="72" role="img" aria-label="Laya">
<title>Laya</title>
<g transform="translate(2.00,5.60) scale(0.950)">
<path d="M 22.141 13.458 A 21.0 21.0 0 1 0 42.500 50.187" fill="none" stroke="#2a78d6" stroke-width="5.0" stroke-linecap="round" opacity="0.95"/>
<circle cx="48.213" cy="42.609" r="2.782" fill="#2a78d6" opacity="0.929"/>
<circle cx="49.456" cy="33.958" r="2.527" fill="#2a78d6" opacity="0.894"/>
<circle cx="46.696" cy="26.535" r="2.291" fill="#2a78d6" opacity="0.852"/>
<circle cx="41.336" cy="21.918" r="2.067" fill="#2a78d6" opacity="0.803"/>
<circle cx="35.242" cy="20.694" r="1.852" fill="#2a78d6" opacity="0.749"/>
<circle cx="30.173" cy="22.422" r="1.642" fill="#2a78d6" opacity="0.691"/>
<circle cx="27.294" cy="25.889" r="1.438" fill="#2a78d6" opacity="0.628"/>
<circle cx="26.902" cy="29.558" r="1.239" fill="#2a78d6" opacity="0.562"/>
<circle cx="28.430" cy="32.075" r="1.043" fill="#2a78d6" opacity="0.493"/>
<circle cx="30.702" cy="32.690" r="0.850" fill="#2a78d6" opacity="0.420"/>
<circle cx="32.00" cy="32.00" r="2.35" fill="#2a78d6"/>
</g>
<text x="70" y="42" font-family="DejaVu Sans, Helvetica Neue, Helvetica, Arial, sans-serif"
font-size="34" font-weight="600" letter-spacing="0.5" fill="#eceef1">laya</text>
<text x="71.5" y="57" font-family="DejaVu Sans, Helvetica Neue, Helvetica, Arial, sans-serif"
font-size="10.5" letter-spacing="2.6" fill="#eceef1" opacity="0.62">DECISIONS, NOT TEXT</text>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+22
View File
@@ -0,0 +1,22 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 252 72"
width="252" height="72" role="img" aria-label="Laya">
<title>Laya</title>
<g transform="translate(2.00,5.60) scale(0.950)">
<path d="M 22.141 13.458 A 21.0 21.0 0 1 0 42.500 50.187" fill="none" stroke="#2a78d6" stroke-width="5.0" stroke-linecap="round" opacity="0.95"/>
<circle cx="48.213" cy="42.609" r="2.782" fill="#2a78d6" opacity="0.929"/>
<circle cx="49.456" cy="33.958" r="2.527" fill="#2a78d6" opacity="0.894"/>
<circle cx="46.696" cy="26.535" r="2.291" fill="#2a78d6" opacity="0.852"/>
<circle cx="41.336" cy="21.918" r="2.067" fill="#2a78d6" opacity="0.803"/>
<circle cx="35.242" cy="20.694" r="1.852" fill="#2a78d6" opacity="0.749"/>
<circle cx="30.173" cy="22.422" r="1.642" fill="#2a78d6" opacity="0.691"/>
<circle cx="27.294" cy="25.889" r="1.438" fill="#2a78d6" opacity="0.628"/>
<circle cx="26.902" cy="29.558" r="1.239" fill="#2a78d6" opacity="0.562"/>
<circle cx="28.430" cy="32.075" r="1.043" fill="#2a78d6" opacity="0.493"/>
<circle cx="30.702" cy="32.690" r="0.850" fill="#2a78d6" opacity="0.420"/>
<circle cx="32.00" cy="32.00" r="2.35" fill="#2a78d6"/>
</g>
<text x="70" y="42" font-family="DejaVu Sans, Helvetica Neue, Helvetica, Arial, sans-serif"
font-size="34" font-weight="600" letter-spacing="0.5" fill="#111111">laya</text>
<text x="71.5" y="57" font-family="DejaVu Sans, Helvetica Neue, Helvetica, Arial, sans-serif"
font-size="10.5" letter-spacing="2.6" fill="#111111" opacity="0.62">DECISIONS, NOT TEXT</text>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+20
View File
@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"
width="64" height="64" role="img" aria-label="Laya">
<title>Laya</title>
<desc>An open stroke whose end breaks into points that spiral inward and shrink to a single
point: becoming, then dissolving into one.</desc>
<g fill="none" stroke="none">
<path d="M 22.141 13.458 A 21.0 21.0 0 1 0 42.500 50.187" stroke="#111111" stroke-width="5.0" stroke-linecap="round" opacity="0.95"/>
<circle cx="48.213" cy="42.609" r="2.782" fill="#111111" opacity="0.929"/>
<circle cx="49.456" cy="33.958" r="2.527" fill="#111111" opacity="0.894"/>
<circle cx="46.696" cy="26.535" r="2.291" fill="#111111" opacity="0.852"/>
<circle cx="41.336" cy="21.918" r="2.067" fill="#111111" opacity="0.803"/>
<circle cx="35.242" cy="20.694" r="1.852" fill="#111111" opacity="0.749"/>
<circle cx="30.173" cy="22.422" r="1.642" fill="#111111" opacity="0.691"/>
<circle cx="27.294" cy="25.889" r="1.438" fill="#111111" opacity="0.628"/>
<circle cx="26.902" cy="29.558" r="1.239" fill="#111111" opacity="0.562"/>
<circle cx="28.430" cy="32.075" r="1.043" fill="#111111" opacity="0.493"/>
<circle cx="30.702" cy="32.690" r="0.850" fill="#111111" opacity="0.420"/>
<circle cx="32.00" cy="32.00" r="2.35" fill="#111111"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+20
View File
@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"
width="64" height="64" role="img" aria-label="Laya">
<title>Laya</title>
<desc>An open stroke whose end breaks into points that spiral inward and shrink to a single
point: becoming, then dissolving into one.</desc>
<g fill="none" stroke="none">
<path d="M 22.141 13.458 A 21.0 21.0 0 1 0 42.500 50.187" stroke="currentColor" stroke-width="5.0" stroke-linecap="round" opacity="0.95"/>
<circle cx="48.213" cy="42.609" r="2.782" fill="currentColor" opacity="0.929"/>
<circle cx="49.456" cy="33.958" r="2.527" fill="currentColor" opacity="0.894"/>
<circle cx="46.696" cy="26.535" r="2.291" fill="currentColor" opacity="0.852"/>
<circle cx="41.336" cy="21.918" r="2.067" fill="currentColor" opacity="0.803"/>
<circle cx="35.242" cy="20.694" r="1.852" fill="currentColor" opacity="0.749"/>
<circle cx="30.173" cy="22.422" r="1.642" fill="currentColor" opacity="0.691"/>
<circle cx="27.294" cy="25.889" r="1.438" fill="currentColor" opacity="0.628"/>
<circle cx="26.902" cy="29.558" r="1.239" fill="currentColor" opacity="0.562"/>
<circle cx="28.430" cy="32.075" r="1.043" fill="currentColor" opacity="0.493"/>
<circle cx="30.702" cy="32.690" r="0.850" fill="currentColor" opacity="0.420"/>
<circle cx="32.00" cy="32.00" r="2.35" fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

+20
View File
@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"
width="64" height="64" role="img" aria-label="Laya">
<title>Laya</title>
<desc>An open stroke whose end breaks into points that spiral inward and shrink to a single
point: becoming, then dissolving into one.</desc>
<g fill="none" stroke="none">
<path d="M 22.141 13.458 A 21.0 21.0 0 1 0 42.500 50.187" stroke="#2a78d6" stroke-width="5.0" stroke-linecap="round" opacity="0.95"/>
<circle cx="48.213" cy="42.609" r="2.782" fill="#2a78d6" opacity="0.929"/>
<circle cx="49.456" cy="33.958" r="2.527" fill="#2a78d6" opacity="0.894"/>
<circle cx="46.696" cy="26.535" r="2.291" fill="#2a78d6" opacity="0.852"/>
<circle cx="41.336" cy="21.918" r="2.067" fill="#2a78d6" opacity="0.803"/>
<circle cx="35.242" cy="20.694" r="1.852" fill="#2a78d6" opacity="0.749"/>
<circle cx="30.173" cy="22.422" r="1.642" fill="#2a78d6" opacity="0.691"/>
<circle cx="27.294" cy="25.889" r="1.438" fill="#2a78d6" opacity="0.628"/>
<circle cx="26.902" cy="29.558" r="1.239" fill="#2a78d6" opacity="0.562"/>
<circle cx="28.430" cy="32.075" r="1.043" fill="#2a78d6" opacity="0.493"/>
<circle cx="30.702" cy="32.690" r="0.850" fill="#2a78d6" opacity="0.420"/>
<circle cx="32.00" cy="32.00" r="2.35" fill="#2a78d6"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+141
View File
@@ -0,0 +1,141 @@
"""Generate the Laya logo: SVG sources plus PNG renders.
The mark is one ring in two states. Half of it is an unbroken stroke; the other half breaks into
points that shrink and fade, and the smallest point sits next to where the stroke begins again --
so the eye closes the loop on its own.
`laya` (लय) is Sanskrit for dissolution. The mark reads as that cycle: becoming and dissolving,
neither one the end. It carries a second meaning specific to this project -- a continuous stroke
resolving into discrete points is what the model does, turning unstructured state into a typed
decision.
python3 notebooks/make_logo.py -> assets/logo-mark.svg logo-mark.png
assets/logo-lockup.svg logo-lockup.png
assets/logo-mark-mono.svg
"""
import math
import os
import subprocess
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ASSETS = os.path.join(REPO, "assets")
os.makedirs(ASSETS, exist_ok=True)
INK = "#111111"
BLUE = "#2a78d6"
PAPER = "#eceef1" # wordmark ink for dark backgrounds
SIZE = 64 # viewBox
CX = CY = 32.0
R = 21.0
STROKE = 5.0
# The stroke covers this sweep; the points cover the rest.
ARC_FROM, ARC_TO = 118.0, 300.0 # degrees, measured counter-clockwise from +x
N_DOTS = 10
DOT_MAX, DOT_MIN = 3.1, 0.85
OP_MAX, OP_MIN = 0.95, 0.42
def pt(deg, r=R):
a = math.radians(deg)
return CX + r * math.cos(a), CY - r * math.sin(a) # SVG y grows downward
def arc_path():
x0, y0 = pt(ARC_FROM)
x1, y1 = pt(ARC_TO)
sweep = (ARC_TO - ARC_FROM) % 360
large = 1 if sweep > 180 else 0
# sweep-flag 0 draws counter-clockwise in SVG's y-down space
return "M %.3f %.3f A %.1f %.1f 0 %d 0 %.3f %.3f" % (x0, y0, R, R, large, x1, y1)
def dots(color):
"""Points leaving the stroke and spiralling inward, shrinking toward a single point.
Inward rather than around: `laya` is absorption, and a ring that dissolves into its own
centre says that where a ring of even dots would just read as a loading spinner. It is also
what the model does -- a spread of options collapsing to one decision.
"""
span = 268.0 # how far the spiral travels before reaching the centre
out = []
for i in range(N_DOTS):
f = (i + 1) / float(N_DOTS)
deg = ARC_TO + span * f
r = R * (1.0 - 0.93 * (f ** 1.08)) # ease inward, ending near the centre
x, y = pt(deg, r)
rr = DOT_MAX + (DOT_MIN - DOT_MAX) * (f ** 0.85)
op = OP_MAX + (OP_MIN - OP_MAX) * (f ** 1.4)
out.append(' <circle cx="%.3f" cy="%.3f" r="%.3f" fill="%s" opacity="%.3f"/>'
% (x, y, rr, color, op))
out.append(' <circle cx="%.2f" cy="%.2f" r="2.35" fill="%s"/>' % (CX, CY, color))
return "\n".join(out)
def mark_svg(color, use_current=False):
c = "currentColor" if use_current else color
return '''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %d %d"
width="%d" height="%d" role="img" aria-label="Laya">
<title>Laya</title>
<desc>An open stroke whose end breaks into points that spiral inward and shrink to a single
point: becoming, then dissolving into one.</desc>
<g fill="none" stroke="none">
<path d="%s" stroke="%s" stroke-width="%.1f" stroke-linecap="round" opacity="0.95"/>
%s
</g>
</svg>
''' % (SIZE, SIZE, SIZE, SIZE, arc_path(), c, STROKE, dots(c))
def lockup_svg(color, text=INK):
"""Mark plus wordmark, left aligned, for README headers.
`text` is the wordmark ink -- dark for light backgrounds, near-white for dark ones, so the
README header stays legible under either GitHub theme.
"""
w, h = 252, 72
s = 0.95 # mark scale inside the lockup
tx, ty = 2, (h - SIZE * s) / 2
return '''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %d %d"
width="%d" height="%d" role="img" aria-label="Laya">
<title>Laya</title>
<g transform="translate(%.2f,%.2f) scale(%.3f)">
<path d="%s" fill="none" stroke="%s" stroke-width="%.1f" stroke-linecap="round" opacity="0.95"/>
%s
</g>
<text x="70" y="%d" font-family="DejaVu Sans, Helvetica Neue, Helvetica, Arial, sans-serif"
font-size="34" font-weight="600" letter-spacing="0.5" fill="%s">laya</text>
<text x="71.5" y="%d" font-family="DejaVu Sans, Helvetica Neue, Helvetica, Arial, sans-serif"
font-size="10.5" letter-spacing="2.6" fill="%s" opacity="0.62">DECISIONS, NOT TEXT</text>
</svg>
''' % (w, h, w, h, tx, ty, s, arc_path(), color, STROKE, dots(color), 42, text, 57, text)
def render(svg_path, png_path, width):
subprocess.run(["rsvg-convert", "-w", str(width), "-a",
"-o", png_path, svg_path], check=True)
return os.path.getsize(png_path)
def main():
files = [
("logo-mark.svg", mark_svg(BLUE), "logo-mark.png", 512),
("logo-mark-ink.svg", mark_svg(INK), "logo-mark-ink.png", 512),
("logo-mark-mono.svg", mark_svg(None, use_current=True), None, None),
("logo-lockup.svg", lockup_svg(BLUE), "logo-lockup.png", 1040),
("logo-lockup-dark.svg", lockup_svg(BLUE, PAPER), "logo-lockup-dark.png", 1040),
]
for name, svg, png, width in files:
sp = os.path.join(ASSETS, name)
with open(sp, "w") as f:
f.write(svg)
line = " %-22s %5d B" % (name, os.path.getsize(sp))
if png:
size = render(sp, os.path.join(ASSETS, png), width)
line += " -> %-20s %6.1f KB" % (png, size / 1024)
print(line)
if __name__ == "__main__":
main()