{"id":28633678,"url":"https://github.com/nallwhy/lang_schema","last_synced_at":"2025-06-12T15:09:35.660Z","repository":{"id":289965820,"uuid":"972724356","full_name":"nallwhy/lang_schema","owner":"nallwhy","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-08T12:00:44.000Z","size":32,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-11T03:41:14.817Z","etag":null,"topics":["ai","elixir"],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/nallwhy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-25T14:53:12.000Z","updated_at":"2025-05-09T05:51:22.000Z","dependencies_parsed_at":"2025-04-26T03:09:06.523Z","dependency_job_id":"1a19ec12-4f8e-4c1a-8a7e-b3f0bfff52a9","html_url":"https://github.com/nallwhy/lang_schema","commit_stats":null,"previous_names":["nallwhy/lang_schema"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nallwhy/lang_schema","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nallwhy%2Flang_schema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nallwhy%2Flang_schema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nallwhy%2Flang_schema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nallwhy%2Flang_schema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nallwhy","download_url":"https://codeload.github.com/nallwhy/lang_schema/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nallwhy%2Flang_schema/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259490550,"owners_count":22865769,"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","elixir"],"created_at":"2025-06-12T15:09:32.238Z","updated_at":"2025-06-12T15:09:35.644Z","avatar_url":"https://github.com/nallwhy.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Module Version](https://img.shields.io/hexpm/v/lang_schema.svg)](https://hex.pm/packages/lang_schema)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/lang_schema)\n\n# LangSchema\n\nConverts an abstract schema into JSON schemas required by various AI providers, minimizing code changes when switching providers.\n\n## Design Goals\n\nLangSchema aims to define an abstract schema that can be commonly applied across different AI providers, allowing you to switch providers without modifying your original schema. While provider-specific features are not entirely excluded, supporting every custom feature is not the primary goal. Instead, LangSchema prioritizes raising errors when a schema might implicitly behave incorrectly due to differences between providers, making such issues explicit and easier to fix.\n\n## Concepts\n\n- **Abstract Schema**: A subset of JSON Schema that is primarily used to define structured outputs or function parameters for AI providers. It aims to maintain an independent expression without being tied to any specific provider. For an example, see [schema.ex](https://github.com/nallwhy/lang_schema/blob/main/test/support/schema.ex).\n- **JSON Schema**: The concrete output generated by converting the abstract schema to match the specific requirements of each AI provider.\n\n## Built-in Supported AI providers\n\n- OpenAI: [LangSchema.Converter.OpenAI](./lib/lang_schema/converter/openai.ex)\n- Gemini: [LangSchema.Converter.Gemini](./lib/lang_schema/converter/gemini.ex)\n\n## Writing a Custom Converter\n\nYou can create your own converter for a new AI provider by implementing the `LangSchema.Converter` behaviour.\n\nHere's a simple example based on the OpenAI converter:\n\n```elixir\ndefmodule MyApp.LangSchema.Converter.MyProvider do\n  use LangSchema.Converter\n\n  @impl LangSchema.Converter\n  def wrap(json_schema, opts) do\n    name = Keyword.get(opts, :name, \"response\")\n\n    %{\n      \"name\" =\u003e name,\n      \"schema\" =\u003e json_schema\n    }\n  end\n\n  @impl LangSchema.Converter\n  def types() do\n    # Add type converters\n    %{\n      integer: MyApp.LangSchema.Type.MyProvider.Integer,\n      number: MyApp.LangSchema.Type.MyProvider.Number,\n      string: MyApp.LangSchema.Type.MyProvider.String,\n      array: MyApp.LangSchema.Type.MyProvider.Array,\n      object: MyApp.LangSchema.Type.MyProvider.Object\n    }\n  end\n\n  @impl LangSchema.Converter\n  def allowed_combinations() do\n    # List only the combinations your provider supports, e.g., :any_of, :one_of, :all_of\n    [:any_of] \n  end\n\n  @impl LangSchema.Converter\n  def keywords() do\n    %{\n      # Add keyword converters\n      nullable: MyApp.LangSchema.Keyword.MyProvider.Nullable\n    }\n  end\nend\n```\n\n## Installation\n\nThe package can be installed by adding `lang_schema` to your list of dependencies\nin `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:lang_schema, \"~\u003e 0.3.0\"}\n  ]\nend\n```\n\n## Relationship with Elixir LangChain\n\nElixir [LangChain](https://hex.pm/packages/langchain) provides support for structured output using `json_schema` for chat and `parameters_schema` for functions. By leveraging LangSchema with LangChain, you can seamlessly switch between AI providers without changing your code, maintaining a unified schema approach across different integrations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnallwhy%2Flang_schema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnallwhy%2Flang_schema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnallwhy%2Flang_schema/lists"}