interactions: - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '116' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - The company was founded in 1985 by Jane Smith. model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: +PmVuEApqLuclhW7dBY3PSFPFboFXJY8eptEPUx1fT2qCmC6RxFrugzN1Lwfz4g6E1QxO293jLzIG0+832CBvBNncz29/Fi9HJ6KOt02Irootgc66orCOFBRdj03rLk8ZA3muL5ZHD1q0M28VH/vuxbq3rprAUa8GXZGvbnoRrx5oD09AdyWPMhoMTuYjaG6mJzFvB/mcLZ+ps08kDFrPHA+bzya6l+83L93PE1GuLvaipI8o/6oPAoZKDttOg49sAQ/vJSqN72C0Yo7htszvIHPHrxZYxS841Lnu5e12Tw9x8c875Ydu3BsbrzgREE9w0V/NqadFzw8aC282qWOOw7uprtGbVi83vAEPFuwpjqiez+60ygDvfoYhL3CciA9PNuMu2I8Xjw6iC68y9SovMARqbzefxe8/8Dwu9o+lDy5eVc4j3JbPPs9cDyrbVM8NQC+OrhhDL0JQI873MLIuzvBlLxjf4W8XqFiPJNZtTunhL68JVhgvOhZczsD6Jk8o0rDvJKUhry3Ngm8aAYnO5GMq7y8PzG6v0uBubeB+7tRe6W8bGRZvPinkbmnSzE84vv7u4pLGjsT2+48xDggPEixorqMPVQ96CbCORttLLzZcRi9MSDDOzeRpLxzfI+8vYSUu95ZzTx+G543U3SNvN9E1zqqFC68LvqfOxp+r7wG2va7OfmdOwiPcLzRykY8LNalu6fSNzt2uBi9Z3s/PPX9rTxUOKG8GJ0PvSGCCrye04I7FQ2Cu4IPjTyDz5I7jNAcvKKtzLvboBE8rYOMPCbEmTypBs86TgGCPE8kkLxUT2q8ytYpPAkbnDw2PWY75i36uwTpDTxj8Zy6FVFBPHXYULt+Wy48ubEdvOyXLz0UDk08OEBpPPPHbDs/VQk8z+ITvUv0gjyJoos8Y2i+OsAMabsTyp28VeKOvBuMRTxOW1K8thU6uxbfrTq3UN07wZkRvPopZDxfq6u83YOBuzKvOzxTcjm8D73pu6+7tzy8MQM8cqYkvH5GMrux6Em93uABvCpTo7wKxAq858sdvIKsnrsPBYK84L1IPEmMDDx/m3M8eRGcu30U+bwX76083nnwuug0qbscUoK7nRfcOtnJkzyrWUG7b+wiPE3dobxHsTq8rl7UvHNSFLw5Cwo8Ycziu/qa47r2fY47HE61uljCCTzzOuA73vYgu/x+tzxUSWu8NKMpO9pUtLulR0E8p9B+ue8ZbztLUYU9SxGFPOvJ9btocly8dqi0u0onaDygdkk8BFNnvAjpuTw6cdA7jNogPAlA0bq9WNK8EPKUvOmmIrzf0vK7bJbpPHgbsTuvaXI8cnjCvE/XkbvANWY8sKR7vOltqLxkauY8F4AMvNiJu7yq+MM6g+cZuk80xjx8x3K8i2mEPN9xH7zlPQS8rbxbPE755TxMUO48kElfPIXjUTzJb9a8++FAOzPlGDxWKg48iVwAvdJGVDs0RUm8O06uOgcPobte70w7K0Dvu1p67rxOX/U7wsFtPN1lkjxYDyC9O3q6vL6R2DxGWB08UNbju049DjqUFZU6KiYpu8O2C7ultJy6D5EhvA5Xqbpc4Ks7rxkRPI6RV7x1aU+6NDN1vCqsxrypAzY83As3PDCTIrsggtA8nws/vHjJzDz10UA9LffDuz+8ODrN8tQ82hGKuk2blzsh2DM8j7PzO1dDNzzbeNe8vw2dvLoC0ToF/ua7k/AXvV/7Ar0Ff6m8Na8EvBEcqjxrroC8TFe5vG0ALbuzax+9Hk58vNzSYjySXjA8js4kN28GnLuA3SE5n4r9uwzQ5zyuM7C80yaOvKpMGryBP827SbR2vLtdOrs3BPm8sovQPBJEV7wH2zw851T+O6iPz7yPqj89kOvGOOKQVztRP0+8JnejO3Q1prypHbK8925lPBjkhrs+2Cs9xNBiPIKEiDwA7Pe7CMSKO5q987iKyPq78f+UPLSh4DxMuwg87k2FvJC8FTpmhCC9cojqu9ESN72CSCq7nYjlu2xBZLzWRfC8yabbvMs+ZLq5+Jg8hqXqvDHanrzsRoS8iyXkO397Bj0X4gE8hGmNPALmcTzIp148w58JvAsqzzxAiAU7iI7tureLQb0BLMq8NzoTPANeDbsIzoe6PgPgvHRPAj20Wwm9PF9NOw46aLzaNea8/XQGvbQDFryY1LA8Jm2vPI5UQjxMRoW70M8PPNrPzDztTYY7ihreO0B6xTuszPc8D5u9vPpNIb3WtHK8JoJavK1iqzpjrY28iYTgO69/dLv2DkQ8c4dFPMC6gjzQ2hK89L8fvIgZzDzbBlY9/zV/OrRhnTw6BgM8JXhDPNR5f7yNyp+7v//lO1Sa07oyi8E8cTiOO1Cpr7kgi5A7OP3APPfZBTs/rRA8SXoaO3DSVzxtKpG76qFjPGE7kz0RjQG8fyTYvPdvDrwEUA47Td96ufnJnTxw1Ya9jdlHO1PKIrwKGEA5ikzcPLc9C71ziLy8cB6fvP84x7yCgw27vAbqO70NOT0AG4S89r4UPL1NJLyxa4o8GJYGui9yBj0R+cG8mtyGOy87ijw8dg09VviNPGsbZzzawoS65fq3PPAyUr1gb6k8f8zkPG/D9ztcIOQ8B9ouvb8MAjyeB/Y86pUOveB7KLwZWwk8YR9yuyZwpjtCeIO8qbbFPAmQt7xylw49rV9yu0+e8zsFfyW7/onXvOLTyrtjz5K8QOICvMi4cjx/SH88b8riOyH3rTuYDDC8AgoSvPMTSjwpTYu8cHmmvHos9Duuj8+6ANCxvFQQyDzt9lo8hT25PHNcAzyvtze8D1dJPL8r9jyZXgS9IivXuskXazyB+k+9n9/Ju5NY8TwOc2+8NTc/vKNYebzZML07DkxDPTDlFLyILto8rmYKvLWRlLwwcYE8+U+wvI/xnTxhi5s793YQvHZ9ODycbtS8a+5HPBi5+Tty7HU8CurfPP2JHr1ANE48EdKsvDgSQT3itcE8mzAnPBnDD7xdhbk8xb6avHQl27vg9zc81bOYPGbXgblThZK7drB/Oi9xGDyglMi8JmWfu9IiXbp2qXA7xz1wu8vfVryp9mM8QvsvPJi3mLxXBwI8CITgvAmM2TnHxZk80d8pvCcjhTyd1MC77B1uvLcnXLwI57w8Wf8WPLgcAzvQ6bs6NrnCOrkU77wFOzs9nutfPClXdjxGXLM7/kKju9VW5TtzS/a8UvHTPATCiLuPV8w77yI8PHgLkLu2l3i8UAu/O2ncSLpg4HA88tRRPGadw7xliR28QinFO/agP7xe1hY9yRrCPN1QxLzwcWQ81XrPPCcZyLpx1Ra8EoOcOm9pIL2j+lA8U4u4OxeSD71Lk7E8G0m8vMD8+LxHuNq4xmmAvJNHz7x7ito7cQPWvN7Qazrk0+q8hBEFvSRVHzvX52I86JP+PDbZsDlCFze881TGPEtt6zztCRa7a/dwPLriQjqnVzu9PvgfvHdGpLz5wpS7oRDoPACh0zu9v8I79XywPDFsSDtTebc8hRuavO45XjxGTmk82VWIu97f0by2SRM8ol3QPIsJTrxnvhO9mogavNOdmDubVys99fDsO0yoAL0B/wG8yWCCvKaLcDs0Gom8OKGLOt2KUryVptu6W0QZOwyRNzvMQTC9U1Y2PP14ET3evxk7mptnO/Xxn7wS9Ze7LifuuoIhfLzkAS49IUmLPN78KDziMsI7bROHu5HMjTwnMIm8zOudu7c2Fz2yLv28Je8kvQgv6zpGnSs9RewFPV65hjxQpVO8aYIivU7e7Tve24G8CvxBu0C+AryhPg29texSPPXwZLyXmQG9zWMOu7r/c7l8yA69fgC0uyvAvTxdapQ7r+vCPI9kEb0GO/e7qzWYPLraK73QMZg8qiXAvHy21DupTxA9P3UmPRWHH7tXKSu8+toaPBzPAj3YGdm8CAKEPMSmLTsifFe8YtoIvc8eLr3L8k09OxBBvOTrFLz9KB+8yj3aO2GfCrvAUJe8N/20u6JkDj3VxKG8Y2MkO7PKATyOLo+8zQSjvN7ErbwtI7I8yt9bPKFZwTy8F7672r4Bu5t8djy6NaM6KXvEOoX3jLzLBQu8T7o0OuRuBTsINYo72PadOnVTGT1/Kwy8yVi9PEwcBD3PQyE8jvioPO4Fn7uzflK9tfOXvLmLEj3m4Ls8lwNUPHAqML2Zwby8uqVKvDDWB70Dbj09sB+8vP6p0LkXAh080awBvYhPnLqreQs883+uuglyKruI+ou87S6WPNBm7jtnKs084+38ux3TAb3iWmc7haf/vNNv9rtaWLs82OIcvCMK4jhJDlC7LHO9ur8U4jzxmOw8QbN0vMaVXLwC7j88iF5PvDalGL1ncEE8cndYPHsr8jupqTY9PTnaPP5+pTzlgwU839Y2vOiuwLs6c0o6wDRrvC5N3jxU/xq8z/z9u1MZoLulZq67R+QZPbPxW7zZGxM9xo3SO3tMLLxH+uW8jiEXvSwZqbx/dWE7wJuhPHC8gzz9+As9V40mu0uWgbxdqr08/gdcPA1swrwh9CK98SbHvPyXFD3xlyI9fJ3PO6w+MDuP/r2899ayPCcI3bzgraS8TJgtPJwjybyu5w28TBhGvNuls7wRDae8enSBvNbKgLyfueQ8TuK7vF9iOzz5v1a9JdqsPMRuDj2Dkm+7hJARPfq5PD212Ok6TM28OpvAxzz4fsu7oM6eu/KBCDwINws6udiDO7XMFjzLAYA89H7WPKNBkzybtUq8h4AhvAHESLptIQW9/pmyvA0AjzwoioU8Ucr8PEZFoDoJoCq8sD6XOxux8Dy9BxO83/iqvMyCOzwq8gY7QR6mPFWEHT1lEHI8/dG9uuFMsrwBMtI8yh6Au+AtWDoEfYS6vPunuf+wGbyr80e7rMfGvA7yDjx3nQ482fZsvLaI3Lwj8Z87hi0vPDjhIb3Sq9+7P7aqPJsrbLxKKIE7fX76O4oafLwH/je8VZgovbvvED1awcG8I6ppvEi8qDzcH+47gb8PPNo9aTwuuqI7m5YbPDNEILy2lVw9+2h0uyDmmzplbii9DCOCvNxRt7pX1PU7Yw4xPOZJFDwAbhA7eFp4vGUmyztl0O07ba//OynPz7nks4q5s6kFu1kn7Du29Ma6pMnAvKBJpLycq8E81yi6uzJwGLsWgSe7dpICPZ/gy7uVFfg8bKihvAPTD70q+/c8fkW0vLoH4btepAk8/1fdPNm+8rvPM4Y8FNk8OybO2bwyeTc8GGazO7dDBD1c+K68KOYAvDA9B731NPs7HfauvMw/eDxw4oY8lt+mvIxMMLxS1wA8qwuLvIw8ODzX+4Y86jyIvPTzqzrifTm8NGe1PE2scLw1ACk8L1mQPEVsmDviXam7qS5PvaNE67yLjWe7lZq9O2M7z7voCUC8DDXZO5ipj7zSZkO8asf+u1ZjTrzQnmi8K8ayuylPe7urky89ahjwOovmqzyu3k+8S8oaPS54gryDnTe8OMW/vAnJP7ovW4m8ObElvPCUFD1Z5Oi8i8UgOAPS3TuIHDu8vlInPAUTibzemYw8w1mOPM5Euztw+z+8mS8pvKmxmLwhxKC8uMn/u8Hm0rynCdW7KnvdO1yA2LvLmAC9eb2Qu3818zz3BfC6g/EEvIwYRzyMG9i74qR2PCFjMb3g2fC72TJCvMtTObuVfHq6m02xvN/rfzpjpHO6o10xPOk9ZTuyWnG7HycjPY/aqbqyq5c7c15IvJH+JzzJxwO8T7WAvGLFFTsWoyy7sB71PJLHTTzV5Ii7YdKhvAalGTz9Yv+7yZ1ouzJbp7wZf6O8k9bgO4I66Tvcmyg7+isLO4BVjzxRmci785VCvJhzNT0/+uY86wZEuupZ8bx+gHE8+7evu+q9ED3T6ba7tOZ8O86GeDxFWU68imoQPccNhTzrPFm7LWoFPValnLs6zye9ZGwcPeEtjDsw8Oi63RHUO1UaRj1TEJ27FlFNvMeLp7sTtYY8EyaYuXCCe7zx6Zy7hxUdvfs4VT2JN7C8lbhNvL3Cxjw8FzM8TWHsO2sLRTxO/d68u5c7vCLut7zJtIa6C++SPIg2IjxiUeU8PkRKvSwB5jzf01c87o53vEYzaru+4367+TQAvRymNbvd3Vu8tY3AuxuU7TwF5F67XI8kO204UTwVgnO6bBw8PLOexrvf7u23dohYPV6pWTouWZg8RgqovJbsnzyvBkA884yOvAoP9bsY4O46JB8VvZuhwLxd1EC8mj6hOwZDo7yIt8C7d1/kux/Z9rxGgTs9mAeqPDJ/qLv/IEa6eQvtOnTIQ7ybsXW8kzd5O+AIDbs6ptS8QZQHPBrXjLxOvSu8o3ubPE0NFj3tA6a8geKju+8hOrwFehc9WHWhPPxN2byFQOQ7tswPO8wBIjw2XW08eKWNvCduOLwwk1a8gG/UOYmoLbxyN2s71ASvPDe4mrvJ/CI8I0uZvM9U2jtR3hI8jU1ROzMu7rsdHNk8RC6VvLg8mjy6Bt68sVDMvHHsoru74AK9VVT6PCUxArz35X472GYPOmpoobvtAVa8s8fWvETPwru6hAY8fybLu6JTbTz+OgK9wwOUvB3xdjx1KwG8lRu6vOsEoLv6/Ug8vGoGvIXDrLzFXRU76vSUvK+C17x7FK28TVa1PElMcjt5k+486IGVuyFyEb1Jco46XVe+O75jxrwJCLa8ZjCsOyVnez0tj6e8ottzvPXNwrwtBmO7ih1Fu+Aa5ryJHQU8a89+vL4p6jtb0Zm8tlILu33ttztJRsk72ecEPbLBn7xIZTi9EesJPZWT7LsAQNU7AEbxPCzsED3BWY48VlscPCi6jzwWKHG83oKmPBvcADz3TZ08GF6hvH0JgrrlJbE8Ng57PKKocrwM0648HqkqvLriTzwT/708jtkAvBr+mjs7TAG7fFkQvR0ucLy1PA08nGyRuxCBijwOGck7K4JTvANN8jzrQ5i8d6ztu2YunDzdkbO8wP6KPJsPSD2j6BQ8JsyVPJViFDxXg+w89lIRPc3Vo7s+Mio9s6+uvF+oCr1wGMm893L+vOk7sLtCzCy8XnUtvL+FqbystLu7qDkVvVoYbzvb6h+4U5QYvF5TwLu9hrs8CRjnu57+f7ypVvw8GCFJPMnBG7w7U5O8L4OXPCpb+jwlppK70HMZPfI3w7xtdgW9kHo2PMfkV7xLSh88NnmIOxEDODipUxi6f88CPNdhp7xYOyG7z19SvNcaMzkvKSK8Q2covT0OPr1ygt28w6sEPYDrzDyMyD+9hzEJPLpYGT2PYZS8MjZ+vKZmdbt9xW+84Sr/u/HhWz3GkQ49TEaAvGCNAj3rpOs8DvhrPMw/bDxeUJE8l78fPDOkAj3L6+Y8UwVfO+dVY7yZDc87E6O3PGjX9byrV4+878aOPLgVEzy8syw8YP6rvJwbiDtkWBy8inCOu1KMfTuIm4a88lEDvchh6TyOk2I6IEAXvdYupTwfErU8rf4OPNteuTzDo8c7hsXMu0VIDzuCgGu6nxUDux7TfbxInfo8lf7PvEgmKzv6Zky9J3SNu9yk1zy0tBq85GIAvIo2zrzfalk8RgcoOxnpgryx0dE8p6u2O4ZZUrwxay68lfgxvBkZkrxZQmE7P7kbu+YImbvFSLq8OIVYvFcA47tcaDA8ugXrvBvzEr2bMhS9Xu3DuyHiXLvCq9i701QtOwAoLLzKjZc8w8wsurkCnrqTrQO8+VwdPAjs/TsIGju7PDOuvIOjCDvRLwK9ThIsuUT337zUy9O6DBawOv6MiryAJyU9sfhsvBDApzueU4m8oz/1PGSSBzy5zxQ9QtS4OwjuEb12UvY8YXzgPAXaKjs5TZC8CqNEvMEGZLxdx3u87PnRPEqMXTxVWFG8PrU5vBuSM7tkhio9i0DQPOsOarsvC6s7WpgTuHZ/7TxC3C09phIhPPV0gbwQbQ+97PQXvaM9Dr2I5846Era5O4vSVzzb7pc8Ra4HOyJrx7shlLc5+3DRush0ATx+no8757Yzvd9FB7yBr8q7b8Q+vAfiEb0jsqE89P+lu27YwzvM8nY8kkJEt+U8RrtkK8w7HTdMPKOOJrzltxg85lo/PJgibTu/GCa7wAe5PH28iTxHPM27WBbPvNeISLyj5jc991OIu977kDxcVu+8TSygPBdbgrxrE5+70EZVPG8guDz8c8o802vCvFsrdLsrmAQ9Ch3rOq5hqLtC71s88mtCvGG+9zwjtqa8Cx1EvHkMvLvUqJm8I5mxvMkFyryikZQ5HDd6vA2rwTvNWxA8l1k4vKC+kruxabo8qKaNu2seqjzERY07iqt2PHMgubtwR+a8iZ4qvMQoGTyr4Dc8pjCCPEYUIz3q9HY6bpAmPUcKhzxWsJW78EtQOyRZgjyVNPU8spzeu5Lm8TqjRDM8JuDSPICeoryHyJe8yKLbPKXk/Tu4shQ96upJvHP6BTyAYZU7wIOuvIfE3jrBN228MCtxvNh8QrwtgHA8x6XZu2Y6Yru8Nju9a5xgOOdczzxpphI9ElpPvFrfsbtfzp277uTxPKFLGLwkd5I8S139O4fcmrsJwAm9f6v4O4QsMTwrxu+8ll3zvFz4tDzj1gW93trUPH0P2zsr28s7g8IRPYJFvrt36Tk8lzzTu1O2b7u5ql67zZvvPBO9/zq6M8+8fitNPemsIT2pv3U86tVePOxoKDwjm9Y8JM9suwAjzjtF1uo8Q4raO1/PlLsPvQ+784oPPFKTcLwzJAS5RTJWPPBdVLu+3Zc8DPHmuzQOFryF71y8cnFbPAIWtjwcvCo8qgA7PEOwq7m6fMU8O5VHvIBmUTxq/Uy7AHCcPMH/F7z5rY68oh/TPH3WTDwkPP27K1wUvP9HGL204rW8xW6/uqfKLTvgC3a62qoPPOsSijyleuC72GYtvPdWLD2V8QG9WZANOwHnt7ylV128DAipvJ4osjzhR8I817V7u3xTF7x69yI9dvQRvDWQDLwLhwG9rSw3vJvJADzp0tI80UhovF97DL043Xi8/RtBPM+wrTy9fIS85SEHPQCwiLx5sf08hkupPDDjoDw82KQ7nfl7u/TEqjmQIMG75dE3O13dqDxgYHg8vEkRO1uv37rIiyS7MN6WO7HBmzyRDxC9Ebf6uo7KGL0KcZu7QjijN8jf7rtHK/276qwgPTPTyTvQWK67Y4zuO9NMADviVoO8QZhRuvhI0Tyva90815ggO2qdkTzK0PC8Yu6oOn1EV7xB+5w8dnq7u95w/TzeNdg7WOMivLYxmjpGWRI8g9g6vWwhtTtBZ988SqSjPK+ErbyUP2s8qEKKPIFiBj23A/+7g7o/O8t0JDwy9Ma84vqbvO1kvTvntMS76W0jPP1Wt7w/GHS8sgeCuvWm1DyKEX28TcrpOmL0VTwXgNA8+NPIPFX2yTvFXLE7VO9DumzITb3wGww8u2kaPaORFL2W9tG8GooivaA34zsHOHY9snSKvGyucTwGo+86kaTIOwSLmTxiOji8xa0Mu2T/8jndXpU8J6LVvMF1r7yg+/e8IwhdO5seIL0Hm+g7Ev6BOzglHTxcLO28Y3oove71BrzM0188ygUePLEKe7yeFs+8e6bOvIikQzo/RQE8OGeTPG4aoLzNaeE84EvmPPbJjLw5Pvg6BgrBu25RkTvuRmA8aFEvvKakIrzAQ3W7NWSPvNNH9DzI6588meIQPfM40TwuWq67IMiuPJlgzDzsNvI8Ka4evZCLOLqfOji97Z9ku8h26ruKgb88AoOAvKycvTqJUZO89lF+PMQK7ruACFm8kl8jO03xorxedcS8Hx2RO57xEjw2ymQ7PoMBPR4vq7zwhII8X4ZWvb7lKbwQ/Ou5ChCWvCW2gjzRQog76z6NvGcY/Lz9GV68t7kavRDAuzzd6XI7kb1oPE4j2DxvB0+8PJ1UvE2e+rz9fLO8CWyaPCsa0bwsmMM8hFUoPEQours/0KU8RCgQPPYYI7w1gku896IOvZgCu7z4cHC8nMQaPEFBQT26VnE75guqPBHq3zuXDyu8s3vvOnknaTzW18y8bsoBPECberwzP5G412obPctyLT38Yok6L4LDPLd7pjusjF64WwUcPEwkCbxjpBq9BQuePAYWibuPwDg9w2fBuws2FrtwaZO8qXxQvIEcsTzboc28L7tFvDmS9rxyCwq84ZxUu2ojv7s/zzM8nNIGPRjKJTzJoA08eyHFuUmTajxHo4y8Er97vNw1aLwhYNK8c5qWO9eKDD0YpAO7I/otPZS4eLvwMbE88gZWvDqDmLvfcBo9JlcUPO2whrmsiVI8WOX4O6bVwTwU0qw8v5cXPVlCHbs9eB28m/pjOzafgrx8ntG8JaMIPCwbprwU7JK8MplNu6YWFzxJ84G7eyEYPWqui7xRjyK8kZVOPUpovjuQRww8hrCSuieJQDwmFJ48u1aXvJRE2Tt6gJe8R0LLu/RPt7zIc5W8wzdYPMnyhLz9y328HL1ZPd8ogrs3NpM7eiolvOyj4rwNFbC8QiAtvO53XzxrsPK8yCZyvDy2BL1T4JQ8ZK+lPGDHhzwORf88WuEkPPZeKzwuZte844KHu6PVrbzWAAa8LPAWPMofEr2L8kq8xYn7Oz0RSbtJWu285234PDQ9ALx93zG7xRHPPPSGyLx71sk8ZA1RvJJ7mDwV4J884yWXPHYRKbyOJi09mffbuqC2CD0LHeG8XPhdPa+4CbuX+6Q7FQdFvCXbmryd6q07TjEWOyG4YbtfQPS8sSHWvLgZgrwnSkg9FICcvCz08Du29gi8cXVWPON0Qrx9CZY6HSLVvP/tX7yFFcq8XAmoPCZ0Er1hg5c7cQrKvM++kzw+Jwe9IjhjPCDyALz7D2+83HniOC9nUDtk/Fg8M+Z9PE5YPrtznne869RlvGpCMLx8su27xheTPDyKwLu7w7i7uIkIPfydRbxUXN+7zwxvvKyQ3LnaFkq8ZCfcPDhN+ToZmKU7Eh4JPIWITD3D4oC63oQFvC6mozxCsZ+8xp4svdF03Dua+6G816U9Petcc7ysMzE8FdDnvHmWUTxvuYc8aVGfvNZlaTsG7wG8TiLEvFgIgTyRzsG8+PwTPLmr17tDfrK8nvhiOc9Ea7xrYPw7XiKzuxa3Fr1DkJA7kog/PJG2jLprsig8/ijevLM2RLyha5q776ILvNz5iTzzVji7NqgpO9T/YTySpW48H1K6PHEkXDzwH328iZkKPa0G+jvnFLo7FNlkvAtAyDsp1Rw9L/pHvNwHEby6ZU09zOKyPBu/RjtUk4q8ePcZvdGOiDsJZ2y8V4YOPej1lbxV6iO8XVXFO84hy7sfZjk8T1mku/5l4jsC+BE9/ID/O5hLrrtYCXM8B55AO7bzEbx+SfQ80Rr8uymiiDuhkNA8e/39vCuGOzyTah467fe+OJmafryVW5u8P7OWPIzZLLxggyQ8liWoubZ2IDsOrR69JrdBPINqQTtMEls72a6KvJiKXrsqtMM7sAkAPUykQ7zFZzq89WwyPGutYLzyHTw9tAS3POCwhDyd9CY7lmzBPE8QXDtRU2m8SoirPA9t67zeXlk8lo/Ju152HT1mcf88bs/2u+UQUzwi+vi83ekPvGyb2LwU+wG9bxiNPOpynTxMFnU7LIeNuz/QVjyMbqu7+QbSOq5KZDvMqJS8NBG7O5hkLTyfHom7VoEWuzb3lTzYD5W7zg4XPbRbsjwVweu7s0ZePHGWiDxt+o+8eKeGPEarGz3ZMLg80S2DO9cjBb1pftu8KgOmvIkszbuppOc8qOmwPNgW0bu3xZK8L/euvBIRsLz4BMw77S3bO5wVkbv3v208F83BOtb3B72hDWk8eGMovUx+KTxLhO47Iiz5vBEWwjzmqTO8q8m8upiDaLwoqRU8V8LBvKOuOjzjeyQ7J2G0O9/74zxP7CO8k8mZvKgMxDxLZv474buMPGkACL29trA80bjRvLJVvjvJfcQ8+JUUPZx5PruwTfy81Q6MvBXatrw6fRG9d2qsO9nooTwxMyY73O1TveDIprs/Lo+8AQOqu+BqUjykT6M8A/jnO/CiUzz3l7g7rJUuvCZXJLxFHlo7iHj5O1w7cTqYX/E6vaQNPfFfkbrzW/u8HINfPA1N9TwXK6a8lfinvLRrB71VlY68vfx5vZxzPrw9HZA83sFIvFm5Bzz80gA74cO3vP1dPruE0xY8tegMPSdc37z84bY85+EbvYuTa7zkfzC81KRFPBD0kDxY35s8JebxvFjbv7yqSwk8x16Yu6YDwLxzMam8Xi3PO9n/xLvyPOo7ZZ7EvM7eDj1xMFQ8oYyXvJ1DczvoD4I8ApxwvFDuw7xenTu8264wvcsFzjzu07w8g7TaPNQfY7zkIWW8kUr+vOsbj7wj/Q69IYYcvYKmNzx9pUM8CQUQvFAVDDwLoXo8UbIiPeDKFbx5NO27j5QvPeuDrzzBniI6AKSsvNqvZjzTer079/i0vD2Dabw4Dsy8FcWzu/k0vTx8Ggc86p1/vMk7tzxKIx07fm6nOVGFLDuG0WO8GC6OvDvUCrtPKow700m6vDtDrTyHZL68y4OTPFMDi7xxWbK7HvW8ureWgjypGp48+GuavBM1nTx/1gE7yhrCPK+qMrz4YkS84m02vCspXjyaAAU9ljjWPCMyZjrV9Xa8Rt2evKEnhL1IX0C8xlJPPQscbjy9AQq9h8etPDok67msAWa8tCwaPUORODuJGrg8hNmaPDMtGLxa2Ka87IUAvY8qoDzJ3J68S4bIvMVULDxfabi88nipvHnaaD20PyK8Ec8bPGREILwSDPM8C+clPWFdL7y+oVe456Q0vRtCvrx3Tcg7j+CzPFfsi7s06rc8BILcOqs5rjsj0Ka8s/ycvFG73rxPIAU8MvW1vLzEID0FbtQ843atu7CNvLvvWqm8w5JNvJ7dcTsjtEy8j5IZPHWv9LwDHK06FTHdvIsO6juUUdc8tSBouyXMgrgt8wG8KjI0PU8Ia7ztRpK810cvvLBtKjzyLj28LHv4vJt/TrtOSfi8JCQuOsO4L7yKuWu8fxWuO44gErpPPTS7/PX7PAXYvLu0g2c7ORCFvEOfqTpqDs28o18IPQVZlTxrNTG8qwgVvSr+SjvxdaE8qetkO0/a2zt/p228SEizvJqLFz1Y6ZC8Ih8HvL9spDvDgi480iHLOgsGl7ySb6U86UwBu809U7wZFwK85GQBPEKXULydLxE8oRMAvFOtLrzSixw8cCb1PJacmjzU7wu8AOjpvPJtibsGQTC8UnYgPAdzYTwbvCI8rM8SOx9CULyBfk69TiiyvIduArwWdP48m08ePGQtELxE2aY6NsCZPKhozryW1y+7Ib2AOzP1zjrHTaO7uaQGPJK9kbwwrug8O7wTvF+qMr3Qm7G8jrLmvGYdWbx4m+E86/i6uhDUhDwIi/Y8WJEjPTF/qzzgMxM8A763OlK2XrwahCu8U7qMvDo9Dr3VQUc8THrCvMp0Ij2AAdW679e6u+Batjwhoa68ZPQ6PApc4jtxVMs63KcRPdhQ9Dr18LA8VqyLu3ZoKbx/ytE7+lhkPJ4sQzyT2KK8uudfPCmnArzaiCC9cxxfPCBhzTuT2YW8XXAePBMWx7sXrGq83KtUPMdp0Lt8hL+8/6ZEuzrr2jwxLJw8Qf8FPEKk/7tVzEW9wU4/vby7u7uSUPm7ioTHvA== index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 15 total_tokens: 15 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '127' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - Our mission is to make technology accessible to everyone. model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 11 total_tokens: 11 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '8159' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '610' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t index: 0 type: function created: 1769707352 id: chatcmpl-5 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 65 prompt_tokens: 1719 total_tokens: 1784 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '9143' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '680' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl index: 0 type: function created: 1769707353 id: chatcmpl-973 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 86 prompt_tokens: 1971 total_tokens: 2057 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '10213' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '626' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: 'We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let''s attempt: "print(__dict__.keys())".' role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag index: 0 type: function created: 1769707355 id: chatcmpl-404 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 65 prompt_tokens: 2247 total_tokens: 2312 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '11089' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '593' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra index: 0 type: function created: 1769707356 id: chatcmpl-596 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 54 prompt_tokens: 2464 total_tokens: 2518 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '93' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - company founded mission model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 4 total_tokens: 4 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '11590' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '637' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo index: 0 type: function created: 1769707358 id: chatcmpl-564 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 77 prompt_tokens: 2557 total_tokens: 2634 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '93' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - company founded mission model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: TIsSuYSE3Txwv7E5gk7LOnJb6bkfxII9DnGXPaEaVDwJIiI8Q3rgO57vd7zAgOE4Uz7YOkYSsLzvB3O7oSxCvFncmLxBWja9n0CpO0disbtFwUq8fYwoPaScqD2YG2s9oPXsO4fAlryXtcG8Ek0bvYHKErxBF748P38GOlmJHr2b5808dyvXvA+7IzvubjC8aSQzvNCDArxMUDK68EUHPZGC4jy/LS29D615PJDd3DwAHr+8IvlEPKMr8TqddkM9L7fkO7JJqrzsBBg8ZqI2u7cW0Dw7HN28uZYwvJ45ETy9r3Y8ec8du8KLOzx+xK484r7nOvYbdrxA3Gm8VyQUvVBJz7rTUOa8/ynHOrLYCr2w8Eo7lYY1vLirqLy5ibk7omPqO8HiIjxieH+8usALvWgU7rvcrGU8+/guvGoPhjsgYAK8wH2KuxXiSDxscDg7QuQ4PGVPfbxmo2C8X0WNOxnszrzcTbG7v/PNO0BTXTuVQ5U6tZqEPL24YTv1NBU89UQNvFxaVrzkXeS8ynJNuoqAhrxjDcw7PbKFPPMiprzH8Xe8qo4AvcyTB716KA+8f/BaPIYSdru0d+87k07wuyS8NDz7mQU8wqLGvNt9Zrzax9q8BW8KPQBWcju4Iv48QUV6vLvgmjwPuzQ8xQKkO7MKRbyR77I7oa0au6nskryb2008fDnkPO7iJzzrUAq9hflcO/LJk7wSn3C8XwBKPC5AET2AP5C8aKwgvSSmkzxmMZO8xDStPK+mBjwV5D48OLs+u3bKBb2fR2G7pd+UPLLIoDykjvS6lTZPPKzLMby6XqE6QMhyPKir8rtqOgQ8UD9VvHmVvDyO0bc82D3oPA2kxDwei4A8bcWWuxWNYTycqAg7pPwIPS34BbzdW5A8iSzxuyVVNL0fqcA8IP4jvBMdurxYL8q8n8aHvEzcXDwzWpO841UbvQt8qLsc0GA7NycCPByAv7so77I8wFJ0O1chuDwJUqk7bDIivGtkfjxKvpo6lGTQueCPE7o+OQy9GkkUOz/tkTzzU768BwQrvBmQDLzxOvG8QOoXPKWxmTxvekQ8MJEAvMkQnTvvsXM8NJg1vHtu2Dod8Sy8Qpt0uxrzprzEhZu7gigMPJWAcrzU3La7maO7vHNZYruEuH08tegBvO04i7zzr2881GAJPHO8rDzFqRW7LgGCuqcYIzxeG2m8LCi4O0/9VDx9sUk7lsiQu7sXOTuY1fQ8KMTVPA2gMLzq5xS8k4XMuwyaqzsce+q8TpeavAktMTxuc+q7ls7qu/DwWLzej1U8hPOnO97MYbxGusu89NDpOuqEQbzY9Lc6yUTxu05cQLxncFS7J1QSO9xm0rxtbwE9mRZsvEA2krw7+hM5tYOLO9fL3Dy0ml64WoCkvIZHlLxO6oS8VVUwPJV/nTxg1ic88MUlPOLQijti8SA8kUqlPELJS7wbNQ+5cTVJuyBjkbwGdZa8gCEUO/FSlTtkshK6lwW9PFMQ3rxJD1M83TWxPBMqq7vMGnC8ln6EvCVaEz3s8h27YPK0vMKXjzxHOw678GmKuwHNAT0NmZu75EAvPeosLrxyWiI7Wx31uiR/KbxC9Ke7UyqkuyCPIDwYYmC8D7vau3AI+bmqtAu7aRBvvLHZF7s1SiW8XztAvVYxP7ulKiy8aW8cO5V97TvxtRi9BYH7vOqGl7tMTmW8PgrXvHgHsjrdqQg72GyKvddDhrw1Fa+8LkZ6vLwlPDwrnkg8E14JvJs+4TtGqxe9DDJ1uj51dDt1B+a86Areu/FRlDsEdcu7Uik+vDSRqzz+/Q08M2oIvFBwlbpWxKC8U/CWvDmsK7xWSGm8xdYhvD9azrzPR1E8WFaTu5mdD733G0w8A5mavLXbnTrvlUE6wSzBu/x83TzSqQy9mvSXO6q/NjxsfEU8BkEtvAVJDTynEkQ8Yh8iO4IS9jxu7oG8nVzBvKPMFz3qUB05By4GvFcbSTzMELS8SV6DvFin2rzDaP+8CyywvDxyUby6GCy8vkxwPKrTj7z2ObY8K2xtvHD6Db3/kjY8PC7zu4pxBz0GI1q7HJHJu5MOnDw8SUy72PicvP+CDTwX0lQ8FlkqvL9XNr0MMTS7XlqyO/TyhjyVf8e79/e2vI2T0DuYRVS8702DvEGRpDzLP568O0EmvdI1ZjyMPT89oT/tPAbJHbxAY6q878/IPKhsH7wkFGS9Or35PPcXqjwHfQi8D7vdvGAzYTx9bPo7KXe3vKBzQLwLIkY6wkM0PBUvuLwbSR48yL59PAqH0DxTuI+8e1pWvNktjbyVL088sJJ5PBoRCz3V6LI7fkjXOsEXiry5Nve7BQwVPaq+GbtCiR47nImfPER93jxWuZk8yLIKvFAQJjt9m0Y8zW8xPQ+5MDyo76q8QNCMuzgUMz3hX5U8rIHNO9AvOrobRtE6qrYdO9IqiDwbuCS9yXFAOydpcb1L49O7DFn1PFhPDb0n0Eq7RlFpvC5RaLxkqrS7He+XvJ7eZTz2NwG93vdcvNFBEr2nsgg9iqzGPI+IvzzwjHu8losKvedQLzxni1A7PglzuhpvXzthAhQ9TOIPvHVis7z5lMo8uVa6PLx9sTwsDCs922e3u3dCj7nNRVw9YIjNvNpX2rydeKI74b+wu30XkTxr9KO8G005PDpmFLz5Bcw89AnEvDZS5DwqU/k7JZEnvd4bo7qMd4g8MeAHPGSHsDoa0cA8FktDPDUWtDw8GhO9ZdKvvKhOtzxrbN47iGtzvMr/PzyfjsG7uFRLvBT9+bnPJrk8pfytPKu+jb1Wmh68RTToPH0k2zwWf9O7kOgDve8gTDpSmf28ISRDPItwozy2HKo8nlotvURfRTxdG2Q8h9hAPX+T9bxpl4G7a2x3vL/WcLydXFg8fP1jvASJiTwNp847oocAPIw2BzyLLSi9pVgJPeKDgzq3lsW8cJKtPK4LDrzHk227s7m+O+O7WTzLjpS8EThjuRxYnzupuHw8V37iu/p+QDyMF86774jOPL8z47t6z1A8oW3EvDog7boks/q8w5mWO+ydFzwho5u6IvFXPEEqhbsZTyW9KL+uvDS0GzyRtLK8BqJTvNvujbsCAXk83iHJO+pZAz3aLbY8eHOZOt98ALpkYPs7Wxs2PEReQDy9lTy9tUvPOwiMVbrXZ/S7cTifOwtY3rz3uU074qGwOrUZGb0d5tG8Z7AKPRnXFb06vPu8k4pMPcBA0ro/uSm9IjKkPIqCXbsiYdK8DdFkPBIuirt9iMe736UEvWuyjjzMn5s87/IuvHS9AL183+G8qghAvOkJoboW6jE738YeO8llhTwFWA28tlwJvNudLL1Etaa6Hs8UvMMRDzo6ncY8JJQQPFzwlbpsCGY8NZCDvFxM4DzkF6e7SCcgvbtvTLwEcl8727qPO97LgbpMpNC8v411Omn6l7z+ixQ8AosAvUR4Cr0qjeK8S2/JvGjvITutMm+8lA7XPFNiUbsqNzA7912CPEFfFjt+T2u8lHG4vBv6szzf8Pk6zLSMvBYAP7xxm4Q7GHDmukbb67ur1sG8/Z9GvLAE9buOGF89J5zdvIRH9rxFWwM99BkCvED/wrzmuu48BG4IvSkJijzEX5U8sKsePbknEL0vSKm879QOPJOvbzzMOs+7MRv8u5JttjwLhwu9+5UYvKs5+Luph5Y8io9VO+snX7yJfVo9r2FqPJBlCr1uKB085DOevEMQ5TwhTlG7Xk8IvaxsI7zRBgY9iHkGPKIJWbyLAEo7FfQHPDZnPTuInKM8h8I3PUF+Hj0IRQS8JiRAvUGJ77yt2VS8OBxlPJIqJL3l+768i4v3u6MlqDxEeR07TlGVOyA3HL3HIja9ji/+vPaS4bw7Xrk8MjqfvCD3DLsF1Kw82rQ4PYyryzs2+g07HIj9vKxm6TwyGwK8Q4cAPb4lqLxX3Se6df6YOovGwbzxPSk9tkzOOiUe1TsgjAq7rIkjvem6OjyYF5K8OXcLuzvEAjzgqzU8Nk9IPOnXzjyrCh082im/vLdVW7xTIT483DfHPGWPobv7VAa8XOmOvLL1Dby+ps+8/1s/vNgPJrx1yHi85nJMvN3blDzOvzY8/fP1vN6IIT1dqAW9kBgbPW5h0bsvNOM8nJCfOyaA7LzT2aK8NSBavLl/HT0UsvO8vAR9vKThQL0sxdg7WjUpPBxmqLzrrJI80I5nvMXn27xgWgC7hsV/u3b7Bz2l+Wm8vbIHvH/hdLqXyoc8NQ5LO6ADhLszp8C83bDIvMOZR7yiEpy7NgnjvGIDALwxVv08EksCPM4/ZTzznKA89gZZvAWNujwXne45U8rhOsWSCr0m/wG9fTETPGN7AL3sRVU8X+lCvJqf4rvvZsO73N6bPM6q+bvGMY48iYlmvBBYyjv1WrM8yqINPCdaVT2037Y7QNXnOLFI4jzxLMa8si46OIUfSju4h7Q8PrwRvMsYbLxwqwO99RAOvQX3tLzy8p08hLUxPM51VDwsQRo921oGvRMeAjzo14S8m1WgvFPRITsI3je9AUdfu5VEUj2vcBE99BYvO2rvwjxBY967TVKYvKdohDziVGg8961/vCdQC70q6iw8fraEvW7giru3OxC8/bppvA/iobvZt8Q85nFZvALw4rsMruy8anO+O4k5jTgvRXs8oaNCu+5BEz1ySqM8iiKjuyRiFrzpd8O7lskQu0Wpz7nXiey898D1PMltXLx3P6S8vZGqPE74G7tMbDS8TjGmvDg91rvDhC08R7pkPNFTxTzfQoo8fKD0OhVPdLv9B588seGVu4sGHz1D6pS89HVvvOnFK7sp53Q8/rc/PPmKBD3k9qc7NfHbO77UJrxTxZe7npoIvP6bJDw1I1i890m/u7ZYPDyAPoe8naSfum0MhzxWuPY7E3kAvKu6H7yF3v88tNplPCgcE716WRE8qhmwPJc0GLzgqVy8rQkGPErr6rzqeYy8ftuVvHJCDD1VklK94xvrvE0qFLzXeOg8KmUJvRVcPTzheQM8OifSPCULFL0JlUE9u8IkPGVHLT0BcIC8vEKXO8yUgLujKr08x2/dvB5BRT1WphA9edqAvDSBlbz6A8G7LjFJvK+sf7rnV5s70SJJu5ix87pbR5u7RmqbvMaoAr28HHA85FrgPGGHb7svP3S8v1ELPBxVfLoAMjG9/z4zO1UVxLth0pC6WF+LvIAdQLyCTKa8yK44Ow+w5jvpPwg9TRCZPOQTWLwsSPi8mlO4O39JDLvKs4e8RvpgPNecGrwlFog8FL0Su5w9XDxVxf+7Y3OmvHvBz7sCtmy7nLIOPVQ2krw7hAM9dAIVO76LazzS6b07isn1O0nQgLzqNNs7yaWePPCEz7wKU/W8OHG1vJb70jr7skK8SulePD/lxLxRYd67DPzyu7rguDuFUAO8j14sPBY/6TyTKmU71G/APEjfj7wDIrE8lyWHuzs3Ijz3xe07tfbpPBNiQz1N6QO8Hhovu/WXarsSjYI7yV6+vChGyLp5P8M71w8ePJWsKzvVyJC81JrgPG0MAjoka368nPvLPNQxdDtUQdu8Z+u7vHABqrxxLQG9cojRvCALF718I0s9XP9BO4LdjjzZ08g6vJ4TPKcGGzy0Ahs7RqI1vKzys7vrgNc6LTIKvHI/bTwxAFY73CHaPPvPvzu1vIE8nxUAuS1jhTv9FPy8h6PUuxt2kzyG5TE8AVC6vMPQhrvn+Fa9a2NRvL5dAb3CtV88YLNYPEPt8jtdvF28oRN8vENHartJDvS8LenaugfFOTz5U5S8MXl/vNdrfLwb8xG9alHUPMnLsjyj0qe8kJE5O9SvxTyTeWq6PCUdvIxNhjwA3Ek6Mw+HvBhyMDzsMSg9Kuvbu+NFojw5lwO6nGeBPBkDyju0iiM8m+HJusGdKrsM+OW8zjUiPSGDAr0LUhU8AhkQOqNLFzxnBAC9ZeHVO+6INbv7Rki8CJMVvDUhIjor8Zs8H62XvLg1FTxnBsA4R3OHvMl0GT2CY+48RHnTPDB59zw2ViM8CwMXPNROlTyzmrq7LS2LPIWrTjt+PYE8X/0pPVv1Vj06SDo8GIeJvOSm/Txx+JM881c6vGreUDt6D2E8es5/O29GprtWTAc98rR2O29jOj3pb6G7wiiWPKXnLrz9FxQ8mY49vGLVZ7wbXyy8pyXFPGUoWTu+A+A884BDvW8U17zTtZk7luKDPDwuuTunMxM93xETvQgY2zxrPWS8mrSMu7VAv7yxia27MVH6OvsqybywQJc85iyeO+9rDbzLw/M7/MGjPNvE4jydFxC8AjTPujtJPTw3Okq8bz+bPHDNJr1CZzQ80fJyPJu5pbrOPo46Y7L7u6HFjrzp6MA83B/WOz64Rjy4hwU8FKwrvIQKNL3cMJE8XMSVO1KPH72AGb+8AFHBur5jwryLKY07SVFUPHZKybwnSPE7MKmJvGE/UjuOGqk7Asj+PDBnZjxq36Y8Lapvuj02iTv/2ZM89ooDPdEsFDxfDf68wFSmPJgmtrzUNJW8RhKBPLx7OLzfEHm84GinO0CKWryRG4m8xiMPPaT1zjwCQCK7oRYXO/nKHruzvlg937QfO8Zdo7zonq873cSwu4W3RLw/0FE8rZnBPJU3xTzeu+w7aisdPfjSqDz0b0w9+uUHPdMbybpG4Gs8ZswKOoMxXrzyhi88yORovEe0Szu1Hfe8sh1pO8D8JDy+Bgw8da0ZvWX4Lbs3aBc9DWnUvMabWrxM/Iq6kPugvPBj/DwymEm77IkHPX8F37s2Rs27kSzgPKpsBD2w78Y7+iGvutpDCj1C1sE6OB+VvCDB5LykeCW7/4TYu3kanTwwbkm7BnWWPOYn3TtPhEI8k7MmPK/qEL3jeBS9i4j+OmAhl7zD06e84tyAPPMZET1pTY+7UA5nvI6TMTuRPRI71fgFPNYsort/uSU8dLZjOi7ZNbvaV9s7ZMa4PBiICLwZaYi7SRT4vLnr9TupRrc8/eCTuyYQCr1Wo3o8deiAvA8Dnrx3IKk8zyZEvPVjuTp+4p68nrKou7vx4rwQDJg6nJe+vAssBLitNCQ7jkXkOw7E6TymKcI6StsNvLmf9Lxh2VU8g0O6vG11oTyYsQ08/1i8vDXzrztItpG7caTrO/P2ND2LYlY8SAHYPAPw17wTGi+96dEIOw+jxbz+gT07f4M/O+hAJLxMhhW9Tnu0PKauN7sHcZO89zFPu1e9vLx4sbE8ec48vBjuJrxn9K+8IdmUO7jgJLo2NKK8cDqqPGO1orwdZce8HXhqu3V40bw7xue7z0eVOnpjDj3Wu4k7/hkMvXsbGD1Pxqa8t6LlPIspqrxAAfo892L1OxnPKjw+iho8gPPcPKMjAT2RMmQ8Ba88PEW4m7zpZ0o8ZCOHuxmZ8TzpFAK6wPD5vP+hKz1s40I8cnCVPFo9bryx5Xa8SMGlO8QpFbx7wNM8FVUSvUd4Bj1E9oo8Jqehu4IesDybz9082CGPPLY+xjt5oa+8IV6quzf5qbplSh49ImyFvL5b8rvwW6a8+O/NvA2P1zwMnTe86MnsvIrGzDsgbpy7v+2guyI2Er1qcmA8i9wZvShivzne1Ew8qt30OeMv4ruw8168SW3YvEVJOT3ISaK807dWvH7aYDylbUW7jvz3vG4oIbxb7My62J2ZPGU2/bpRcBI8Ob+tPP0qET0Tkz679ACLvC1kj7z8vFk8pATnu+IEmDw+bkI8csH3Ox0PgrxmdsC8qoh6uo0Xrrx8kFw86jV4PD8n1TwzD9w8Uz1dvHfQDDyM/x07Hg4jPMsrfTvDTDU8jYUlPQj6vrw4x3M8QJKfPHdN5bzRiAa9mI+auj6MVjzTQ9q8dAXavIqHBjzVL+g78O8ivBOPmrxm0fw8UWMUPf5HD70lZB08v/FOu2Oq1TslCgU916QePALPfTz+bWu7yB+xuzbpTrztvzm8BnqYPETywLyeI9088RrOO0fVzDwoZXG8LrfMPBVznLsmAK+7EBaSu3xS9zrnD/+8rrS8uzZabbwwzQE9QCcCvLeuvDsmLOu7bMcwPXOEmTvk3+o8eufhuoY7BTrX5r88EDoCPKfkJzwNA1694QQNPUVqPDy2HuS7tOr3vKmCoDzQ/FE83juzvGnXfjw+wv+8rZ++PHMDu7zuBPU8DLaxO+Aibzz31GK6XXQgvfZw/buvjqo8WkinPHg6FL3GZl46u6zyvJLi/7y8RdS8qRUwPAYANLzZdZq89GufvAKkurtkw0A8CFwAvfvC0TpRjNS8kHlRPEiOiTwGgr07yO1IPO22U7xKsbE8mZwAvCnLC7uH8Qc6SrUFPZhqIb2kAJ0727kAvGwbqjynhyk8iLpAOqYdL73+3rS82FFgvHCM4Tw2TAG9GsdPOyU5D70ylLG7hn5tPEZMTzx/2p+8FC3aO4MXgTz1Ejg7c+o5u8JFRzzbaYA875pJvOjFJTz3XL06lYHcO/SQzbuS9VO5zTpKuZtV5TwDPKq87hbvvBBMgTwtS9w89ueGu40k9DuUHuG8wrKUPFcKC7ywMrs8ami8vP2KfLyBAKK8x/LQuOemxzr6qx69bcjAOyelhjxq8Q+91VkSvLJUvzzW9hW8pc62vDWXnbs+w1i7BQazOiJT+bwSfAy8KuM3PYifdTuxIeg5lAEwPb4mpzu1EJ27pwSnvFWu3jxXXMQ8tib9vOdFWboml+I8l4XVu+XPqjyCnc287JW6vLAKBzwzOPq8YnhKvP4CKLs4Hb88XrjlOmyW07tGytU7GkyFvI44KDwZNyQ8eDVDPPR6sLwpvoY85VqnvH9mQ7yIdGQ8BfyoO+jZLj2+LKi7J6gVvKBV/LtLlOo61wORvMd5ITzfUdc80uu+PDtH3zsOMM+7EfBZvOVHhTzpEAK9nPeRPLVntjuiabG8hnmjvFMuvjsxKCK7YYglveoQIj1LGVM9RnJevHJlnDsQvF876H7EPOq98bwaK+67Q0qUvDa3wbxz5yU7ftl9vK+OiLwAbdi8YruYPJKsyTzApEG83hgHPSW1/Lv1jre7tUtGPNxbf7wbTZI7fyEuPG4ptTwKcwq9bQOwvAJzozwn4Ua8jmb/uyU217uyFeI7Wu8NvEM+JD3mpzu93s6jvBYQrrxCHrW7YtNLOwPkaDvgOSs8TfoDPTHOrjs47I67Ux92u7+HpzzNNjs8au8QO8FXvjvh3dM8azYbvJtnKz32Gw88PwGcO0g05Lpsp6U86FKvu5n0JDyVII+8uNuqPC2NGzxgXOq8rMqbvFc3RbteSaY76JaOOzfVgrzr5Ai8zHO6vPV2ozxe+DS8Ska+PIIvILySsEa8cj3CvOD4GzxUgwA9uqIEvKjB07pds2M8+LBKvJrSEzveSTG8EIzGPIP30DtDIQw9Bjx1PN1dsDxxQW+7NJPBvBL3kztFL5o6OpcvO07r5LzWtNm6bsvZvMts1zuZM4o7cPGBvDd+3Tx1A3Q7On0gPXwKLTy06548mSBlvOg6SjzvPEs8l1qzvEph2btBwkw8MOnrvC1gLbzfch49bZNfu+L+QDx+oF+8qrOHPPTJpjy9tsk8rB0SPLRysLpOeU+8F4T4unTm87ttjy668uIfPbmZEb24N+M8qacaO9j6KL1cil88WvBcvJJt/zrd7UK89jMGvR592jzk56U8H62aPBaOTT1Rfrs81JhCPDMteTwhHQa8N4qcPKmvCL2JNq08dycFvQ7QhLxoFry8zZslvMwY3bwAf0Y8drq4urHuBr1QxCY8nOfDu4WUaTyH4WA6lf0+vBdDODohq5e8PT33vLGjqjns7ku7TyoGPVErsLw9sve8JBROvQEo/Dt3BVI73ZWzvK7my7r7QMa8WBdvvMovc7yE59W8v/BnvEU64zypXWg8qvANvb6B0ToeUtI8JWGmvCE/yzvVl7e74ieSPJBoubzIe6+8LxHNvFcJlzynlLw88/KuPLRvQbrtM8m8LWo+vMZxozrNIRe9G35BPO/H0jxV77Q7/hX4ueP2hTu8M1K7v/4VPUMi1jxwUxu6/CeAPIWjL7yfsZ489kb5PHwktDwWTW68bYBwPKn6UTzMQN885gwNPd4njTxdmw29w/P/OqnQ/zzXAsQ8mRfiu5JiJ7znRxG9YzBLvGL66jyXspm7/GRDOyiv1rxE+cQ6u4uuvA+ygTwN+0s8nGJTPM0oLzwHbNa8Q/aCumfKEjzCqbe8f6G8vNyIvTrgeYa8TOOSu8r5CD15yKY8g3+cPKzgrrvvuew7BSCvvL4PLD1iojQ9lA4cvMgZtjuP7Jc7KLzZO6BHirygc247CZgvPDRzgjrBt5W8svcYPD3HgLzRjZ08q2dKPPRNVjpFVsS7HY71PNIbgTzf6xi9Ua36O5Y6rbrGqfg8ex0YPcPwr7sPATo8b4uHPBdCLz0QUea7oKmLPKvHNryqvck7gvkXvJdZOzySnJa8xwkPPei69LyZj2q7An4EPYwinrpzbdc7KdwsvXAW3LyqFHW8GsfAu3zt4buDJua83ZEjPVsD4LxpSeg4ipiDPCXNBL1Cpkg7UgA0PBFDZjuEXAW6bDeyuwAo7bzHpVC9PzGHPKNYAr25pBW8qx4iPIOHNryLxgq9ZqkVPS/cETyaTwc7O9jsPDFws7nm06S8R6wivZ+9rzyH7SI9V5IbO7iGmTvXeAs9wJaHO7uKVTu5qWy9DrIUO94GYzzy3IQ8jhv5u5lTEDjF2ee8m99YvLtdgLz6RuC8C0oTuXGMJr0mvq88Df+0u4oATDsi+Pe7a2y8PIvdqTuQHXu7dyY8vNUeCrywEwy8hQsBvGzigruo8Zy8LkDYvMuxozwRKa28B+8QvHd3tzwNuiK8/llhulNIjDuYRec8SN3BO4arF70NFDK9/aUovSTNID3agYM8aMlmOOav0zxMmKo8pv96PK03xLwdv9O6r+zNvAJS/rvvNGe7B3DrPPll5btpRxk8ZN62vPsIgjsgeR+7cBf1vInmDT2ee+m6sV6NvKYFjrtbgje95fWoPGX8hzuBNAK9Qc5VO5S7lrvfm6a8Zi85PN4MObxUKpw7J12Zu+2pozz0Z+a8HrFwvK5pNTzOI5C8cCcEvQ/1HT0cqxM8VJ6Pu9HgPLz4J968wIc6vI1k4jt9SY68J+MXvZmdbby7Xeo7GUfzO5C4ULy9MJS8iKgcOm2R0zx0QQA7nYnyOo7wiDz8XCs89zqpO3qcl7wHcOu8Ob6mO7EQCT0H79c7UEDTO2cucDxAGJo8Mg/iPHWh0zvGwfa6sOeYvH0WFb1KpRK9HMc6PZztDLwqrdU7/QstPJB6Hrz8aIi8u+MOvHGh3zyo2g89y6z/PGdp7rvFYb48xa+rOxeMmbwNO9q5j0+IPKsGnry4oSC7QAW0vJjWSbxfz6o88G/KO5fCiTz8e5W8cma9PD4fbTwr3tW8Fi5EPOlmoTukmeq8ZTcBPcOSxbrBWLm65H+oO8SoCzxzrJc5kucIPSJpFj3nZfO7DJURPKDLhrwvsN277RP/O41R27wuVws8GfTYOY8BxLs3Uoi7vQqKPJvZtbvejBE8cN76vM66Izxdpl27bIMJvO1XzbxOiT47ELwVvBabwbzmXBm8U6khPTKkWbyDJZI8NcLKvM1OpbsFhOY7vq+CurkkjDuOdTS81MauPJtdnbzs0So8uLIMPDO+t7pgMsq8eoqcO1eokjwElgM8DLh0PC4martCFd0843NzO/7BXrwhaKk8Ue5APFTy5LzRWli9gS8xvNj4NjupHFg8fBAEPP17dDzFoXc7C4kKvQ1ww7w4BAS9/nkGPHWSODy3tMO8PqCHvOJKY7wT4AE9cTMNvTV5hjquHdk7FZaevIzCtbtOodW7Gi6Lu8mGuzsIkQE8q67oOpgIjzx9uy48bDSSu3+ONjqwi5684gD+OabwDLyFY3i67e8mPfHQYzsIiss8loyaOrO/mzvhaow8X1OwO2SexzxzFQ27bX1kvKavlrwFK/u8HMeNPBQ6Bz3I/MA6Dg2svMuss7slOxe9gA2CvEnQVbxzQXk7GknrumfQBbuOzY684SiDvF38X7sIarg5TbwrvC8iJjxi8pY7zB+EPIIYfzxRJ4G87K3XuI9RGjuFffa88czZvJ3IBLx41Y67Fhatuwb6lLxwrwo9icfEO7PwsjzGGNG8uYYdO720YrsVNKy8KoJ0PEArPLwQ4Q490M8UvWo1fLxCZUW8DsONO73mTLo+hOs7JiXbPF+sqrtGwJ884h6BvOru1Tt4vfQ7M0VNPG+C7Tx/gkY8ihQNPFs77jwTlx28rF1HvC1gXzy+tSo8SygivDSYobz13SS71l0uvCNaYrzOgdA89IkQPB01pDzulw883Z+FPDut5rwfE748a4CqvMD+vTwaIyY8SgP6vEHdu7uP1og8rKgoPQDslzyy2iY89pQIPKez07uAepI8Eh+JOnbIFrwlIBO7HeTUvJ3m+Lvjr6e883oJPAgfCryT/kW8ZFgIvS4Y37sECQ49+KgDPfac3blGvRy8oYGmvL5VULoTp5e8kgWJu9qpLTzQgM+8nDQ1O26tKryPgeG825efPKk3tbxtWAw8630OvFNi2Dw/J5u62WEjvM9px7w0fBu9EeGsuyvRvroNj848ln84PGGDpDwzloC7HrWqvH6OMb2xQ1Q6ehX0uyWRtbrx9sC8SZHQPMYZdTy2MFS66um+PIkz2bzkagm7L4JGPWoAirxeOHs8UMdSvHBPdjvqLhk8VOEOvZW307r5Xe47s6t7vKmpcDzuI0O73nPuvAAKmrwnZM88d/WVPFjdlbsK7R09T9v9u39sILu1JpK8AsnhPHEbHzuSAJG7R66Zu6weQbteCbK8WwQwvDj1zboDekE8M5kVvdJ3RD3Bk4i8ye59vN7H67ueuum8ky2wvLfOODsawto7/faPvFkIHrzbcw+7So4IPNP4Jzz3GrQ8rqKCuyAxb7yB8VK86b3MO3fJhzy+dze9SRHFuhp73rtWOgI8ww+tPBHgRTybgZO8PZp3PHZSJzvFQoq8iKriPPUvpjuxqho59tbDPH44N7y1BQC5MWRPPImO2Lsef+i614aXPMw6qTyOJ8U7DgiXPD6DwTw+YOM81ZrJPO+5wjqHCAC9nnO/vGDJIjxaNjo8wMykO33zerzMsB48KtaUPJwvozt9f5G8hEnQOWeXHL26hWw8SPAOPMF0zTys6OW7A+ecvBqzFTz/Ykm9fQJoOnjtgzwaXfY689HKvNq7Y7zXr6G8TTINPVdYzrxvsL08AbN8vKcilbv1qD27BYmivMtx2rydeRe8R5Q9PD6BP7sGi0o7tXg5O5BurrsujG08kTnFPLOSJDp8wYO8G1wsPOiUNbxyxxi8dqwKvEx79TqZMcG8pmqRvIGljDucTiE8sHBuPNMzp7rCa6E7+1ytO6T5Lbv3k2Y8ntqzuz+Akzzs54w8bAULvW6+ILwEUB28zv3QvIgfhLsBroE79hfauuKmXzz+XZm8clxWO4Iot7vO9Me86qzQPNxCybtpvR+8son3PG5gmLylAr489yf6u8hVs7suei89WYuLOxG9QDyMhBW9IAyDupe4KTwy0Q+8cmh8PG8PujvQ1A88pZAfvGHEwbtGYz06fgWjPOW6hLu5X/E8GLVSOgX4CLswtw48N0qKvFYmW7wvVsc7UXFquw== index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 4 total_tokens: 4 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '12462' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra - content: |- We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo type: function - content: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')","stdout":"Mission Statement 0.032522473484277725\nOur mission is to make technology accessible to everyone.\n---\nCompany History 0.032522473484277725\nThe company was founded in 1985 by Jane Smith.\n---\n","stderr":"","success":true}' role: tool tool_call_id: call_tjt6miwo model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '872' content-type: - application/json parsed_body: choices: - finish_reason: stop index: 0 message: content: |- **Answer** | Information | Source | |-------------|--------| | **Founded:** 1985 | Search result “Company History” | | **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” | **Key Findings** 1. The company was founded in **1985** (document “Company History”). 2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”). These details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches. role: assistant created: 1769707361 id: chatcmpl-700 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 118 prompt_tokens: 2766 total_tokens: 2884 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '13928' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra - content: |- We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo type: function - content: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')","stdout":"Mission Statement 0.032522473484277725\nOur mission is to make technology accessible to everyone.\n---\nCompany History 0.032522473484277725\nThe company was founded in 1985 by Jane Smith.\n---\n","stderr":"","success":true}' role: tool tool_call_id: call_tjt6miwo - content: |- **Answer** | Information | Source | |-------------|--------| | **Founded:** 1985 | Search result “Company History” | | **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” | **Key Findings** 1. The company was founded in **1985** (document “Company History”). 2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”). These details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches. role: assistant - content: |- 1 validation error: ```json [ { "type": "json_invalid", "loc": [], "msg": "Invalid JSON: expected value at line 1 column 1", "input": "**Answer**\n\n| Information | Source |\n|-------------|--------|\n| **Founded:** 1985 | Search result “Company History” |\n| **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” |\n\n**Key Findings**\n\n1. The company was founded in **1985** (document “Company History”).\n2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”).\n\nThese details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches." } ] ``` Fix the errors and try again. role: user model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '833' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: Need to return JSON, not markdown. Let's output JSON array with fields. role: assistant tool_calls: - function: arguments: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))"}' name: execute_code id: call_hx2g2fr3 index: 0 type: function created: 1769707364 id: chatcmpl-261 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 110 prompt_tokens: 3076 total_tokens: 3186 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '15192' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra - content: |- We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo type: function - content: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')","stdout":"Mission Statement 0.032522473484277725\nOur mission is to make technology accessible to everyone.\n---\nCompany History 0.032522473484277725\nThe company was founded in 1985 by Jane Smith.\n---\n","stderr":"","success":true}' role: tool tool_call_id: call_tjt6miwo - content: |- **Answer** | Information | Source | |-------------|--------| | **Founded:** 1985 | Search result “Company History” | | **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” | **Key Findings** 1. The company was founded in **1985** (document “Company History”). 2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”). These details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches. role: assistant - content: |- 1 validation error: ```json [ { "type": "json_invalid", "loc": [], "msg": "Invalid JSON: expected value at line 1 column 1", "input": "**Answer**\n\n| Information | Source |\n|-------------|--------|\n| **Founded:** 1985 | Search result “Company History” |\n| **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” |\n\n**Key Findings**\n\n1. The company was founded in **1985** (document “Company History”).\n2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”).\n\nThese details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches." } ] ``` Fix the errors and try again. role: user - content: |- Need to return JSON, not markdown. Let's output JSON array with fields. role: assistant tool_calls: - function: arguments: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))"}' name: execute_code id: call_hx2g2fr3 type: function - content: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))","stdout":"{\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_hx2g2fr3 model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '507' content-type: - application/json parsed_body: choices: - finish_reason: stop index: 0 message: content: |- ```json { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } ``` role: assistant created: 1769707366 id: chatcmpl-781 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 56 prompt_tokens: 3346 total_tokens: 3402 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '15914' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra - content: |- We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo type: function - content: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')","stdout":"Mission Statement 0.032522473484277725\nOur mission is to make technology accessible to everyone.\n---\nCompany History 0.032522473484277725\nThe company was founded in 1985 by Jane Smith.\n---\n","stderr":"","success":true}' role: tool tool_call_id: call_tjt6miwo - content: |- **Answer** | Information | Source | |-------------|--------| | **Founded:** 1985 | Search result “Company History” | | **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” | **Key Findings** 1. The company was founded in **1985** (document “Company History”). 2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”). These details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches. role: assistant - content: |- 1 validation error: ```json [ { "type": "json_invalid", "loc": [], "msg": "Invalid JSON: expected value at line 1 column 1", "input": "**Answer**\n\n| Information | Source |\n|-------------|--------|\n| **Founded:** 1985 | Search result “Company History” |\n| **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” |\n\n**Key Findings**\n\n1. The company was founded in **1985** (document “Company History”).\n2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”).\n\nThese details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches." } ] ``` Fix the errors and try again. role: user - content: |- Need to return JSON, not markdown. Let's output JSON array with fields. role: assistant tool_calls: - function: arguments: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))"}' name: execute_code id: call_hx2g2fr3 type: function - content: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))","stdout":"{\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_hx2g2fr3 - content: |- ```json { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } ``` role: assistant - content: |- 1 validation error: ```json [ { "type": "missing", "loc": [ "answer" ], "msg": "Field required", "input": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ] ``` Fix the errors and try again. role: user model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '861' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: 'We need to wrap within {"answer": {...}}.' role: assistant tool_calls: - function: arguments: '{"code":"import json\noutput = {\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\nprint(json.dumps(output, indent=2))"}' name: execute_code id: call_docxc0ic index: 0 type: function created: 1769707370 id: chatcmpl-624 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 115 prompt_tokens: 3509 total_tokens: 3624 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '17302' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra - content: |- We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo type: function - content: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')","stdout":"Mission Statement 0.032522473484277725\nOur mission is to make technology accessible to everyone.\n---\nCompany History 0.032522473484277725\nThe company was founded in 1985 by Jane Smith.\n---\n","stderr":"","success":true}' role: tool tool_call_id: call_tjt6miwo - content: |- **Answer** | Information | Source | |-------------|--------| | **Founded:** 1985 | Search result “Company History” | | **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” | **Key Findings** 1. The company was founded in **1985** (document “Company History”). 2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”). These details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches. role: assistant - content: |- 1 validation error: ```json [ { "type": "json_invalid", "loc": [], "msg": "Invalid JSON: expected value at line 1 column 1", "input": "**Answer**\n\n| Information | Source |\n|-------------|--------|\n| **Founded:** 1985 | Search result “Company History” |\n| **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” |\n\n**Key Findings**\n\n1. The company was founded in **1985** (document “Company History”).\n2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”).\n\nThese details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches." } ] ``` Fix the errors and try again. role: user - content: |- Need to return JSON, not markdown. Let's output JSON array with fields. role: assistant tool_calls: - function: arguments: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))"}' name: execute_code id: call_hx2g2fr3 type: function - content: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))","stdout":"{\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_hx2g2fr3 - content: |- ```json { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } ``` role: assistant - content: |- 1 validation error: ```json [ { "type": "missing", "loc": [ "answer" ], "msg": "Field required", "input": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ] ``` Fix the errors and try again. role: user - content: |- We need to wrap within {"answer": {...}}. role: assistant tool_calls: - function: arguments: '{"code":"import json\noutput = {\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\nprint(json.dumps(output, indent=2))"}' name: execute_code id: call_docxc0ic type: function - content: '{"code":"import json\noutput = {\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\nprint(json.dumps(output, indent=2))","stdout":"{\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_docxc0ic model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '543' content-type: - application/json parsed_body: choices: - finish_reason: stop index: 0 message: content: | ```json { "answer": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ``` role: assistant created: 1769707372 id: chatcmpl-185 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 64 prompt_tokens: 3802 total_tokens: 3866 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '18080' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra - content: |- We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo type: function - content: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')","stdout":"Mission Statement 0.032522473484277725\nOur mission is to make technology accessible to everyone.\n---\nCompany History 0.032522473484277725\nThe company was founded in 1985 by Jane Smith.\n---\n","stderr":"","success":true}' role: tool tool_call_id: call_tjt6miwo - content: |- **Answer** | Information | Source | |-------------|--------| | **Founded:** 1985 | Search result “Company History” | | **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” | **Key Findings** 1. The company was founded in **1985** (document “Company History”). 2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”). These details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches. role: assistant - content: |- 1 validation error: ```json [ { "type": "json_invalid", "loc": [], "msg": "Invalid JSON: expected value at line 1 column 1", "input": "**Answer**\n\n| Information | Source |\n|-------------|--------|\n| **Founded:** 1985 | Search result “Company History” |\n| **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” |\n\n**Key Findings**\n\n1. The company was founded in **1985** (document “Company History”).\n2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”).\n\nThese details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches." } ] ``` Fix the errors and try again. role: user - content: |- Need to return JSON, not markdown. Let's output JSON array with fields. role: assistant tool_calls: - function: arguments: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))"}' name: execute_code id: call_hx2g2fr3 type: function - content: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))","stdout":"{\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_hx2g2fr3 - content: |- ```json { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } ``` role: assistant - content: |- 1 validation error: ```json [ { "type": "missing", "loc": [ "answer" ], "msg": "Field required", "input": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ] ``` Fix the errors and try again. role: user - content: |- We need to wrap within {"answer": {...}}. role: assistant tool_calls: - function: arguments: '{"code":"import json\noutput = {\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\nprint(json.dumps(output, indent=2))"}' name: execute_code id: call_docxc0ic type: function - content: '{"code":"import json\noutput = {\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\nprint(json.dumps(output, indent=2))","stdout":"{\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_docxc0ic - content: | ```json { "answer": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ``` role: assistant - content: |- 1 validation error: ```json [ { "type": "string_type", "loc": [ "answer" ], "msg": "Input should be a valid string", "input": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ] ``` Fix the errors and try again. role: user model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '729' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: Need answer field be string. So output should be {"answer":"..."} where string contains info. Let's create string summary. role: assistant tool_calls: - function: arguments: '{"code":"answer_text = \"Founded: 1985; Mission: Our mission is to make technology accessible to everyone.\";\nprint(json.dumps({\"answer\": answer_text}, indent=2))"}' name: execute_code id: call_uk6y6wn8 index: 0 type: function created: 1769707375 id: chatcmpl-533 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 86 prompt_tokens: 3978 total_tokens: 4064 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '18952' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### llm(prompt) -> str Call an LLM directly with the given prompt. Returns the response as a string. Use this for classification, summarization, extraction, or any task where you already have the content and just need LLM reasoning. ## Pre-loaded Documents Variable If documents were pre-loaded for this session, a `documents` variable is available: ```python # documents is a list of dicts with keys: id, title, uri, content for doc in documents: print(doc['title'], len(doc['content'])) ``` Check if it exists with: `if 'documents' in dir(): ...` ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use llm() for Classification/Extraction**: When you need to classify, summarize, or extract structured data from content you already have, use llm(). 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using llm() for classification ```python # Get document content content = get_document("Q1 Report") # Use llm() to classify sentiment sentiment = llm(f"Classify the sentiment as positive, negative, or mixed: {content}") print(sentiment) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: Using the pre-loaded documents variable, tell me when was the company founded and what is their mission? role: user - content: |- Check documents variable. role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')"}' name: execute_code id: call_1uonnu1t type: function - content: '{"code":"if ''documents'' in dir():\n for doc in documents:\n print(doc[''title''], len(doc[''content'']))\nelse:\n print(''No preloaded documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''dir'' is not defined\n","success":false}' role: tool tool_call_id: call_1uonnu1t - content: |- dir not defined; we can use globals(). Let's check if 'documents' in globals(). role: assistant tool_calls: - function: arguments: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')"}' name: execute_code id: call_40ur54cl type: function - content: '{"code":"if ''documents'' in globals():\n print(''preloaded'', len(documents))\n for doc in documents:\n print(doc[''title''])\nelse:\n print(''no documents'')","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''globals'' is not defined\n","success":false}' role: tool tool_call_id: call_40ur54cl - content: |- We cannot use dir or globals. Maybe the execution environment disallows these. We can try accessing variables via __dict__? Let's attempt: "print(__dict__.keys())". role: assistant tool_calls: - function: arguments: '{"code":"print(__dict__.keys())"}' name: execute_code id: call_xwupy2ag type: function - content: '{"code":"print(__dict__.keys())","stdout":"","stderr":"Traceback (most recent call last):\n File \"/Users/ggozad/dev/open-source/haiku.rag-feat-recursive-llm/haiku_rag_slim/haiku/rag/agents/rlm/sandbox.py\", line 340, in _execute_sync\n exec(code, exec_globals, self.locals)\n ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\", line 1, in \nNameError: name ''__dict__'' is not defined\n","success":false}' role: tool tool_call_id: call_xwupy2ag - content: |- The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search. role: assistant tool_calls: - function: arguments: '{"code":"search(\"company founded mission\", limit=5)"}' name: execute_code id: call_5dmqpjra type: function - content: '{"code":"search(\"company founded mission\", limit=5)","stdout":"","stderr":"","success":true}' role: tool tool_call_id: call_5dmqpjra - content: |- We need to print results. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')"}' name: execute_code id: call_tjt6miwo type: function - content: '{"code":"results = search(\"company founded mission\", limit=5)\nfor r in results:\n print(r[''document_title''], r[''score''])\n print(r[''content''][:200])\n print(''---'')","stdout":"Mission Statement 0.032522473484277725\nOur mission is to make technology accessible to everyone.\n---\nCompany History 0.032522473484277725\nThe company was founded in 1985 by Jane Smith.\n---\n","stderr":"","success":true}' role: tool tool_call_id: call_tjt6miwo - content: |- **Answer** | Information | Source | |-------------|--------| | **Founded:** 1985 | Search result “Company History” | | **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” | **Key Findings** 1. The company was founded in **1985** (document “Company History”). 2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”). These details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches. role: assistant - content: |- 1 validation error: ```json [ { "type": "json_invalid", "loc": [], "msg": "Invalid JSON: expected value at line 1 column 1", "input": "**Answer**\n\n| Information | Source |\n|-------------|--------|\n| **Founded:** 1985 | Search result “Company History” |\n| **Mission:** “Our mission is to make technology accessible to everyone.” | Search result “Mission Statement” |\n\n**Key Findings**\n\n1. The company was founded in **1985** (document “Company History”).\n2. The mission statement is “to make technology accessible to everyone” (document “Mission Statement”).\n\nThese details were retrieved by searching the knowledge base for “company founded mission” and examining the top matches." } ] ``` Fix the errors and try again. role: user - content: |- Need to return JSON, not markdown. Let's output JSON array with fields. role: assistant tool_calls: - function: arguments: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))"}' name: execute_code id: call_hx2g2fr3 type: function - content: '{"code":"import json\nanswer = {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\nprint(json.dumps(answer, indent=2))","stdout":"{\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_hx2g2fr3 - content: |- ```json { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } ``` role: assistant - content: |- 1 validation error: ```json [ { "type": "missing", "loc": [ "answer" ], "msg": "Field required", "input": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ] ``` Fix the errors and try again. role: user - content: |- We need to wrap within {"answer": {...}}. role: assistant tool_calls: - function: arguments: '{"code":"import json\noutput = {\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\nprint(json.dumps(output, indent=2))"}' name: execute_code id: call_docxc0ic type: function - content: '{"code":"import json\noutput = {\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\nprint(json.dumps(output, indent=2))","stdout":"{\n \"answer\": {\n \"Founded\": 1985,\n \"Mission\": \"Our mission is to make technology accessible to everyone.\",\n \"Sources\": {\n \"Founded\": \"Company History\",\n \"Mission\": \"Mission Statement\"\n }\n }\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_docxc0ic - content: | ```json { "answer": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ``` role: assistant - content: |- 1 validation error: ```json [ { "type": "string_type", "loc": [ "answer" ], "msg": "Input should be a valid string", "input": { "Founded": 1985, "Mission": "Our mission is to make technology accessible to everyone.", "Sources": { "Founded": "Company History", "Mission": "Mission Statement" } } } ] ``` Fix the errors and try again. role: user - content: |- Need answer field be string. So output should be {"answer":"..."} where string contains info. Let's create string summary. role: assistant tool_calls: - function: arguments: '{"code":"answer_text = \"Founded: 1985; Mission: Our mission is to make technology accessible to everyone.\";\nprint(json.dumps({\"answer\": answer_text}, indent=2))"}' name: execute_code id: call_uk6y6wn8 type: function - content: '{"code":"answer_text = \"Founded: 1985; Mission: Our mission is to make technology accessible to everyone.\";\nprint(json.dumps({\"answer\": answer_text}, indent=2))","stdout":"{\n \"answer\": \"Founded: 1985; Mission: Our mission is to make technology accessible to everyone.\"\n}\n","stderr":"","success":true}' role: tool tool_call_id: call_uk6y6wn8 model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '407' content-type: - application/json parsed_body: choices: - finish_reason: stop index: 0 message: content: | ```json { "answer": "Founded: 1985; Mission: Our mission is to make technology accessible to everyone." } ``` role: assistant created: 1769707377 id: chatcmpl-312 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 34 prompt_tokens: 4161 total_tokens: 4195 status: code: 200 message: OK version: 1