Skip to content

Commit d48406b

Browse files
committed
Install redis-gears from S3 as part of module deps, and test AI-Gears LLAPI.
1 parent 620a273 commit d48406b

File tree

3 files changed

+359
-0
lines changed

3 files changed

+359
-0
lines changed

Install_RedisGears.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
if [ -z ${OS+x} ]
2+
then
3+
echo "os is not set"
4+
exit 1
5+
fi
6+
7+
echo "installing redisgears for :" $OS
8+
9+
WORK_DIR=./bin/RedisGears/
10+
REDISGEARS_ZIP=redisgears.linux-$OS-x64.master.zip
11+
REDISGEARS_DEPS=redisgears-python.linux-$OS-x64.master.tgz
12+
REDISGEARS_S3_PATH=http://redismodules.s3.amazonaws.com/redisgears/snapshots/$REDISGEARS_ZIP
13+
REDISGEARS_DEPS_S3_PATH=http://redismodules.s3.amazonaws.com/redisgears/snapshots/$REDISGEARS_DEPS
14+
15+
mkdir -p $WORK_DIR
16+
17+
if [ -f "$WORK_DIR$REDISGEARS_ZIP" ]; then
18+
echo "Skiping RedisGears download"
19+
else
20+
echo "Download RedisGears"
21+
wget -P $WORK_DIR $REDISGEARS_S3_PATH
22+
unzip $WORK_DIR$REDISGEARS_ZIP -d $WORK_DIR
23+
fi
24+
25+
if [ -f "$WORK_DIR$REDISGEARS_DEPS" ]; then
26+
echo "Skiping RedisGears download"
27+
else
28+
echo "Download RedisGears deps"
29+
wget -P $WORK_DIR $REDISGEARS_DEPS_S3_PATH
30+
tar -C $WORK_DIR -xvf $WORK_DIR$REDISGEARS_DEPS
31+
fi

get_deps.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,7 @@ if [[ $WITH_ORT != 0 ]]; then
330330
else
331331
echo "Skipping ONNXRuntime."
332332
fi # WITH_ORT
333+
334+
################################################################################### REDISGEARS
335+
336+
OS=bionic /bin/bash $HERE/Install_RedisGears.sh

