Skip to content

Commit 5223ccd

Browse files
committed
fixes #13
1 parent 096d376 commit 5223ccd

3 files changed

Lines changed: 206 additions & 14 deletions

File tree

dialoghelper/_modidx.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
'dialoghelper.core.import_dialog': ('core.html#import_dialog', 'dialoghelper/core.py'),
2020
'dialoghelper.core.import_gist': ('core.html#import_gist', 'dialoghelper/core.py'),
2121
'dialoghelper.core.import_string': ('core.html#import_string', 'dialoghelper/core.py'),
22+
'dialoghelper.core.is_usable_tool': ('core.html#is_usable_tool', 'dialoghelper/core.py'),
2223
'dialoghelper.core.load_gist': ('core.html#load_gist', 'dialoghelper/core.py'),
24+
'dialoghelper.core.mk_toollist': ('core.html#mk_toollist', 'dialoghelper/core.py'),
2325
'dialoghelper.core.msg_idx': ('core.html#msg_idx', 'dialoghelper/core.py'),
2426
'dialoghelper.core.read_msg': ('core.html#read_msg', 'dialoghelper/core.py'),
2527
'dialoghelper.core.read_msg_ids': ('core.html#read_msg_ids', 'dialoghelper/core.py'),

dialoghelper/core.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.
22

33
# %% auto 0
4-
__all__ = ['Placements', 'get_db', 'find_var', 'find_dialog_id', 'find_msgs', 'find_msg_id', 'read_msg_ids', 'msg_idx',
5-
'read_msg', 'add_msg', 'update_msg', 'add_html', 'load_gist', 'gist_file', 'import_string', 'import_gist',
6-
'export_dialog', 'import_dialog', 'asdict']
4+
__all__ = ['Placements', 'empty', 'get_db', 'find_var', 'find_dialog_id', 'find_msgs', 'find_msg_id', 'read_msg_ids', 'msg_idx',
5+
'read_msg', 'add_msg', 'update_msg', 'add_html', 'load_gist', 'gist_file', 'import_string', 'is_usable_tool',
6+
'mk_toollist', 'import_gist', 'export_dialog', 'import_dialog', 'asdict']
77

88
# %% ../nbs/00_core.ipynb
9-
import inspect, json, importlib, linecache
9+
import json, importlib, linecache
1010
from typing import Dict
1111
from tempfile import TemporaryDirectory
1212
from ipykernel_helper import *
@@ -17,6 +17,7 @@
1717
from ghapi.all import *
1818
from fastlite import *
1919
from fastcore.xtras import asdict
20+
from inspect import currentframe,Parameter,signature
2021

