{"id":15175569,"url":"https://github.com/jrhizor/elelem","last_synced_at":"2025-10-06T10:31:48.565Z","repository":{"id":194665262,"uuid":"690326242","full_name":"jrhizor/elelem","owner":"jrhizor","description":"Simple, opinionated, JSON-typed, and traced LLM framework for TypeScript.","archived":false,"fork":false,"pushed_at":"2024-03-11T22:01:53.000Z","size":90,"stargazers_count":35,"open_issues_count":7,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-14T07:42:01.975Z","etag":null,"topics":["ai","cohere","llm","openai"],"latest_commit_sha":null,"homepage":"https://www.mealbymeal.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jrhizor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-09-12T01:32:42.000Z","updated_at":"2024-11-21T07:05:55.000Z","dependencies_parsed_at":"2023-09-14T14:47:18.131Z","dependency_job_id":"b08b719c-0366-46cd-a645-d5b21c558d0d","html_url":"https://github.com/jrhizor/elelem","commit_stats":null,"previous_names":["jrhizor/elelem"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhizor%2Felelem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhizor%2Felelem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhizor%2Felelem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhizor%2Felelem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jrhizor","download_url":"https://codeload.github.com/jrhizor/elelem/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235519907,"owners_count":19003201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","cohere","llm","openai"],"created_at":"2024-09-27T12:39:30.860Z","updated_at":"2025-10-06T10:31:43.256Z","avatar_url":"https://github.com/jrhizor.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"![Elelem](images/elelem.png)\n\n# Elelem\nElelem is a simple, opinionated, JSON-typed, and traced LLM framework in TypeScript.\n\n## Why another LLM library?\n\nIn September 2023, I tried to port [MealByMeal](https://mealbymeal.com/), a production LLM-based application, over to LangChain. \nCaching wasn't supported for chat-based endpoints (specifically for `gpt-3.5-turbo`).\nAdditionally, the interface for interacting with these endpoints felt quite awkward.\nSince then, LangChain Expression Language (LCEL) was introduced, but handling and enforcing typed outputs is still repetitive and error-prone. \nFurthermore, without leveraging `gpt-4`, the structured outputs are seldom valid. \nFor debugging nuances like retries and parsing errors, the in-built tracing leaves much to be desired.\nAll of these issues led me to create my own lightweight library.\n\n## How does Elelem compare to LangChain?\n\n| Feature                                       | Elelem | Langchain |\n|-----------------------------------------------|--------|-----------|\n| TypeScript library                            | ✅      | ✅         |\n| OpenAI generation support                     | ✅      | ✅         |\n| Cohere generation support                     | ✅      | ✅         |\n| Anthropic generation support                  | ✅      | ✅         |\n| Emphasis on typed LLM outputs                 | ✅      | ❌         |\n| Easily composable multi-step LLM workflows    | ✅      | ❌         |\n| Convenient API for single chat completions    | ✅      | ❌         |\n| Caching for OpenAI chat endpoints             | ✅      | ❌         |\n| OpenTelemetry support                         | ✅      | ❌         |\n| Autogenerated JSON examples in prompts        | ✅      | ❌         |\n| Python library                                | ❌      | ✅         |\n| Support for many models (Claude, Llama, etc.) | ❌      | ✅         |\n| Vector store support                          | ❌      | ✅         |\n| A million other features                      | ❌      | ✅         |\n\n## Example\n\nInstall with `npm install elelem` or `yarn add elelem`.\n\nYou'll need `yarn add zod openai` and `yarn add ioredis` if you're using Redis for caching (see `src/elelem.test.ts` for an example of setting up caching).\n\nUsage:\n```typescript\nimport { z } from \"zod\";\nimport OpenAI from \"openai\";\nimport { elelem, JsonSchemaAndExampleFormatter } from \"elelem\";\n\nconst capitolResponseSchema = z.object({\n    capitol: z.string(),\n});\n\nconst cityResponseSchema = z.object({\n    foundingYear: z.string(),\n    populationEstimate: z.number(),\n});\n\nconst llm = elelem.init({\n    openai: new OpenAI({ apiKey: process.env.OPENAI_API_KEY })\n});\n\nconst inputCountry = \"USA\";\n\n(async () =\u003e {\n    const { result, usage } = await llm.session(\n        \"capitol-info-retriever\",\n        { openai: { model: \"gpt-3.5-turbo\" } },\n        async (c) =\u003e {\n            const { result: capitol } = await c.openai(\n                \"get-capitol\",\n                { max_tokens: 100, temperature: 0 },\n                `What is the capitol of the country provided?`,\n                inputCountry,\n                capitolResponseSchema,\n                JsonSchemaAndExampleFormatter,\n            );\n\n            const { result: cityDescription } = await c.openai(\n                \"city-description\",\n                { max_tokens: 100, temperature: 0 },\n                `For the given capitol city, return the founding year and an estimate of the population of the city.`,\n                capitol.capitol,\n                cityResponseSchema,\n                JsonSchemaAndExampleFormatter,\n            );\n\n            return cityDescription;\n        },\n    );\n\n    console.log(result);\n    // { foundingYear: '1790', populationEstimate: 705749 }\n\n    console.log(usage);\n    // {\n    //     completion_tokens: 26,\n    //     prompt_tokens: 695,\n    //     total_tokens: 721,\n    //     cost_usd: 0.0010945\n    // }\n})();\n```\n\n## Viewing Traces on Jaeger\n\nStart [Jaeger](https://www.jaegertracing.io/) locally using:\n```\ndocker run --rm --name jaeger \\\n  -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \\\n  -p 6831:6831/udp \\\n  -p 6832:6832/udp \\\n  -p 5778:5778 \\\n  -p 16686:16686 \\\n  -p 4317:4317 \\\n  -p 4318:4318 \\\n  -p 14250:14250 \\\n  -p 14268:14268 \\\n  -p 14269:14269 \\\n  -p 9411:9411 \\\n  jaegertracing/all-in-one:1.49\n```\n\nAllow publishing traces to Jaeger with the following:\n```typescript\nimport * as opentelemetry from \"@opentelemetry/sdk-node\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-proto\";\n\nconst sdk = new opentelemetry.NodeSDK({\n    serviceName: \"your-service-name\",\n    traceExporter: new OTLPTraceExporter(),\n});\nsdk.start();\n\n// rest of your code...\n\nprocess.on('SIGTERM', () =\u003e {\n    sdk.shutdown()\n        .then(() =\u003e console.log('Tracing terminated'))\n        .catch((error) =\u003e console.log('Error terminating tracing', error))\n        .finally(() =\u003e process.exit(0));\n});\n```\n\nWhen you run your code, your traces will be available at http://localhost:16686/.\n\n### What do the traces look like in Jaeger?\n\n![Exploring Traces in Jaeger](https://i.imgur.com/1DGWd6O.gif)\n\n### Tracing in Production\n\nSee the [OpenTelemetry docs](https://opentelemetry.io/docs/instrumentation/js/exporters/) for more information on sending traces to hosted instances of Zipkin, Jaeger, Datadog, etc.\n\n## Contributing\n\nPull requests are welcome. For major changes, please open an issue first\nto discuss what you would like to change.\n\nPlease make sure to update tests as appropriate.\n\n## For Contributors: Running Integration Tests\n\nTo run tests, first make sure you have Git, Yarn, and Docker installed. Then checkout the repo and install dependencies:\n```\ngit clone git@github.com:jrhizor/elelem.git\ncd elelem\nyarn install\n```\n\nCreate a `.env` file:\n```\nOPENAI_API_KEY=\u003cyour key\u003e\nREDIS=redis://localhost:6379\n```\n\nStart up Redis:\n```\ndocker run -it -p 6379:6379 redis\n```\n\nStart up Jaeger:\n```\ndocker run --rm --name jaeger \\\n  -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \\\n  -p 6831:6831/udp \\\n  -p 6832:6832/udp \\\n  -p 5778:5778 \\\n  -p 16686:16686 \\\n  -p 4317:4317 \\\n  -p 4318:4318 \\\n  -p 14250:14250 \\\n  -p 14268:14268 \\\n  -p 14269:14269 \\\n  -p 9411:9411 \\\n  jaegertracing/all-in-one:1.49\n```\n\nNow you're ready to run the unit and integration tests:\n```\nyarn test\n```\n\n## License\n\n[MIT](https://choosealicense.com/licenses/mit/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrhizor%2Felelem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjrhizor%2Felelem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrhizor%2Felelem/lists"}