-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing py-tuple py-list py-dict py-chain #671
Changes from 3 commits
22ef306
a99ec53
9c46072
564a233
1385469
43d865e
03f688e
03cc598
0f733de
6051d1b
247b800
43dffe2
37adfb4
073527d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
import os | ||
|
||
from .atoms import ExpressionAtom, E, GroundedAtom, OperationAtom, ValueAtom, NoReduceError, AtomType, MatchableObject, \ | ||
G, S, Atoms | ||
G, S, Atoms, ValueObject, OperationObject | ||
from .base import Tokenizer, SExprParser | ||
from .ext import register_atoms, register_tokens | ||
import hyperonpy as hp | ||
|
@@ -212,3 +212,52 @@ def load_ascii_atom(space, name): | |
return { | ||
r"load-ascii": loadAtom | ||
} | ||
|
||
def groundedatom_to_python_object(a): | ||
obj = a.get_object() | ||
if isinstance(obj, ValueObject): | ||
obj = obj.value | ||
if isinstance(obj, OperationObject): | ||
obj = obj.content | ||
return obj | ||
|
||
# convert nested tuples to nested python tuples or lists | ||
def _py_tuple_list(tuple_list, *atoms): | ||
rez = [] | ||
for a in atoms: | ||
if isinstance(a, GroundedAtom): | ||
rez.append(groundedatom_to_python_object(a)) | ||
elif isinstance(a, ExpressionAtom): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to add one more or you see some problems with it? (py-tulple (user "some message)) is not working now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in this case it is better to add it directly in groundedatom_to_python_object. @Necr0x0Der What do you think about it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turning arbitrary atoms to Python objects is generally useful. The problem is that there can be some difference how we would like to do this. In particular, in some cases we would like to distinguish, say, |
||
rez.append(_py_tuple_list(tuple_list, *a.get_children())) | ||
return tuple_list(rez) | ||
|
||
def py_tuple(*atoms): | ||
return [ValueAtom(_py_tuple_list(tuple, *atoms))] | ||
|
||
def py_list(*atoms): | ||
return [ValueAtom(_py_tuple_list(list, *atoms))] | ||
|
||
def tuple_to_keyvalue(a): | ||
ac = a.get_children() | ||
if len(ac) != 2: | ||
raise Exception("Syntax error in tuple_to_keyvalue") | ||
return groundedatom_to_python_object(ac[0]), groundedatom_to_python_object(ac[1]) | ||
|
||
# convert pair of tuples to python dictionary | ||
def py_dict(*atoms): | ||
return [ValueAtom(dict([tuple_to_keyvalue(a) for a in atoms]))] | ||
|
||
# chain python objects with | (syntactic sugar for langchain) | ||
def py_chain(*atoms): | ||
objects = [groundedatom_to_python_object(a) for a in atoms] | ||
result = objects[0] | ||
for obj in objects[1:]: | ||
result = result | obj | ||
return [ValueAtom(result)] | ||
|
||
@register_atoms() | ||
def py_funs(): | ||
return {"py-tuple": OperationAtom("py-tuple", py_tuple, unwrap = False), | ||
"py-list": OperationAtom("py-list", py_list, unwrap = False), | ||
"py-dict": OperationAtom("py-dict", py_dict, unwrap = False), | ||
"py-chain": OperationAtom("py-chain", py_chain, unwrap = False)} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,10 @@ | ||
!(import! &self simple_import) | ||
|
||
!(import_from example_01 import simple_fun) | ||
!(import_from example_01 import SimpleObject) | ||
!(bind! simple_fun (py-atom example_01.simple_fun)) | ||
!(bind! SimpleObject (py-atom example_01.SimpleObject)) | ||
|
||
!(bind! so (SimpleObject)) | ||
|
||
|
||
; it is important that obj will have type SimpleObject when passed to simple_fun! | ||
!(simple_fun 1 2 "3" (kwarg1 2) (obj so) ) | ||
!(simple_fun 1 2 "3" (Kwargs (kwarg1 2) (obj so)) ) | ||
|
||
!(call_dot so method "arg1" "arg2" (arg3 3)) | ||
!( (py-dot so method) "arg1" "arg2" (Kwargs (arg3 3)) ) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,16 @@ | ||
!(import! &self simple_import) | ||
!(bind! np (py-atom numpy)) | ||
|
||
!(import_as numpy as np) | ||
!(bind! a1 ( (py-dot np array) (py-atom (py-tuple 1 2 3) ))) | ||
!(bind! a2 ( (py-dot a1 __mul__) 3)) | ||
!(bind! a3 ( (py-dot a1 __add__) a2)) | ||
|
||
!(bind! a1 (call_dot np array (ptuple 1 2 3) )) | ||
!(bind! a2 (call_dot a1 __mul__ 3)) | ||
!(bind! a3 (call_dot a1 __add__ a2)) | ||
|
||
!(a1) | ||
!(a2) | ||
!(a3) | ||
|
||
!(__unwrap a1) | ||
!(__unwrap a2) | ||
!(__unwrap a3) | ||
!(bind! m1 ((py-dot np array) (py-atom (py-list (1 2 3) (py-list 4 4 5) (py-tuple 6 7 8)) ))) | ||
!(bind! linalg (py-atom numpy.linalg)) | ||
!(bind! m1_inv ( (py-dot linalg inv) m1)) | ||
|
||
!(bind! m1 (call_dot np array (ptuple (1 2 3) (4 4 5) (6 7 8)) )) | ||
!(import_as numpy.linalg as linalg) | ||
!(bind! m1_inv (call_dot linalg inv m1)) | ||
|
||
!(__unwrap (call_dot np matmul m1 m1_inv)) | ||
!( (py-dot np matmul) m1 m1_inv) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,18 @@ | ||
!(import! &self simple_import) | ||
!(bind! ChatOpenAI (py-atom langchain_openai.ChatOpenAI)) | ||
!(bind! ChatPromptTemplate (py-atom langchain_core.prompts.ChatPromptTemplate)) | ||
!(bind! StrOutputParser (py-atom langchain_core.output_parsers.StrOutputParser)) | ||
|
||
!(import_from langchain_openai import ChatOpenAI) | ||
!(import_from langchain_core.prompts import ChatPromptTemplate) | ||
!(import_from langchain_core.output_parsers import StrOutputParser) | ||
!(bind! model (ChatOpenAI (Kwargs (temperature 0) (model "gpt-3.5-turbo")))) | ||
|
||
!(bind! prompt ( (py-dot ChatPromptTemplate from_template) "tell me a joke about cat")) | ||
|
||
!(bind! model (ChatOpenAI (temperature 0) (model "gpt-3.5-turbo"))) | ||
!(bind! chain1 (py-chain prompt model (StrOutputParser) )) | ||
|
||
!(bind! prompt (call_dot ChatPromptTemplate from_template "tell me a joke about cat")) | ||
!( (py-dot chain1 invoke) (py-dict)) | ||
|
||
!(bind! chain1 (chain prompt model (StrOutputParser) )) | ||
!(bind! prompt2 ( (py-dot ChatPromptTemplate from_messages ) (py-tuple ("system" "You are very funny") ("user" "tell me joke about {foo}")))) | ||
|
||
!(__unwrap(call_dot chain1 invoke (pdict))) | ||
!(bind! chain2 (py-chain prompt2 model (StrOutputParser) )) | ||
|
||
!(bind! prompt2 (call_dot ChatPromptTemplate from_messages (ptuple ("system" "You are very funny") ("user" "tell me joke about {foo}")))) | ||
|
||
!(bind! chain2 (chain prompt2 model (StrOutputParser) )) | ||
|
||
!(__unwrap(call_dot chain2 invoke (pdict (foo "dogs") ))) | ||
!((py-dot chain2 invoke) (py-dict ("foo" "dogs"))) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,6 @@ | ||
!(import! &self simple_import) | ||
!(bind! linalg (py-atom numpy.linalg)) | ||
!(bind! numpy (py-atom numpy)) | ||
|
||
; with simple "import" it is rather common that we import something | ||
; twice because of submodules in python | ||
; So let's import twice to make sure that it does not cause any problems | ||
!(import numpy) | ||
!(import numpy) | ||
!(import numpy.linalg) | ||
|
||
|
||
!(bind! m1 (call_dot2 numpy random rand 3 3 )) | ||
!(bind! m1_inv (call_dot2 numpy linalg inv m1)) | ||
|
||
!(__unwrap (call_dot numpy matmul m1 m1_inv)) | ||
!(bind! m1 ((py-dot numpy random.rand) 3 3 )) | ||
!(bind! m1_inv ( (py-dot linalg inv) m1)) | ||
!( (py-dot numpy matmul) m1 m1_inv) |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this function is needed with such implementation. You don't need to check if the type is
ValueObject
orOperationObject
. Both of them havecontent
field (andvalue
orop
getter). If there are no other checks, thengroundedatom_to_python_object(a)
is the same asobj.get_object().content
. The latter is even shorter.