tests/flow/tests_withGears.py

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
import redis
2+
3+
from includes import *
4+
import os
5+
from functools import wraps
6+
7+
8+
def skip_if_gears_not_loaded(f):
9+
@wraps(f)
10+
def wrapper(env, *args, **kwargs):
11+
con = env.getConnection()
12+
modules = con.execute_command("MODULE", "LIST")
13+
if b'rg' in [module[1] for module in modules]:
14+
return f(env, *args, **kwargs)
15+
try:
16+
redisgears_path = os.path.join(os.path.dirname(__file__), '../../deps/linux-x64-cpu/bin/RedisGears/redisgears.so')
17+
python_plugin_path = os.path.join(os.path.dirname(__file__), '../../deps/linux-x64-cpu/bin/RedisGears/plugin/gears_python.so')
18+
python_env_path = os.path.join(os.path.dirname(__file__), '../../deps/linux-x64-cpu/bin/RedisGears')
19+
ret = con.execute_command('MODULE', 'LOAD', redisgears_path, 'Plugin', python_plugin_path, 'CreateVenv',
20+
0, 'PythonInstallationDir', python_env_path)
21+
env.assertEqual(ret, b'OK')
22+
except Exception as e:
23+
env.debugPrint(str(e), force=True)
24+
env.debugPrint("skipping since RedisGears not loaded", force=True)
25+
return
26+
return f(env, *args, **kwargs)
27+
return wrapper
28+
29+
30+
@skip_if_gears_not_loaded
31+
def test_ping_gears(env):
32+
33+
script = '''
34+
def ping(record):
35+
return "pong"
36+
37+
GB("CommandReader").map(ping).register(trigger="ping_test")
38+
'''
39+
con = env.getConnection()
40+
ret = con.execute_command('rg.pyexecute', script)
41+
env.assertEqual(ret, b'OK')
42+
ret = con.execute_command('rg.trigger', 'ping_test')
43+
env.assertEqual(ret[0], b'pong')
44+
45+
46+
@skip_if_gears_not_loaded
47+
def ntest_model_run(env):
48+
script = '''
49+
50+
import redisAI
51+
52+
def ModelRun_oldAPI(record):
53+
keys = ['a{1}', 'b{1}']
54+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
55+
modelRunner = redisAI.createModelRunner('m{1}')
56+
redisAI.modelRunnerAddInput(modelRunner, 'a', tensors[0])
57+
redisAI.modelRunnerAddInput(modelRunner, 'b', tensors[1])
58+
redisAI.modelRunnerAddOutput(modelRunner, 'mul')
59+
res = redisAI.modelRunnerRun(modelRunner)
60+
redisAI.setTensorInKey('c{1}', res[0])
61+
return "ModelRun_oldAPI_OK"
62+
63+
async def ModelRun_Async(record):
64+
keys = ['a{1}', 'b{1}']
65+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
66+
modelRunner = redisAI.createModelRunner('m{1}')
67+
redisAI.modelRunnerAddInput(modelRunner, 'a', tensors[0])
68+
redisAI.modelRunnerAddInput(modelRunner, 'b', tensors[1])
69+
redisAI.modelRunnerAddOutput(modelRunner, 'mul')
70+
res = await redisAI.modelRunnerRunAsync(modelRunner)
71+
redisAI.setTensorInKey('c{1}', res[0])
72+
return "ModelRun_Async_OK"
73+
74+
async def ModelRun_AsyncRunError(record):
75+
try:
76+
keys = ['a{1}', 'b{1}']
77+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
78+
modelRunner = redisAI.createModelRunner('m{1}')
79+
res = await redisAI.modelRunnerRunAsync(modelRunner)
80+
return "Error - Exception was not raised"
81+
except Exception as e:
82+
return e
83+
84+
GB("CommandReader").map(ModelRun_oldAPI).register(trigger="ModelRun_oldAPI_test1")
85+
GB("CommandReader").map(ModelRun_Async).register(trigger="ModelRun_Async_test2")
86+
GB("CommandReader").map(ModelRun_AsyncRunError).register(trigger="ModelRun_AsyncRunError_test3")
87+
'''
88+
89+
con = env.getConnection()
90+
ret = con.execute_command('rg.pyexecute', script)
91+
env.assertEqual(ret, b'OK')
92+
93+
test_data_path = os.path.join(os.path.dirname(__file__), 'test_data')
94+
model_filename = os.path.join(test_data_path, 'graph.pb')
95+
96+
with open(model_filename, 'rb') as f:
97+
model_pb = f.read()
98+
99+
ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE,
100+
'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb)
101+
env.assertEqual(ret, b'OK')
102+
103+
con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
104+
con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
105+
106+
ret = con.execute_command('rg.trigger', 'ModelRun_oldAPI_test1')
107+
env.assertEqual(ret[0], b'ModelRun_oldAPI_OK')
108+
values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES')
109+
env.assertEqual(values, [b'4', b'9', b'4', b'9'])
110+
111+
ret = con.execute_command('rg.trigger', 'ModelRun_Async_test2')
112+
env.assertEqual(ret[0], b'ModelRun_Async_OK')
113+
values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES')
114+
env.assertEqual(values, [b'4', b'9', b'4', b'9'])
115+
116+
ret = con.execute_command('rg.trigger', 'ModelRun_AsyncRunError_test3')
117+
# This should raise an exception
118+
env.assertEqual(ret[0].__str__(), "b'Must specify at least one target to fetch or execute.'")
119+
120+
121+
@skip_if_gears_not_loaded
122+
def ntest_script_run(env):
123+
script = '''
124+
125+
import redisAI
126+
127+
def ScriptRun_oldAPI(record):
128+
keys = ['a{1}', 'b{1}']
129+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
130+
scriptRunner = redisAI.createScriptRunner('myscript{1}', 'bar')
131+
redisAI.scriptRunnerAddInput(scriptRunner, tensors[0])
132+
redisAI.scriptRunnerAddInput(scriptRunner, tensors[1])
133+
redisAI.scriptRunnerAddOutput(scriptRunner)
134+
res = redisAI.scriptRunnerRun(scriptRunner)
135+
redisAI.setTensorInKey('c{1}', res[0])
136+
return "ScriptRun_oldAPI_OK"
137+
138+
async def ScriptRun_Async(record):
139+
keys = ['a{1}', 'b{1}']
140+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
141+
scriptRunner = redisAI.createScriptRunner('myscript{1}', 'bar')
142+
redisAI.scriptRunnerAddInput(scriptRunner, tensors[0])
143+
redisAI.scriptRunnerAddInput(scriptRunner, tensors[1])
144+
redisAI.scriptRunnerAddOutput(scriptRunner)
145+
res = await redisAI.scriptRunnerRunAsync(scriptRunner)
146+
redisAI.setTensorInKey('c{1}', res[0])
147+
return "ScriptRun_Async_OK"
148+
149+
async def ScriptRun_AsyncRunError(record):
150+
try:
151+
keys = ['a{1}', 'b{1}']
152+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
153+
scriptRunner = redisAI.createScriptRunner('myscript{1}', 'bad_func')
154+
redisAI.scriptRunnerAddInput(scriptRunner, tensors[0])
155+
redisAI.scriptRunnerAddInput(scriptRunner, tensors[1])
156+
redisAI.scriptRunnerAddOutput(scriptRunner)
157+
res = await redisAI.scriptRunnerRunAsync(scriptRunner)
158+
return "Error - Exception was not raised"
159+
except Exception as e:
160+
return e
161+
162+
GB("CommandReader").map(ScriptRun_oldAPI).register(trigger="ScriptRun_oldAPI_test1")
163+
GB("CommandReader").map(ScriptRun_Async).register(trigger="ScriptRun_Async_test2")
164+
GB("CommandReader").map(ScriptRun_AsyncRunError).register(trigger="ScriptRun_AsyncRunError_test3")
165+
'''
166+
167+
con = env.getConnection()
168+
ret = con.execute_command('rg.pyexecute', script)
169+
env.assertEqual(ret, b'OK')
170+
171+
test_data_path = os.path.join(os.path.dirname(__file__), 'test_data')
172+
script_filename = os.path.join(test_data_path, 'script.txt')
173+
174+
with open(script_filename, 'rb') as f:
175+
script = f.read()
176+
177+
ret = con.execute_command('AI.SCRIPTSET', 'myscript{1}', DEVICE, 'TAG', 'version1', 'SOURCE', script)
178+
env.assertEqual(ret, b'OK')
179+
ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
180+
env.assertEqual(ret, b'OK')
181+
ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
182+
env.assertEqual(ret, b'OK')
183+
184+
ret = con.execute_command('rg.trigger', 'ScriptRun_oldAPI_test1')
185+
env.assertEqual(ret[0], b'ScriptRun_oldAPI_OK')
186+
values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES')
187+
env.assertEqual(values, [b'4', b'6', b'4', b'6'])
188+
189+
ret = con.execute_command('rg.trigger', 'ScriptRun_Async_test2')
190+
env.assertEqual(ret[0], b'ScriptRun_Async_OK')
191+
values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES')
192+
env.assertEqual(values, [b'4', b'6', b'4', b'6'])
193+
194+
ret = con.execute_command('rg.trigger', 'ScriptRun_AsyncRunError_test3')
195+
# This should raise an exception
196+
error_string = b'attempted to get undefined function bad_func'
197+
env.assertEqual(str(ret[0])[:len(error_string)+2]+"'", "{}".format(error_string))
198+
199+
200+
@skip_if_gears_not_loaded
201+
def ntest_DAG_run_via_gears(env):
202+
script = '''
203+
204+
import redisAI
205+
206+
async def DAGRun_tensorSetTensorGet(record):
207+
keys = ['a{1}']
208+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
209+
DAGRunner = redisAI.createDAGRunner()
210+
DAGRunner.TensorSet('tensor_a', tensors[0])
211+
DAGRunner.TensorGet('tensor_a')
212+
res = await DAGRunner.Run()
213+
redisAI.setTensorInKey('test1_res{1}', res[0])
214+
return "test1_OK"
215+
216+
async def DAGRun_simpleModelRun(record):
217+
218+
keys = ['a{1}', 'b{1}']
219+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
220+
DAGRunner = redisAI.createDAGRunner()
221+
DAGRunner.Input('tensor_a', tensors[0])
222+
DAGRunner.Input('tensor_b', tensors[1])
223+
DAGRunner.ModelRun(name='m{1}', inputs=['tensor_a', 'tensor_b'], outputs=['tensor_c'])
224+
DAGRunner.TensorGet('tensor_c')
225+
res = await DAGRunner.Run()
226+
redisAI.setTensorInKey('test2_res{1}', res[0])
227+
return "test2_OK"
228+
229+
async def DAGRun_simpleScriptRun(record):
230+
231+
keys = ['a{1}', 'b{1}']
232+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
233+
DAGRunner = redisAI.createDAGRunner()
234+
DAGRunner.Input('tensor_a', tensors[0])
235+
DAGRunner.Input('tensor_b', tensors[1])
236+
DAGRunner.ScriptRun(name='myscript{1}', func='bar', inputs=['tensor_a', 'tensor_b'], outputs=['tensor_c'])
237+
DAGRunner.TensorGet('tensor_c')
238+
res = await DAGRunner.Run()
239+
redisAI.setTensorInKey('test3_res{1}', res[0])
240+
return "test3_OK"
241+
242+
async def DAGRun_scriptRunError(record):
243+
244+
keys = ['a{1}', 'b{1}']
245+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
246+
DAGRunner = redisAI.createDAGRunner()
247+
DAGRunner.Input('tensor_a', tensors[0])
248+
DAGRunner.Input('tensor_b', tensors[1])
249+
DAGRunner.ScriptRun(name='myscript{1}', func='no_func', inputs=['tensor_a', 'tensor_b'], outputs=['tensor_c'])
250+
DAGRunner.TensorGet('tensor_c')
251+
try:
252+
res = await DAGRunner.Run()
253+
except Exception as e:
254+
return e
255+
256+
async def DAGRun_addOpsFromString(record):
257+
258+
keys = ['a{1}', 'b{1}']
259+
tensors = redisAI.mgetTensorsFromKeyspace(keys)
260+
DAGRunner = redisAI.createDAGRunner()
261+
DAGRunner.Input('tensor_a', tensors[0]).Input('tensor_b', tensors[1])
262+
DAGRunner.OpsFromString('|> AI.MODELRUN m{1} INPUTS tensor_a tensor_b OUTPUTS tensor_c |> AI.TENSORGET tensor_c')
263+
res = await DAGRunner.Run()
264+
redisAI.setTensorInKey('test5_res{1}', res[0])
265+
return "test5_OK"
266+
267+
GB("CommandReader").map(DAGRun_tensorSetTensorGet).register(trigger="DAGRun_test1")
268+
GB("CommandReader").map(DAGRun_simpleModelRun).register(trigger="DAGRun_test2")
269+
GB("CommandReader").map(DAGRun_simpleScriptRun).register(trigger="DAGRun_test3")
270+
GB("CommandReader").map(DAGRun_scriptRunError).register(trigger="DAGRun_test4")
271+
GB("CommandReader").map(DAGRun_addOpsFromString).register(trigger="DAGRun_test5")
272+
'''
273+
274+
con = env.getConnection()
275+
ret = con.execute_command('rg.pyexecute', script)
276+
env.assertEqual(ret, b'OK')
277+
278+
ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
279+
env.assertEqual(ret, b'OK')
280+
ret = con.execute_command('rg.trigger', 'DAGRun_test1')
281+
env.assertEqual(ret[0], b'test1_OK')
282+
283+
values = con.execute_command('AI.TENSORGET', 'test1_res{1}', 'VALUES')
284+
env.assertEqual(values, [b'2', b'3', b'2', b'3'])
285+
286+
con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT',
287+
2, 2, 'VALUES', 2, 3, 2, 3)
288+
test_data_path = os.path.join(os.path.dirname(__file__), 'test_data')
289+
model_filename = os.path.join(test_data_path, 'graph.pb')
290+
291+
with open(model_filename, 'rb') as f:
292+
model_pb = f.read()
293+
ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE,
294+
'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb)
295+
env.assertEqual(ret, b'OK')
296+
ret = con.execute_command('rg.trigger', 'DAGRun_test2')
297+
env.assertEqual(ret[0], b'test2_OK')
298+
299+
values = con.execute_command('AI.TENSORGET', 'test2_res{1}', 'VALUES')
300+
env.assertEqual(values, [b'4', b'9', b'4', b'9'])
301+
302+
script_filename = os.path.join(test_data_path, 'script.txt')
303+
with open(script_filename, 'rb') as f:
304+
script = f.read()
305+
ret = con.execute_command('AI.SCRIPTSET', 'myscript{1}', DEVICE, 'TAG', 'version1', 'SOURCE', script)
306+
env.assertEqual(ret, b'OK')
307+
308+
ret = con.execute_command('rg.trigger', 'DAGRun_test3')
309+
env.assertEqual(ret[0], b'test3_OK')
310+
311+
values = con.execute_command('AI.TENSORGET', 'test3_res{1}', 'VALUES')
312+
env.assertEqual(values, [b'4', b'6', b'4', b'6'])
313+
314+
ret = con.execute_command('rg.trigger', 'DAGRun_test4')
315+
# This should raise an exception
316+
317+
error_string = b'attempted to get undefined function no_func'
318+
env.assertEqual(str(ret[0])[:len(error_string)+2]+"'", "{}".format(error_string))
319+
320+
ret = con.execute_command('rg.trigger', 'DAGRun_test5')
321+
env.assertEqual(ret[0], b'test5_OK')
322+
323+
values = con.execute_command('AI.TENSORGET', 'test5_res{1}', 'VALUES')
324+
env.assertEqual(values, [b'4', b'9', b'4', b'9'])

0 commit comments

Comments
 (0)