from IPython.display import display,Markdown
import textwrapinspecttools
This module provides LLM tools to dynamically inspect source code, types, and module capabilities. Functions take string arguments (dotted symbol paths) rather than Python objects because LLM tool interfaces can only pass serializable values—not live Python references.
Helpers
importmodule
def importmodule(
mod:str, # The module to import (e.g. 'torch.nn.functional')
caller_symbol:str='__msg_id', # The name of the special variable to find the correct caller namespace
):
Import a module into the caller’s global namespace so it’s available for symsrc, symval, symdir, etc. Use this before inspecting or using symbols from modules not yet imported.
importmodule lets the LLM dynamically import modules by name. Here we import fastcore.utils and verify it’s available.
importmodule('fastcore.utils')
fastcore.__version__'1.12.5'
resolve
def resolve(
sym:str, # Dotted symbol path, with optional [n] indexing, e.g. "module.attr.subattr[1]" or "_last" for previous result
):
Resolve a dotted symbol string to its Python object, with optional [n] indexing. Sets global _last to the resolved object for chaining. Pass "_last" to reference the result of the previous tool call.
Examples:
resolve("sympy.sets.sets.Interval")-><class 'sympy.sets.sets.Interval'>resolve("mylist[2]")-> third element of mylist
SymbolNotFound
def SymbolNotFound(
args:VAR_POSITIONAL, kwargs:VAR_KEYWORD
):
Common base class for all non-exit exceptions.
resolve navigates dotted paths like "a.argfirst" to reach the actual Python object.
a = fastcore.utils.L(1)
resolve('a.argfirst')<bound method L.argfirst of [1]>
It also sets _last for chaining. Since it’s used internally by all get* tools in this module, the tools all set _last too.
_last<bound method L.argfirst of [1]>
It works on both objects and classes:
resolve('fastcore.utils.L.argfirst')<function fastcore.foundation.L.argfirst(self: fastcore.foundation.L, f, negate=False)>
Symbol info
symsrc
def symsrc(
sym:str, # Dotted symbol path (e.g `Interval` or `sympy.sets.sets.Interval`) or "_last" for previous result
):
Get the source code for a symbol.
Examples:
symsrc("Interval")-> source code of Interval class if it’s already importedsymsrc("sympy.sets.sets.Interval")-> source code of Interval classsymsrc("_last")-> source of object from previous tool call- For dispatchers or registries of callables:
symnth("module.dispatcher.funcs", n) then symsrc("_last")
symsrc retrieves the source code of any symbol by path—essential for letting the LLM understand how functions work.
print(symsrc('a.argfirst'))File: /Users/jhoward/aai-ws/fastcore/fastcore/foundation.py
@patch
@curryable
def argfirst(self:L, f, negate=False):
"Return index of first matching item"
if negate: f = not_(f)
return first(i for i,o in self.enumerate() if f(o))
class B:
def a(): ...
b = B()
print(symsrc('b'))File: /var/folders/51/b2_szf2945n072c0vj2cyty40000gn/T/ipykernel_33003/2711726673.py
class B:
def a(): ...
def f():
"testing"
return 1
print(symsrc('f'))File: /var/folders/51/b2_szf2945n072c0vj2cyty40000gn/T/ipykernel_33003/242320393.py
def f():
"testing"
return 1
from toolslm import xmlprint(symsrc('xml')[:200])File: /Users/jhoward/aai-ws/toolslm/toolslm/xml.py
# AUTOGENERATED! DO NOT EDIT! File to edit: ../00_xml.ipynb.
# %% auto #0
__all__ = ['doctype', 'json_to_xml', 'get_mime_text', 'cell2out', 'cell2x
symtype
def symtype(
syms:str, # Comma separated str list of dotted symbol paths (e.g `'Interval,a'` or `'sympy.sets.sets.Interval'`); "_last" for prev result
):
Get the type of a symbol and set _last.
Examples:
symtype("sympy.sets.sets.Interval")-><class 'type'>symtype("doesnotexist")->'SymbolNotFoundsymtype("_last")-> type of previous result
symtype returns the type of a symbol—useful for the LLM to understand what kind of object it’s dealing with.
symtype('a.argfirst')[method]
symtype('fffaa,b')["SymbolNotFound(Symbol 'fffaa' not found. Consider using `importmodule` first.)",
__main__.B]
symval
def symval(
syms:str, # Comma separated str list of dotted symbol paths (e.g `Interval` or `sympy.sets.sets.Interval`); "_last" for prev result
):
List of repr of symbols’ values.
Examples:
symval("sympy.sets.sets.Interval")->[<class 'sympy.sets.sets.Interval'>]symval("some_dict.keys")->[dict_keys([...])]symval("a,notexist")->['foo','SymbolNotFound']
symval returns the repr() of a symbol’s value—handy for inspecting data without needing to execute arbitrary code.
a[1]
symval('a,foofoo')['[1]',
"SymbolNotFound(Symbol 'foofoo' not found. Consider using `importmodule` first.)"]
symtype_val
def symtype_val(
syms:str, # Comma separated str list of dotted symbol paths (e.g `Interval` or `sympy.sets.sets.Interval`); "_last" for prev result
):
List of 2-ple of (type,repr) of symbols’ values.
Examples:
symtype_val("a,c,notexist")->[(<class 'str'>,'foo'),(<class 'int'>,1), 'SymbolNotFound']
symtype_val('a,b,foofoo')[(fastcore.foundation.L, '[1]'),
(__main__.B, '<__main__.B object>'),
'SymbolNotFound']
symdir
def symdir(
sym:str, # Dotted symbol path (e.g `Interval` or `sympy.sets.sets.Interval`) or "_last" for previous result
exclude_private:bool=False, # Filter out attrs starting with "_"
):
Get dir() listing of a symbol’s attributes and set _last. E.g: symdir("sympy.Interval") -> ['__add__', '__and__', ...]
symdir lists all attributes of an object (i.e it calls dir(). Here we filter out private names to see the public API of an L list.
' '.join(symdir('a', exclude_private=True))'accumulate append argfirst argwhere attrgot batched clear combinations compress concat copy copy count cycle dropwhile enumerate extend filter flatmap flatten groupby index insert itemgot items map map_dict map_first map_zip map_zipwith pairwise partition permutations pop product range reduce remove renumerate reverse rstarargfirst rstarargwhere rstardropwhile rstarfilter rstarmap rstarpartition rstarreduce rstarsorted rstartakewhile setattrs shuffle sort sorted split splitlines starargfirst starargwhere stardropwhile starfilter starmap starpartition starreduce starsorted startakewhile sum takewhile unique val2idx zip zipwith'
symnth
def symnth(
sym:str, # Dotted symbol path to a dict or object with .values()
n:int, # Index into the values (0-based)
):
Get the nth value from a dict (or any object with .values()). Sets _last so you can chain with symsrc("_last") etc.
Examples:
symnth("dispatcher.funcs", 12)-> 13th registered functionsymnth("dispatcher.funcs", 0); symsrc("_last")-> source of first handler
symnth extracts the nth value from a dict (or anything with .values()).
handlers = dict(int=lambda x: x*2, str=lambda x: x.upper(), list=lambda x: len(x))
symnth('handlers', 0)<function __main__.<lambda>(x)>
Combined with _last, this lets the LLM drill into registries of handlers/dispatchers and then inspect their source.
symsrc('_last')'File: /var/folders/51/b2_szf2945n072c0vj2cyty40000gn/T/ipykernel_33003/340145363.py\n\nhandlers = dict(int=lambda x: x*2, str=lambda x: x.upper(), list=lambda x: len(x))\n'
symlen
def symlen(
sym:str, # Dotted symbol path or "_last" for previous result
):
Returns the length of the given symbol
symslice
def symslice(
sym:str, # Dotted symbol path or "_last" for previous result
start:int, # Starting index for slice
end:int, # Ending index for slice
):
Returns the contents of the symbol from the given start to the end.
a = ['a', 'b', 'c', 'd']
symslice('a', 1, 3)['b', 'c']
On failure we get a str error:
symslice('resolve', 0, 1)"Error: 'function' object is not subscriptable"
symsearch
def symsearch(
sym:str, # Dotted symbol path or "_last" for previous result
term:str, # Search term (exact string or regex pattern)
regex:bool=True, # If True, regex search; if False, exact match
flags:int=0, # Regex flags (e.g., re.IGNORECASE)
):
Search contents of symbol, which is assumed to be str for regex, or iterable for non-regex. Regex mode returns (match, start, end) tuples; otherwise returns (item, index) tuples
symsearch('a', 'c', regex=False), symsearch('a', 'z', regex=False)("[('c', 2)]", '[]')
text = "The quick brown fox jumps over 3 lazy dogs and 12 cats"symsearch('text', r'\d+', regex=True)"[('3', 31, 32), ('12', 47, 49)]"
symsearch('text', r'\b[aeiou]\w*', regex=True, flags=re.IGNORECASE)"[('over', 26, 30), ('and', 43, 46)]"
symset
def symset(
val:str, # Value to assign to _ai_sym
):
*Set _ai_sym to the given value*
symset('Otters are awesome!'); _ai_sym'Otters are awesome!'
Symbol context
symfiles_folder
def symfiles_folder(
sym:str, # Dotted symbol path or "_last" for previous result
types:str | list='py', # List or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg
skip_file_re:str='^_mod', # Skip files matching regex
prefix:bool=False, # Include Anthropic's suggested prose intro?
out:bool=True, # Include notebook cell outputs?
include_base:bool=True, # Include full path in src?
title:str=None, # Optional title attr for Documents element
max_size:int=100000, # Skip files larger than this (bytes)
max_total:int=10000000, # Max total output size in bytes
readme_first:bool=False, # Prioritize README files at start of context?
files_only:bool=False, # Return dict of {filename: size} instead of context?
sigs_only:bool=False, # Return signatures instead of full text? (where supported by `codesigs` lib)
ids:bool=True, # Include cell ids in notebooks?
recursive:bool=True, # search subfolders
symlinks:bool=True, # follow symlinks?
file_glob:str=None, # Only include files matching glob
file_re:str=None, # Only include files matching regex
folder_re:str=None, # Only enter folders matching regex
skip_file_glob:str=None, # Skip files matching glob
skip_folder_re:str=None, # Skip folders matching regex,
ret_folders:bool=False, # return folders, not just files
sort:bool=True, # sort files by name within each folder
exts:str | list=None, # list or comma-separated str of exts to include
):
Return XML context of files in the folder containing sym’s definition
# print(symfiles_folder('xml'))symfiles_package
def symfiles_package(
sym:str, # Dotted symbol path or "_last" for previous result
types:str | list='py', # List or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg
skip_file_re:str='^_mod', # Skip files matching regex
skip_folder_re:str='^(\\.|__)', # Skip folders matching regex
prefix:bool=False, # Include Anthropic's suggested prose intro?
out:bool=True, # Include notebook cell outputs?
include_base:bool=True, # Include full path in src?
title:str=None, # Optional title attr for Documents element
max_size:int=100000, # Skip files larger than this (bytes)
max_total:int=10000000, # Max total output size in bytes
readme_first:bool=False, # Prioritize README files at start of context?
files_only:bool=False, # Return dict of {filename: size} instead of context?
sigs_only:bool=False, # Return signatures instead of full text? (where supported by `codesigs` lib)
ids:bool=True, # Include cell ids in notebooks?
recursive:bool=True, # search subfolders
symlinks:bool=True, # follow symlinks?
file_glob:str=None, # Only include files matching glob
file_re:str=None, # Only include files matching regex
folder_re:str=None, # Only enter folders matching regex
skip_file_glob:str=None, # Skip files matching glob
ret_folders:bool=False, # return folders, not just files
sort:bool=True, # sort files by name within each folder
exts:str | list=None, # list or comma-separated str of exts to include
):
Return XML context of all files in sym’s top-level package
# print(symfiles_package('xml'))