Skip to content

Commit

Permalink
Add counter.metaprompt
Browse files Browse the repository at this point in the history
  • Loading branch information
klntsky committed Nov 12, 2024
1 parent 033d686 commit 69d8ebf
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 15 deletions.
7 changes: 7 additions & 0 deletions python/examples/counter.metaprompt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.[:if [:number] is zero or less
:then done!
:else
[:use ./counter
:number=[$ subtract one from [:number].
just give me the resulting number, no other output]]
]
1 change: 1 addition & 0 deletions python/examples/dummy.metaprompt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello world!
5 changes: 5 additions & 0 deletions python/examples/variables.metaprompt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[:foo]
[:foo=bar]
[:baz=[:foo][:foo]]
[:baz]
[:use ./dummy]
22 changes: 22 additions & 0 deletions python/src/config_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from config import Config
from provider_config import ProviderConfig
from providers.interactive import InteractiveProvider
from providers.openai import OpenAIProvider
from dotenv import load_dotenv

import os

load_dotenv()


def load_config():
"""Load configuration from environment variables"""
provider_config = ProviderConfig()

provider_config.merge(InteractiveProvider())

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
if OPENAI_API_KEY is not None:
provider_config.merge(OpenAIProvider(api_key=OPENAI_API_KEY))

return Config(providers=provider_config)
8 changes: 7 additions & 1 deletion python/src/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ async def eval_ast(ast, runtime):
)
old_env = runtime.env
# TODO: persist some variables?
runtime.env = Env(parameters)
evaluated_parameters = {}
for parameter in parameters:
evaluated_parameters[parameter] = await _collect_exprs(
parameters[parameter], runtime
)
runtime.env = Env(evaluated_parameters)
async for expr in eval_ast(loaded_ast, runtime):
yield expr
runtime.env = old_env
Expand All @@ -81,6 +86,7 @@ async def eval_ast(ast, runtime):
async for chunk in eval_ast(ast["condition"], runtime):
condition_chunks.append(chunk)
condition = "".join(condition_chunks)
print(condition)
prompt_result = ""
MAX_RETRIES = 3
retries = 0
Expand Down
13 changes: 7 additions & 6 deletions python/src/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ def _discover_variables(ast):
for node in ast:
yield from _discover_variables(node)
elif isinstance(ast, dict):
if ast["type"] == "comment":
return
elif ast["type"] == "var":
yield {"type": "var", "name": ast["name"]}
elif ast["type"] == "assign":
yield {"type": "assign", "name": ast["name"]}
if "type" in ast:
if ast["type"] == "comment":
return
elif ast["type"] == "var":
yield {"type": "var", "name": ast["name"]}
elif ast["type"] == "assign":
yield {"type": "assign", "name": ast["name"]}
for key in ast:
yield from _discover_variables(ast[key])

Expand Down
25 changes: 19 additions & 6 deletions python/src/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import asyncio
import argparse
from parse_metaprompt import parse_metaprompt
from env import Env
from runtime import Runtime
import os
from config_loader import load_config
from eval import eval_ast


class ParseSetAction(argparse.Action):
Expand All @@ -18,7 +24,7 @@ def parse_arguments():
Parse command-line arguments.
"""
parser = argparse.ArgumentParser(
description="MetaPrompt is a template engine for LLM prompts that supports writing prompts with prompts. Visit https://metaprompt-lang.org/ for more info.",
description="MetaPrompt is a template engine for LLM prompts that supports writing prompts with prompts. Visit https://metaprompt-lang.org/ for more info. Configure API keys via environment variables (.env respected): OPENAI_API_KEY",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)

Expand All @@ -39,15 +45,22 @@ def parse_arguments():
return parser.parse_args()


def main():
async def main():
args = parse_arguments()
print(args)
config = load_config()
config.parameters = dict(args.variables or {})
for file_path in args.INPUT_FILES:
if os.path.isfile(file_path):
with open(file_path, "utf-8") as file:
with open(file_path, "r") as file:
content = file.read()
ast = parse_metaprompt(content)
metaprompt = parse_metaprompt(content)
env = Env(env=config.parameters)
config.model = "gpt-3.5-turbo"
runtime = Runtime(config, env)
runtime.cwd = os.path.dirname(file_path)
async for chunk in eval_ast(metaprompt, runtime):
print(chunk, end="")


if __name__ == "__main__":
main()
asyncio.run(main())
33 changes: 33 additions & 0 deletions python/src/providers/interactive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from provider import BaseLLMProvider
from provider_config import ProviderConfig

from typing import AsyncGenerator


class InteractiveProvider(ProviderConfig):
"""Provider for the interactive CLI interface"""

def __init__(self, api_key: str = None, models=None, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self.add(
'interactive',
InteractiveLLMProvider()
)


class InteractiveLLMProvider(BaseLLMProvider):
def __init__(self, api_key: str = None, model: str = "gpt-4"):
"""Initialize the provider with API key and model name."""
super().__init__()

async def ainvoke(self, prompt: str) -> AsyncGenerator[str, None]:
"""Asynchronously invoke the OpenAI API and yield results in chunks.
Args:
prompt (str): The input prompt for the language model.
Yields:
str: Chunks of the response as they're received.
"""
output = input("[interactive]: " + prompt)
yield output
1 change: 0 additions & 1 deletion python/src/providers/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import openai
import os
from abc import ABC
from typing import AsyncGenerator


Expand Down
2 changes: 1 addition & 1 deletion python/src/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def load_module(self, module_name):
)

if os.path.isfile(file_path):
with open(file_path, "utf-8") as file:
with open(file_path, "r") as file:
content = file.read()
ast = parse_metaprompt(content)
return ast
Expand Down

0 comments on commit 69d8ebf

Please sign in to comment.