π§ Extensive LLM endpoints, expended capabilities through your favorite protocols, πΈοΈ GraphQL,
- Grouping
- Intelli-routing
- Load balancing
- Semantic cache
- Structured data
- Powered by Neuri
- JSON
- Support any order of structured data
- JSON streaming support
- JSON tokenizer & parser
- Code snippet
- WASM with vscode-textmate
- Function calling
- Instruction mapping
- Generative streaming
- Advanced tracing
- Inference tracking
- OpenAI
- GraphQL
- gRPC
- WebSockets
- RESTful
.
βββ apis # Protobuf files
β βββ jsonapi # Shared definitions
β βββ gatewayapi # Business APIs of Gateway
βββ cmd # Entry for microservices
βββ config # Configuration files
βββ graph # GraphQL Schemas, gqlgen configurations
βββ hack # Scripts for both development, testing, deployment
βββ internal # Actual implementation
β βββ configs # Configuration
β βββ constants # Constants
β βββ graph # GraphQL server & model & resolvers
β βββ grpc # gRPC server and client
β βββ libs # Libraries
β βββ meta # Metadata
βββ logs # Logs, excluded from git
βββ pkg # Public APIs
βββ production # Production related deployment, configurations and scripts
βββ release # Release bundles, excluded from git
βββ tools # Tools
β βββ tools.go # Pinned tools
βββ .dockerignore # Docker ignore file
βββ .editorconfig # Editor configuration
βββ .gitignore # Git ignore file
βββ .golangci.yml # GolangCI configuration
βββ buf.gen.yaml # How .proto under apis/ are generated
βββ buf.yaml # How buf is configured
βββ cspell.config.yaml # CSpell configuration
βββ docker-compose.yml # Docker compose file, for bootstrapping the needed external services like db, redis, etc.
Copy the config.example.yaml
to config.yaml
and update the values as needed.
cp config.example.yaml config.yaml
Note
When developing locally, you can use the config.local.yaml
file to override both testing and production configurations without need to worry
about accidentally committing sensitive information since it is ignored by git.
Besides configurations, you can always use environment variables to override the configurations as well.
Every microservice and its entry should have similar build steps and usage as follows.
go build \
-a \
-o "release/lingticio/llmg-grpc" \
-ldflags " -X './internal/meta.Version=1.0.0' -X './internal/meta.LastCommit=abcdefg'" \
"./cmd/lingticio/llmg-grpc"
docker build \
--build-arg="BUILD_VERSION=1.0.0" \
--build-arg="BUILD_LAST_COMMIT=abcdefg" \
-f cmd/lingticio/llmg-grpc/Dockerfile \
.
With config/config.yaml
:
go run cmd/lingticio/llmg-grpc
With config.local.yaml
:
go run cmd/lingticio/llmg-grpc -c $(pwd)/config/config.local.yaml
We use gqlgen
to generate the GraphQL server and client codes based on the schema defined in the graph/${category}/*.graphqls
file.
go generate ./...
Once generated, you can start the server and test the queries, mutations, and subscriptions from internal/graph/${category}/*.resolvers.go
.
buf dep update
chmod +x ./hack/proto-export
./hack/proto-export
We use buf
to manage and generate the APIs based on the Protobuf files.
Follow the instructions here: Buf - Install the Buf CLI
buf dep update
Create new Protobuf files under the apis
directory as following guidelines:
.
apis
βββ jsonapi # <shared defs, such as jsonapi>
β βββ jsonapi.proto
βββ coreapi # <api group, such as api, adminapi, you can categorize them by business>
βββ v1 # <version, such as v1>
βββ v1.proto
go install github.com/grpc-ecosystem/protoc-gen-grpc-gateway-ts
Run the following command to generate the needed files:
buf generate
The generated files includes:
*.gw.go
files for gRPC-Gateway*.pb.go
files for gRPC server and client*.swagger.json
files for Swagger UI
Then you are off to go.
To test the gRPC clients and all sorts of objects like this, as well as meet the SOLID principle, we use a library called counterfeiter to generate test doubles and quickly mock out the dependencies for both local defined and third party interfaces.
Generally all the generated test doubles are generated under the fake
directory that located in the same package as the original interface.
After you have updated the interface, you can run the following command to update and generate the test doubles again freshly:
go generate ./...
First you need to ensure the following comment annotation has been added to the package where you hold all the initial references to the interfaces in order to make sure the go generate
command can find the interfaces:
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
If the above comment annotation hasn't yet been added, add one please.
Then you can add the following comment annotation to tell counterfeiter to generate the test doubles for the interface:
//counterfeiter:generate -o <relative path to store the generated test doubles> --fake-name <the name of the generated fake test double, usually starts with Fake> <where the counterfeiter can find the interface> <the interface name>
For example:
//counterfeiter:generate -o fake/some_client.go --fake-name FakeClient . Client
type Client struct {
Method() string
}
//counterfeiter:generate -o <relative path to store the generated test doubles> --fake-name <the name of the generated fake test double, usually starts with Fake> <the import path of the interface>
For example:
import (
"github.com/some/package"
)
//counterfeiter:generate -o fake/some_client.go --fake-name FakeClient github.com/some/package.Client
var (
client package.Client
)
- Heavily inspired by Portkey.ai
- Heavily inspired by AI Gateway - LLM API Solution | Kong Inc.
- Heavily inspired by Unify: The Best LLM on Every Prompt
- lm-sys/RouteLLM: A framework for serving and evaluating LLM routers - save LLM costs without compromising quality!
Thanks to everyone who contributed to the this project!