{"id":20395335,"url":"https://github.com/donny-hikari/mext","last_synced_at":"2026-05-11T15:05:59.067Z","repository":{"id":227553319,"uuid":"769530811","full_name":"Donny-Hikari/mext","owner":"Donny-Hikari","description":"Mext is a powerful text template language designed for crafting prompts for LLM.","archived":false,"fork":false,"pushed_at":"2024-10-20T16:53:09.000Z","size":164,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-20T19:49:47.622Z","etag":null,"topics":["ai","llm","machine-learning","template-language"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Donny-Hikari.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,"publiccode":null,"codemeta":null}},"created_at":"2024-03-09T10:45:22.000Z","updated_at":"2024-10-29T18:44:45.000Z","dependencies_parsed_at":"2024-10-20T19:29:06.703Z","dependency_job_id":null,"html_url":"https://github.com/Donny-Hikari/mext","commit_stats":null,"previous_names":["donny-hikari/mext"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Donny-Hikari/mext","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Donny-Hikari%2Fmext","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Donny-Hikari%2Fmext/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Donny-Hikari%2Fmext/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Donny-Hikari%2Fmext/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Donny-Hikari","download_url":"https://codeload.github.com/Donny-Hikari/mext/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Donny-Hikari%2Fmext/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32900109,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-10T13:40:02.631Z","status":"online","status_checked_at":"2026-05-11T02:00:05.975Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","llm","machine-learning","template-language"],"created_at":"2024-11-15T03:57:12.749Z","updated_at":"2026-05-11T15:05:59.050Z","avatar_url":"https://github.com/Donny-Hikari.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mext\n\nMext is a powerful text template language designed for crafting prompts for LLM.\n\nThe primary objective of Mext is to provide human friendly yet powerful prompt templates for LLM (large language model), emphasizing readability and adaptability.\n\nAt the same time, the versatility of Mext extends its utility beyond, making it a powerful tool for a wide array of text manipulation tasks.\n\nThis README is written with Mext. Source file: [readme_src/README.mext](readme_src/README.mext).\n\n### Early Stage\n\nThe Mext language is still in its early stage.\nNew syntaxes may be introduced and broken changes might be made.\n\n## Table of content\n\n* [Installation](#installation)\n* [Development](#development)\n* [Render Mext file](#render-mext-file)\n* [Usage as a template language](#usage-as-a-template-language)\n* [Render prompts for LLM](#render-prompts-for-llm)\n* [Syntax](#syntax)\n\n## Installation\n\nUse the following command to install mext.\n\n```bash\n$ pip install mext-lang\n```\n\n## Development\n\nTo build and install mext from scratch, clone this repository and use `make`.\n\nThe default target of make will perform testing, cleanup previous build, and install Mext.\n\n```bash\n$ make\n```\n\nTo perform tests, use:\n\n```bash\n$ make test\n```\n\nYou may as well use pip to install an editable version directly:\n\n```bash\n$ pip install -e .\n```\n\n## Render Mext file\n\nYou can render a Mext file handly with [mext/scripts/render_mext.py](mext/scripts/render_mext.py).\n\nUsage:\n\n```bash\n$ python -m mext.scripts.render_mext readme_src/README.mext -o README.md\n```\n\nOr, if you installed mext, the render script will be installed automatically:\n\n```bash\n$ render-mext readme_src/README.mext -o README.md\n```\n\nTo render this README.md with make:\n\n```bash\n$ make README.md\n```\n\nThis will also render the data file [readme_src/README.yaml](readme_src/README.yaml) from [readme_src/README-yaml.mext](readme_src/README-yaml.mext) and [readme_src/README-yaml.yaml](readme_src/README-yaml.yaml).\n\n## Usage as a template language\n\nCheck out the syntax of Mext as well: [Syntax](#syntax)\n\n* [Basic usage](#basic)\n* [Reuse template](#reuse)\n* [Use with statement](#with_template)\n* [Use custom formatters](#register_formatter)\n\n### Basic usage \u003ca id=\"basic\"\u003e\u003c/a\u003e\n\nTo compose a template with Mext, use `Mext.compose`.\n\nPython:\n```python\nfrom mext import Mext\n\nmext = Mext()\nprompt = mext.compose(template=\"\"\"\nThis is an example template.\n{@if not undefined name}\nThe name is: {name}\n{@endif}\n\"\"\", name=\"Yamato\")\nprint(prompt)\n```\n\nOutput:\n```plaintext\nThis is an example template.\nThe name is: Yamato\n```\n### Reuse template \u003ca id=\"reuse\"\u003e\u003c/a\u003e\n\nYou can set a template and use different variables with it.\n\nGiven a tempalte file `reuse.mext`:\n```mext\nThe name is: {@if not novalue name}{name}{@else}Unknown{@endif}\n```\n\nPython:\n```python\nfrom mext import Mext\n\nmext = Mext()\nmext.set_template(template_fn=\"reuse.mext\")\n\nprompt = mext.compose()\nprint(prompt)\n\nprompt = mext.compose(name=\"Sydney\")\nprint(prompt)\n```\n\nOutput:\n```plaintext\nThe name is: Unknown\nThe name is: Sydney\n```\n### Use with statement \u003ca id=\"with_template\"\u003e\u003c/a\u003e\n\nYou can use `use_template` and `use_params` with the `with` statement.\n\nGiven a tempalte file `with_template.mext`:\n```mext\nThis is the profile of {name}:\nname: {name}\ntitle: {title}\nbackend: {backend}\n```\n\nPython:\n```python\nfrom mext import Mext\n\nmext = Mext()\nwith mext.use_template(template_fn=\"with_template.mext\"): # set the template\n  with mext.use_params(name=\"Mike\", title=\"AI Software Engineer\"): # set the parameters for the template\n    prompt = mext.compose(backend=\"Claude 3\")\n    print(prompt)\n\n```\n\nOutput:\n```plaintext\nThis is the profile of Mike:\nname: Mike\ntitle: AI Software Engineer\nbackend: Claude 3\n```\n### Use custom formatters \u003ca id=\"register_formatter\"\u003e\u003c/a\u003e\n\n`register_formatter` is a powerful function that enables custom functions for text processing.\n\nPython:\n```python\nfrom mext import Mext, MextParser\nfrom urllib.parse import quote\n\nparser = MextParser()\nparser.register_formatter('encode_uri_component', quote) # register a custom formatter 'encode_uri_component'\n\nmext = Mext()\nmext.set_parser(parser)\nprompt = mext.compose(template=\"\"\"\n{@format encode_uri_component var}\n\"\"\", params={\n  'var': \"there are some spaces in this sentence\",\n})\nprint(prompt)\n```\n\nOutput:\n```plaintext\nthere%20are%20some%20spaces%20in%20this%20sentence\n```\n\n## Render prompts for LLM\n\nMext can be integrated into existing LLM pipeline easily.\n\n### Integration with Langchain\n\nMext template:\n```mext\nAnswer the following questions one by one:\n{@for q in questions}\n- {q}\n{@endfor}\n\nAnswer:\n```\n\nPython:\n```python\nfrom mext import Mext\n\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfrom langchain_core.output_parsers import StrOutputParser\n\ndef questions2prompt(params):\n  mext = Mext()\n  prompt = mext.compose(template_fn=\"examples/prompts_for_llm.mext\", params=params)\n  print('==== PROMPT ====')\n  print(prompt) # print the prompt for debug purpose\n  return prompt\n\n# Set your api key in environment: OPENAI_API_KEY=\u003cyour_api_key\u003e\nllm = ChatOpenAI(model_name=\"gpt-3.5-turbo\")\noutput_parser = StrOutputParser()\nchain = RunnableLambda(questions2prompt) | llm | output_parser\n\nparams = {\n  \"questions\": [\n    'The distance of sun to earth',\n    'Who is Alan Turing',\n    'What is the name of the planet where the Foundation established?',\n  ],\n}\noutput = chain.invoke(params)\nprint('==== OUTPUT ====')\nprint(output)\n```\n\nExample output:\n```plaintext\n==== PROMPT ====\nAnswer the following questions one by one:\n- The distance of sun to earth\n- Who is Alan Turing\n- What is the name of the planet where the Foundation established?\n\nAnswer:\n==== OUTPUT ====\n1. The distance of the sun to earth is approximately 93 million miles.\n2. Alan Turing was a British mathematician, logician, and computer scientist who is considered one of the founding fathers of computer science.\n3. The name of the planet where the Foundation established is Terminus.\n```\n\nYou can run this example with:\n```bash\n$ python examples/prompts_for_llm.py\n```\n\n## Syntax\n\nNote although the @import syntax is used in most of the examples in this section, in production it is more often that variables are passed to `Mext.compose` as parameters directly. Check out the section [Usage as a template language](\u003c#usage-as-a-template-language\u003e) as well.\n\n* [if](#if)\n* [for](#for)\n* [trim_newline](#trim_newline)\n* [format](#format)\n* [import](#import)\n* [include](#include)\n* [input](#input)\n* [option](#option)\n* [set](#set)\n* [default](#default)\n* [count](#count)\n* [comment](#comment)\n\n### if\n\nTemplate:\n```mext\n{@import \"if.yaml\"}\n\n{@if true}\nThis will be shown.\n{@elif false}\nThis will not be shown.\n{@else}\nThis will not be shown, either.\n{@endif}\n\n{@if not empty var}\n{var}\n{@endif}\n\n{@if not undefined var}\nvar is defined.\n{@endif}\n{@if undefined var2}\nvar2 is undefined.\n{@endif}\n\n{@if novalue var2}\nvar2 has no value.\n{@endif}\n```\n\nGiven params:\n````json\n{\n  \"var\": \"Text from variable.\"\n}\n````\n\nProduce:\n````markdown\nThis will be shown.\n\nText from variable.\n\nvar is defined.\nvar2 is undefined.\n\nvar2 has no value.\n````\n\n### for\n\nTemplate:\n```mext\n{@import \"for.yaml\"}\n\n## Array\n{@for item in arr}\n- name: {item[name]}\n  content: {item[content]}\n{@endfor}\n\n## Dictionary\n{@for item_key, item_val in dict}\n- key: {item_key}\n  val: {item_val}\n{@endfor}\n```\n\nGiven params:\n````json\n{\n  \"arr\": [\n    {\n      \"name\": \"Item 1\",\n      \"content\": \"Content 1\"\n    },\n    {\n      \"name\": \"Item 2\",\n      \"content\": \"Content 2\"\n    }\n  ],\n  \"dict\": {\n    \"key1\": \"Value 1\",\n    \"key2\": \"Value 2\"\n  }\n}\n````\n\nProduce:\n````markdown\n## Array\n- name: Item 1\n  content: Content 1\n- name: Item 2\n  content: Content 2\n\n## Dictionary\n- key: key1\n  val: Value 1\n- key: key2\n  val: Value 2\n````\n\n### trim_newline\n\nTemplate:\n```mext\n@trim_newline if the following next blocks produce empty result until it meets a non-empty block.\n{@trim_newline}\n{@if false}\nThis will be ignored.\n{@endif}\n\n{@trim_newline}\n{@if true}\nThis will be shown right after the line above.\n{@endif}\n\n{@trim_newline}\nThe above and the next new line will not be trimed.\n\nThe end.\n```\n\nProduce:\n````markdown\n@trim_newline if the following next blocks produce empty result until it meets a non-empty block.\nThis will be shown right after the line above.\n\nThe above and the next new line will not be trimed.\n\nThe end.\n````\n\n### format\n\nTemplate:\n```mext\n{@import \"format.yaml\"}\n@format a variable using given format. Formatters can be registered with `parser.register_formatter`.\n{@format json var}\n```\n\nGiven params:\n````json\n{\n  \"var\": {\n    \"abstract\": \"List of fruits to purchase.\",\n    \"fruits\": [\n      \"apple\",\n      \"banana\",\n      \"pear\"\n    ]\n  }\n}\n````\n\nProduce:\n````markdown\n@format a variable using given format. Formatters can be registered with `parser.register_formatter`.\n{\n  \"abstract\": \"List of fruits to purchase.\",\n  \"fruits\": [\n    \"apple\",\n    \"banana\",\n    \"pear\"\n  ]\n}\n````\n\n### import\n\nTemplate:\n````mext\n@import variables from a file.\nFile ends with 'yaml' or 'json' will automatically be loaded as an object. When 'as' clause is present, the object will be loaded as a variable.\n```\n{@import \"import.yaml\" as imported}\n{@format json imported}\n```\n\nIf no 'as' clause is given, first level members of the object will be loaded into the local namespace.\n```\n{@import \"import.yaml\"}\n{imported_var}\n```\n\nOther file type will be loaded as a string variable. Note you must specify the 'as' clause in this case.\nLoaded from \"default.mext\":\n```\n{@import \"default.mext\" as default_mext}\n{default_mext}\n```\n\nUsing variable as filename is also possible.\nLoaded from \"set.mext\":\n```\n{@import imported.set_mext_fn as set_mext}\n{set_mext}\n```\n````\n\nGiven params:\n````json\n{\n  \"imported_var\": \"This variable is imported from a yaml file.\",\n  \"set_mext_fn\": \"set.mext\"\n}\n````\n\nProduce:\n````markdown\n@import variables from a file.\nFile ends with 'yaml' or 'json' will automatically be loaded as an object. When 'as' clause is present, the object will be loaded as a variable.\n```\n{\n  \"imported_var\": \"This variable is imported from a yaml file.\",\n  \"set_mext_fn\": \"set.mext\"\n}\n```\n\nIf no 'as' clause is given, first level members of the object will be loaded into the local namespace.\n```\nThis variable is imported from a yaml file.\n```\n\nOther file type will be loaded as a string variable. Note you must specify the 'as' clause in this case.\nLoaded from \"default.mext\":\n```\n@default will not overwrite the variable.\n{@default var false}\n{@if var}\nvar is true.\n{@else}\nvar is false.\n{@endif}\n\nWhen the variable exists:\n{@import \"default.yaml\"}\n{@default var false}\n{@if var}\nvar is true.\n{@else}\nvar is false.\n{@endif}\n```\n\nUsing variable as filename is also possible.\nLoaded from \"set.mext\":\n```\n{@import \"set.yaml\"}\n@set will overwrite the variable.\n{@set var false}\n{@if var}\nvar is true.\n{@else}\nvar is false.\n{@endif}\n```\n````\n\n### include\n\nTemplate:\n````mext\n@include content from \"default.mext\" file:\n```\n{@include \"default.mext\"}\n```\n\nWith parameters:\n```\n{@include \"default.mext\" var=true}\n```\n````\n\nProduce:\n````markdown\n@include content from \"default.mext\" file:\n```\n@default will not overwrite the variable.\nvar is false.\n\nWhen the variable exists:\nvar is true.\n```\n\nWith parameters:\n```\n@default will not overwrite the variable.\nvar is true.\n\nWhen the variable exists:\nvar is true.\n```\n````\n\n### input\n\nTemplate:\n````mext\n@input set a variable by calling a provided callback.\n{@input var}\n\nUse the `callbacks` parameter to definite a callback dictionary when calling `parser.parse`.\n```\nparser.parse(\n  template=template,\n  template_fn=template_fn,\n  callbacks={{\n    'var': lambda x: 'any function',\n  }},\n)\n```\n````\n\nProduce:\n````markdown\n@input set a variable by calling a provided callback.\nany function\n\nUse the `callbacks` parameter to definite a callback dictionary when calling `parser.parse`.\n```\nparser.parse(\n  template=template,\n  template_fn=template_fn,\n  callbacks={\n    'var': lambda x: 'any function',\n  },\n)\n```\n````\n\n### option\n\nTemplate:\n```mext\n@option controls the behavior of the parser.\n{@option final_strip off}\nThis will keep the empty line below.\n\n```\n\nProduce:\n````plaintext\n@option controls the behavior of the parser.\nThis will keep the empty line below.\n\n````\n\n### set\n\nTemplate:\n```mext\n{@import \"set.yaml\"}\n@set will overwrite the variable.\n{@set var false}\n{@if var}\nvar is true.\n{@else}\nvar is false.\n{@endif}\n```\n\nGiven params:\n````json\n{\n  \"var\": true\n}\n````\n\nProduce:\n````markdown\n@set will overwrite the variable.\nvar is false.\n````\n\n### default\n\nTemplate:\n```mext\n@default will not overwrite the variable.\n{@default var false}\n{@if var}\nvar is true.\n{@else}\nvar is false.\n{@endif}\n\nWhen the variable exists:\n{@import \"default.yaml\"}\n{@default var false}\n{@if var}\nvar is true.\n{@else}\nvar is false.\n{@endif}\n```\n\nGiven params:\n````json\n{\n  \"var\": true\n}\n````\n\nProduce:\n````markdown\n@default will not overwrite the variable.\nvar is false.\n\nWhen the variable exists:\nvar is true.\n````\n\n### count\n\nTemplate:\n```mext\n{@import \"count.yaml\"}\n\n{@set idx 0}\n{@for item in items}\n{@count idx}\n{idx}. {item}\n{@endfor}\n```\n\nGiven params:\n````json\n{\n  \"items\": [\n    \"Item 1\",\n    \"Item 2\",\n    \"Item 3\"\n  ]\n}\n````\n\nProduce:\n````markdown\n1. Item 1\n2. Item 2\n3. Item 3\n````\n\n### comment\n\nTemplate:\n```mext\n@comment will not be shown in the result.\n{@comment}\nThis will be ignored.\n{@endcomment}\n```\n\nProduce:\n````markdown\n@comment will not be shown in the result.\n````","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonny-hikari%2Fmext","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdonny-hikari%2Fmext","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonny-hikari%2Fmext/lists"}