2122
# %% ../nbs/00_core.ipynb
2223
_all_ = ["asdict"]
@@ -35,7 +36,7 @@ def get_db(ns:dict=None):
3536
# %% ../nbs/00_core.ipynb
3637
def find_var(var:str):
3738
"Search for var in all frames of the call stack"
38-
frame = inspect.currentframe()
39+
frame = currentframe()
3940
while frame:
4041
dv = frame.f_globals.get(var, frame.f_locals.get(var, None))
4142
if dv: return dv
@@ -189,17 +190,38 @@ def import_string(
189190
spec.loader.exec_module(module)
190191
return module
191192

193+
# %% ../nbs/00_core.ipynb
194+
empty = Parameter.empty
195+
196+
def is_usable_tool(func:callable):
197+
"True if the function has a docstring and all parameters have types, meaning that it can be used as an LLM tool."
198+
if not func.__doc__ or not callable(func): return False
199+
return all(p.annotation != empty for p in signature(func).parameters.values())
200+
201+
# %% ../nbs/00_core.ipynb
202+
def mk_toollist(syms):
203+
return "\n".join(f"- &`{sym.__name__}`: {sym.__doc__}" for sym in syms if is_usable_tool(sym))
204+
192205
# %% ../nbs/00_core.ipynb
193206
def import_gist(
194207
gist_id:str, # user/id or just id of gist to import as a module
195208
mod_name:str=None, # module name to create (taken from gist filename if not passed)
196-
add_global:bool=True # add module to caller's globals?
209+
add_global:bool=True, # add module to caller's globals?
210+
import_wildcard:bool=False, # import all exported symbols to caller's globals
211+
create_msg:bool=False # Add a message that lists usable tools
197212
):
198213
"Import gist directly from string without saving to disk"
199214
fil = gist_file(gist_id)
200215
mod_name = mod_name or Path(fil['filename']).stem
201216
module = import_string(fil['content'], mod_name)
202-
if add_global: inspect.currentframe().f_back.f_globals[mod_name] = module
217+
glbs = currentframe().f_back.f_globals
218+
if add_global: glbs[mod_name] = module
219+
syms = getattr(module, '__all__', None)
220+
if syms is None: syms = [o for o in dir(module) if not o.startswith('_')]
221+
syms = [getattr(module, nm) for nm in syms]
222+
if import_wildcard:
223+
for sym in syms: glbs[sym.__name__] = sym
224+
if create_msg: add_msg(f"Tools added to dialog:\n\n{mk_toollist(syms)}")
203225
return module
204226

205227
# %% ../nbs/00_core.ipynb

nbs/00_core.ipynb

Lines changed: 175 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"outputs": [],
2424
"source": [
2525
"#| export\n",
26-
"import inspect, json, importlib, linecache\n",
26+
"import json, importlib, linecache\n",
2727
"from typing import Dict\n",
2828
"from tempfile import TemporaryDirectory\n",
2929
"from ipykernel_helper import *\n",
@@ -33,7 +33,17 @@
3333
"from fastcore.meta import delegates\n",
3434
"from ghapi.all import *\n",
3535
"from fastlite import *\n",
36-
"from fastcore.xtras import asdict"
36+
"from fastcore.xtras import asdict\n",
37+
"from inspect import currentframe,Parameter,signature"
38+
]
39+
},
40+
{
41+
"cell_type": "code",
42+
"execution_count": null,
43+
"metadata": {},
44+
"outputs": [],
45+
"source": [
46+
"from IPython.display import display,Markdown"
3747
]
3848
},
3949
{
@@ -100,7 +110,7 @@
100110
"#| export\n",
101111
"def find_var(var:str):\n",
102112
" \"Search for var in all frames of the call stack\"\n",
103-
" frame = inspect.currentframe()\n",
113+
" frame = currentframe()\n",
104114
" while frame:\n",
105115
" dv = frame.f_globals.get(var, frame.f_locals.get(var, None))\n",
106116
" if dv: return dv\n",
@@ -456,13 +466,20 @@
456466
"name": "stdout",
457467
"output_type": "stream",
458468
"text": [
459-
"testfoo='testbar'\n"
469+
"__all__ = [\"hi\"]\n",
470+
"\n",
471+
"testfoo='testbar'\n",
472+
"\n",
473+
"def hi(\n",
474+
" who:str # who to say hi to\n",
475+
"):\n",
476+
" \"Say hi to `who`\"\n"
460477
]
461478
}
462479
],
463480
"source": [
464481
"gfile = gist_file(gistid)\n",
465-
"print(gfile.content)"
482+
"print(gfile.content[:100]+\"\")"
466483
]
467484
},
468485
{
@@ -488,6 +505,87 @@
488505
" return module"
489506
]
490507
},
508+
{
509+
"cell_type": "code",
510+
"execution_count": null,
511+
"metadata": {},
512+
"outputs": [],
513+
"source": [
514+
"#| export\n",
515+
"empty = Parameter.empty\n",
516+
"\n",
517+
"def is_usable_tool(func:callable):\n",
518+
" \"True if the function has a docstring and all parameters have types, meaning that it can be used as an LLM tool.\" \n",
519+
" if not func.__doc__ or not callable(func): return False\n",
520+
" return all(p.annotation != empty for p in signature(func).parameters.values())"
521+
]
522+
},
523+
{
524+
"cell_type": "code",
525+
"execution_count": null,
526+
"metadata": {},
527+
"outputs": [],
528+
"source": [
529+
"def hi(who:str):\n",
530+
" \"Say hi to `who`\"\n",
531+
" return f\"Hello {who}\"\n",
532+
"\n",
533+
"def hi2(who):\n",
534+
" \"Say hi to `who`\"\n",
535+
" return f\"Hello {who}\"\n",
536+
"\n",
537+
"def hi3(who:str):\n",
538+
" return f\"Hello {who}\"\n",
539+
"\n",
540+
"bye = \"bye\""
541+
]
542+
},
543+
{
544+
"cell_type": "code",
545+
"execution_count": null,
546+
"metadata": {},
547+
"outputs": [],
548+
"source": [
549+
"assert is_usable_tool(hi)\n",
550+
"assert not is_usable_tool(hi2)\n",
551+
"assert not is_usable_tool(hi3)\n",
552+
"assert not is_usable_tool(bye)"
553+
]
554+
},
555+
{
556+
"cell_type": "code",
557+
"execution_count": null,
558+
"metadata": {},
559+
"outputs": [],
560+
"source": [
561+
"#| export\n",
562+
"def mk_toollist(syms):\n",
563+
" return \"\\n\".join(f\"- &`{sym.__name__}`: {sym.__doc__}\" for sym in syms if is_usable_tool(sym))"
564+
]
565+
},
566+
{
567+
"cell_type": "code",
568+
"execution_count": null,
569+
"metadata": {},
570+
"outputs": [
571+
{
572+
"data": {
573+
"text/markdown": [
574+
"- &`hi`: Say hi to `who`"
575+
],
576+
"text/plain": [
577+
"<IPython.core.display.Markdown object>"
578+
]
579+
},
580+
"execution_count": null,
581+
"metadata": {},
582+
"output_type": "execute_result"
583+
}
584+
],
585+
"source": [
586+
"Markdown(mk_toollist([hi]))"
587+
]
588+
},
491589
{
492590
"cell_type": "code",
493591
"execution_count": null,
@@ -498,13 +596,22 @@
498596
"def import_gist(\n",
499597
" gist_id:str, # user/id or just id of gist to import as a module\n",
500598
" mod_name:str=None, # module name to create (taken from gist filename if not passed)\n",
501-
" add_global:bool=True # add module to caller's globals?\n",
599+
" add_global:bool=True, # add module to caller's globals?\n",
600+
" import_wildcard:bool=False, # import all exported symbols to caller's globals\n",
601+
" create_msg:bool=False # Add a message that lists usable tools\n",
502602
"):\n",
503603
" \"Import gist directly from string without saving to disk\"\n",
504604
" fil = gist_file(gist_id)\n",
505605
" mod_name = mod_name or Path(fil['filename']).stem\n",
506606
" module = import_string(fil['content'], mod_name)\n",
507-
" if add_global: inspect.currentframe().f_back.f_globals[mod_name] = module\n",
607+
" glbs = currentframe().f_back.f_globals\n",
608+
" if add_global: glbs[mod_name] = module\n",
609+
" syms = getattr(module, '__all__', None)\n",
610+
" if syms is None: syms = [o for o in dir(module) if not o.startswith('_')]\n",
611+
" syms = [getattr(module, nm) for nm in syms]\n",
612+
" if import_wildcard:\n",
613+
" for sym in syms: glbs[sym.__name__] = sym\n",
614+
" if create_msg: add_msg(f\"Tools added to dialog:\\n\\n{mk_toollist(syms)}\")\n",
508615
" return module"
509616
]
510617
},
@@ -529,6 +636,67 @@
529636
"importtest.testfoo"
530637
]
531638
},
639+
{
640+
"cell_type": "code",
641+
"execution_count": null,
642+
"metadata": {},
643+
"outputs": [
644+
{
645+
"data": {
646+
"text/plain": [
647+
"'testbar'"
648+
]
649+
},
650+
"execution_count": null,
651+
"metadata": {},
652+
"output_type": "execute_result"
653+
}
654+
],
655+
"source": [
656+
"import_gist(gistid, import_wildcard=True)\n",
657+
"importtest.testfoo"
658+
]
659+
},
660+
{
661+
"cell_type": "code",
662+
"execution_count": null,
663+
"metadata": {},
664+
"outputs": [
665+
{
666+
"data": {
667+
"text/plain": [
668+
"'Hello Sarah'"
669+
]
670+
},
671+
"execution_count": null,
672+
"metadata": {},
673+
"output_type": "execute_result"
674+
}
675+
],
676+
"source": [
677+
"hi(\"Sarah\")"
678+
]
679+
},
680+
{
681+
"cell_type": "code",
682+
"execution_count": null,
683+
"metadata": {},
684+
"outputs": [
685+
{
686+
"data": {
687+
"text/plain": [
688+
"['hi']"
689+
]
690+
},
691+
"execution_count": null,
692+
"metadata": {},
693+
"output_type": "execute_result"
694+
}
695+
],
696+
"source": [
697+
"importtest.__all__"
698+
]
699+
},
532700
{
533701
"cell_type": "markdown",
534702
"metadata": {},

0 commit comments

Comments
 (0)