4809 lines
259 KiB
YAML
4809 lines
259 KiB
YAML
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: +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
|
|
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: ORG2uYKaPDyzYse8lBFFvN3N+roqMIc9+yOmPd+ApLwLVVY7G6pbvXAZ5DzJb1G9lLuAO+hHorxcSJE8fKGFu16Ikbs9kB69cDlUvF8d+bp7WMK7JbjqPOZEjD2X9tA81Z8SOxi4ML2YkcS8Y0UzvbOQ7zxMhKk89wAtO9EmBL1R5kC8hsTrO1N+sDtpeVi6z07NuncpqbuvQ6A7QivtO6bE1zwq+Ae9lAf2OscapzzFOyE7oZM3Oy+2qbqPNhE8YD43vG0XxbxplFU82fzMO3NDtDzDG+C8KFU6vZ3OcT278Qs9Hb7ou3HkkTx8/i887q86PDzb1jtwKwG9sQsFvZlIE7z0tIW8gbA8ueVTsbxcHoa7HwDZO2PYn7zkCTk9plLQvBRBhju6YgS7VsLVvNQPH7x6PW88CdxuvRuDOzv7aD68zVxpu9y0ejsk5u87WK30OxI6jTv4eo88i65Iu7B8c7zjGUg87Wcnu+eHEb3Ls2Q7NhC4PMoZSTzOxHw8Q718vI8pq7x0G3+8OwbPuxgQM7wwUny8zWZJPNdJs7yZ/gm9aSVmvPPciLxh2xC8vwmJPMiMBLx39CU8TNzhPGAKprzH5hk7S0qvvBDbrTueWXO9zLOXPFHnLDr4Qyc9LTG3vDWxpzxLIEc8a45kvLDlgjwJtQK9IsBJO7ZVlrtr8tE8wLiwPAHXgDyqosq8AzKJO3C7rLxE9Ie8wqipO6G9OjtwX+S8v4AivSTNqzyOqC47ry/LOrCm2LlozU87vJlYOZKeGb199w68tmWiPAuWvDy+t1k8jD2yPA6rVLy+tv27af79PAqTTzvyP+E69d5dvFG/jTy+AFE85uSgOns+pTwZBjg84MRfPMbfBj3ri7u7MlsSPE6T0LwGuY86H0+1u3Mzijx9+jk6S6o8OzjnDDyX1k68V8beu3uSeTxi2h+9ylMHvVbVtbuxGai8KgfLvGcp2ztwO6+6fjaauyFWlTyQeqc71sSEvI+ZbjyQ3qC6kIvdPNaAsDsQvq670sZouxJjjjydns+7YtLZOzamUrpZ4KK8gTDOPD5Kkjz+fiQ9H8Vhu0oTu7wl8ZS8+eMOPDBtRrtkVww8fWLQuy8hbTzyeJG82F6JPKqJdLwSgly8dktRva1tgrxebso8RuNivB62YbwONdQ8+DPpO6/YiLoQI6s6zrGOuyrirjrez7q8FFfYPE8Nojvv6sA74BoPPIaIaDwMhaY8MwmGPMwKQjtwlt287kMLOlQ+pzy/qRW8lnKRNylCmzx3+So8eHTrvM+OkLwxXpI7k1HQO4TKjTw02Ra9DEhhPLIZ0rsxFDS8qAkzvEeOxLsGOgk8uCPGu6lRgLz2oAS820sqO59+D70DoSg9UvHpu9+L/Tudlis8QehlPFWV9rtHDHS7LBS9OzM+mjz+wII7c7Wiu22wYjwqjzi8DYzPPI7QY7zJJHM8XH+xuN68nzu0t8m8wZPPO3i5e7lK4zI8p3nbPCJnm7xudYw6xwLru+sRmTxc+om8YWlAvH+e7jxsvvI7pFfOvNw9GD1bLAA7D5ztvA0rWDy16EY82qktPfitRrzkMQw79J/YusR9srxvgVK86QM4u+yehDtkHeu8SX+2uwHM3zuODPk8pzYNvPT9SjwRZ8i8KxYtvW1lYLssW9C7GV1IO1toyDvCslI8N3o7vJgTcTs8adu7lZ9JvO5XGb0Qq6C61sAmvaKz7LyVKdk78ynutw26oTzHZz47LsaxvBY0p7xiPSW8rqhEPJYr5zwCBw29Kkn6O4vJALyCdj+8Z5gjPIcGdT0R7fU7WK4ovO8RbTzggNA4k1DJOKq1/zzZoC28eAgbPKZJmbwEWTA8SGMKvLUNzbwi+U68nQueO5E0Z72i+VG8vbGMPDpnrTy1LVu8IKdVOnS+Gj3O4R8884Phu+7K0DwmJxq7JN4SOtMJ7jvlLpS8PZVFvGNlFj1g7aM7/D+qvPO3kjy2pSy99TwqvAziprxnygq9tuZ6vIIaJrwvcD28K5tcPPGeEzxfK4A8chdwPI9Ni7yvr6g8oCmJvEo9YDwPKKu8qYEMvNDbizxtegg98/KJvKRoMjxYbIa77SCbPCcZ0Lx067A812uXO1nLajyZy5c7ev7fvITVurveeMK88IobvZG1nLtO48E65PbSvGUxgTwfYd880SzoPEMaBbzoodW77HYaPAFZLbwDaLk7s2CGuVXY1jwP7no8FqYuvKZwk7x6zDS8RumAvC31yzurHBa8xKSsO9CIkjuK79s8J9AtPOGfCDxYmhy8ztuQu3pQkLqOsw09mTzSPOXeOTzQ5x07WVU8PFTO2bwD1b67QusGPCBZqrzkFe07UGJfO39QDDx1V948cBYPOcp6ubv5pO267lDXuxrJvTySl148mRDNvJKQMDsVQAW7DMLxvMbwD71BRio91QLsuU8KobwKnEq9C3fuPPYwkL3uAzo8IDHxPFiAL7yFyI68hY1yvK1G67yLY4O77LGsOjosUzyilCy9nLVgvA3sADyhzYY86DQTPHiKo7qB0+m6S1cBvUCFHTzgWzk8U1hwOqxiG7zehnG6Gaadu0Rjkjz+tAg9sMhOPN2e2zyM3868F0idPJNhsrtTrvk8Box8u9bTyrysqZM6G48svASC4jqf04O7L0RJPGuqirzkHCS8CRQxObv0Iz0a6D66NNISvQrS0Dvmlvc8woctvOi7hbuuwF89Kc7APPOawTx/2D68gA9LvfJBxrusY8E8NDrqPC06pbwv7kk7FpRPvKVxdzsDZBO8oi3/O/st5LzKGjK9NPwKPFhVpDz1XPY63egWvU9c1zwuI8O8kLOXuxqrxDxv88g7FmpIvbnq17tSsY27SnU5Pdm+prxU8xa8UuTzu8ZvXDygxMQ7vuWHvMJehTyhx4K9fzthvKBw4LplIwu9vagXPaNbmTsc3Xe83NTkPGrDq7zJulK8wBQQPK4KMz2s010793duO/DxxzvQy3A8ifjDPIHRCDxTkJ+3nIgOPauVFrzu15G866ubPPajUzwddKu8UVeFOzEyCz2jtE48pen9PJ2IsrwAL7m8ywsQvdsYDTwhCSq9STamu0h957xlOAM9eDArvN4gLjxfSZk85sKjvDa/lLz8iJo8dXk7PLOeNrxx+uy8mM1IOxnRLTzE61u8/6GAPFIcUr2O/gc7P4d6utsAl7woc7C8r7Thu+tU17ySX4o7k15LuxyYWjxOXbS75uLcPDn3g7xCDCG93r04PMraobxcAlq8ZPLOvDBB1Txb15c8ZtM1umb+KTytwbW81dswvQY/ILwyoUy8BOg8PJrgNbz50oS85AYFPBkH1byEmwu9E++avFHvcjygaSk9ey9pvGUsDD3aPN88y6zeu8/PxjuMiRm9zW48vUlxDrxTdem8Sm2/vPKVMjxeW2y892a9PN15w7wi4L08i9MhvACRQ73PVx+86mTsujlMUDx4DJ+6QPNuPJ0wGL3udLi81gP1PGZ2qLzjs4K8kovNvMBozjx67K06YMsVvbXtZTysJFE7qRKFPInw5LvT4DK8WLGAPPOuQzs2mVg9R3bdOuGCZ7wqRWk8uKILvAtSlTzQGlM8bToGvG/QILzUrj08gPEfPbVfwLsOoYu6JJYWPUDaKDzO7928fPyePLgMzTyYlsi8/ZL6PLEEvbudYbE84LCCPOy3xLtFzI48/1RMO8+d3jzKooY61rFHPDgjNTuDqry8eszCvHRZtrxgXhQ9muZhPBPPnrx84xC8vHjfO/K22LjvyhW8a6xvPPqumjz3au68CmIKvVf68ryAtFa9wTPnu3LKPb0M19K8ZCAbvA4gHbtkeCi8XDWru4gMG72M4ze8goFdvfyRPzswG5w8MaxnPC4aGbxZE5k7P32RPQW9E7tD9Xs8Ag8LvH/1UDy1EI+8Uybxu1XrQDx56AY8o9w/vIQZKLqpFA89DkZmvIQ12TsuGfI7jdf2vK934zwkBJ+8dZNcvCr0wTzSZR+9wZC1PCij6jxzOpQ8hn8PN+uyMbzcsr08+b+hPLr7eDyng367UxYEvLeUB707msK7covnPFuXYbxypri8gIHEPA6d5DsupSm8od20u3AenjwRHBK98j4CPQYx5DpRg6q7GmuePJsz2Tvvpla8TeJJvWn50Tu/vy68t/xTvEB/gbz5GZY7DhI/vFTZDLxZ88Q7PmphumbyGr2xljG6rW+MvGglBbx+7No7UpWovErnYbxlEhE9TASoPFVBzTvajac77LMUPKcpUDytyY47ae9XvInUArwZm0898XttOXVxmrxaF5m7F6bvvIRciDxdD+w76I1lPAVmDb1Ta1K8xTa0PJcg57wmX687FZoQvAR44Ttk1U68lIt2PCoVcLtpBRI9Zr+TPKKhgzrvQhu8B+XsO56XwjyOid26Z6Guu+h2Aj2/N4+86v2VPI/6xbzF8pW6dXueunVltbu5EIE8ngAQvQuEEL2shBE9AQAGPUDcRDu4eBw8TxjEvE8pnruwoH47DP3cu16e1bv9QKC8amr5Oyxv6zwZzns9v1oLvQPK0zwkLz0929S7ujaThDugDP46/WfuO+XzgDuwEtA8gn0OvY5TBbyH+MM8cpCmO14WmzvUhME8x2jau5mQ67vldgW90quMvMgKpjtt/sI79iUrPfksGzx0l808iXM/vGv3Ob3JyIK8ncKsO2LBzTsoY6S8IpROPaxs4zxAU828/7gRPQjtdjzXHEe7x5aOvDX3ljyUWcQ5kWGfPJiUdTyGTH488ekPurKLGDp6y/C5zAY4OpOYiDx9C528mhcXvCXtPDz0RBg9U0vQPAiZRz2kGVG8W/ssPXjQpbxBpIm8uguuvC+Yj7t5P948wgHQPGrdhLySIOe8LvtqPKWjNrzx9kg7d8j4u6SDXLypv4o8jdnuurrCebt+h5K8dWidOw/xV7mJo4e8pBNpvNzJjrz4hSM8cIIgvQlAYjzh0OK8fCeOu+GO37y985M63/sOPElb6zvAF4U7tI65vJL+Er2lqEE893apO95YcT0D+oK8bWqku/TrRruyDGQ8SjCEvITCHD2pBAA7HBbBPJc5wbys6207tIEUPGhfFb1G2o+7ttqju6jNgjzwYtG7Ub3mu65vzzhBRKQ8DySAPGLTljyXltq7UUYdPd5IALwlegi9PFaxuxw2ibyk4Z66uyTFvLixQ7wBxfG8V7uTPGtBF7y58Y08YBA9PULAszuDs4O80o0DPN8qprzvjaS8ONQNPDvF2LzHOZQ8OvLPvEzGmbsaVM683FKIPKjusbyWG+K8+2BePCuYE70iyqQ8rYANvExcNjwizRY8tLYFvM9OELwycO275adBPVlTIL3JcBA7BybHvDoj5DzdRt46IK2qPH4Mq7t5vMA61amjPDbNG7zneXu87EaLvGURlDz0Wpq7OhnyO00OKTx/9u88lejUvItpYzuwKUM8vgqVO+Q20jwuX9a8DI8IPB+PaDwfBHI7yWMgPHVUHTuNzam8XstMvJnOxTsx6EU8qBnZvFS+x7r2pK86KYXUO/SMtzyrxn68elp2vFYiNzuT6C28M43zvNovBb1EgyY96qsSO2wyrLwA7qE8yK6tO/4NCj0BW9s7AqOfOzVxLbwbNZM83VyTu9feKDzawFS82MQqPDF1aTytMp+6Om+wPEiInzuOFOC8DdRAvGx/5jwy1Nk7r6dLvEp+j7ulgAi9R/e7vIGpnrydlg28rSlhO1HTHLy4Smy7GZXHu8Uv+rvQS8u7oQvHvHq3pTk0Kl68pmIIvGAIRLti71K8dUQyPSVbEzw5Mhe9OfpTOxVyGLyMV2+8xGUFvXQ6nzvLHdc81HRNvFFOWTydPQw9YEQqvB6oi7vh9R68+t9AvN1IIbzXkmC7ePaMvEnacDzPGwe91bsoPWXjojokHJQ7kCl7vJfMPDyJ2Yq88i1IulGnAjwGf508mIirPNfu0zzD8UW8cKywvFxDp7oAR3g8j+J2vJ2fTzyKxg09XmolvHNUIj0SPJC6Bvihuwpgq7zWOa+8xSb8PLR4WLs7Apm5VAs/PTPoZj2Mf6K7sDQEvHcvyjzWFSe7rLSQO+KGKDuHVbW76rKiPNRbHTu2myk9vTlru+subDz2y907HI+bPJgtUb0Uir47GE4kvIvfo7wXsl08vWqdPDQqdLvqS908MJ7GupZCjTycdXW64hPJPD1wMjwbZhI9tVgjvQbXtjxnz0m8NZEBvPtsHrzVTGI7vZE8vaDuOr0ct588JNNaurQutLxqNZC8AicePZnEuzwFnwa8elXzPBmUqDvwHHy8AbDiuzJMNTuB0xu83nsGPJhzwbs4O0m8KINwvO8YVL09uiU9DwX5OonzYjxxUCs8BLh6PI2YvLz7snE8sGNVO5QHxLw9yba87l5vvGppML2zS5K7J+YMPDBusDuj7647JxHbvBeh6zu90Ya8lDguPQfhw7pM0dI83PC7Oqn4KD2W7O+8RH32u5sb+jpHYy28sbcOvF+BGLpuHiM8LVZRPE0eJLyWXoe8AFgkOSPGY7urGta8K9LwPANWUrzRloG8glBFvIAzMjwqjQ89x4aNPAMu47xfF4M8lxqHvNl17rxsLa28SQ9wPNiMtzs36zI6pGTWOqVLJz30SQU90rctPADiLLdFHyM9VIbGPB5vg7yf8BA8N+h5vCa6FDzRQR88QWi8O7eohztSXRw7OBiwu7vwPbvaLwc9G961vFljK7zxHzq8jsR3vLcV/DvhgdY7ugAGPGJPJLuEPNq7aZETvGortDzQhx880OK4PIf5+jyVXQA8/IFMO22xwLxavba8SicFvAMLEryb9+Y7XzLGvFJDcTvhkNy7o0LePGNgFL23Gry8/kVUO+BGEby8FpU7oqbEPDEspjx4sty8O+YEvAgfUzqdGbK8B6eXPD0wDzs34AQ9SMW7u6dqkTzVdIG82RSVPAH2CryvChK8pamhvG7tcjsY2mc8NIJlvFoYLDzUPDM6fg2MPNV+n7ycfTu7ReD4OyArXLssUmC8BTIfvXwYP72FU/K8K9daOjtm4jxgbq087SXnOxEyIzwvTNM6Y5EpvaPGyLzC/Xs7fjJ+O9Kd+Lw7x4C7MBLcu/xDtLyavQO8lfEgPIFpAz2K96S74ZzdPOQ33LxtOa+8CC5cPDDKo7wqZfg8belwPBoJO7yEG1y7S+3EOtXesjxpYZI7UFhfvKl12TtRtuc74j3Kuy48KbzWDAs8q/G7OzPlNjwbZwo8grFCvLhwYDx7dpO8BO1VPNc89rtf9KG8pP8vPIhrgjutGaK8t8aHvHin8TxovEu8DuUpPaxmPrwWNA868jYBPfyZyTw6VCA7/RUYOljvdrqeaRI9fQxpPNDBE711i8o8/pS+POX6BT1Sjzw6oAT9vF+thTzLblu8DmMnPQfOnzqnRZ286VEtPLEfibwh4NU85xg6PMyM+jwhusw8rQEZPM8CXzxwaZ48U5YtvA/AdryntNQ71SXMu43nFjuvbJw8nk2hvH/QprxAmTm8DuOzvJbQZjzv/d27QKgjvLftirq3wlo8OA3RO4isZDzPjoQ8+e/QvKQXyDtn8i06AbbnPPB7GrvxtC+6nXiHuG0sMz16ULM7T+aKvIQgNbw36qy7CVaTvDnsY7xKo/C7SGATPM0hHLs5jto8ADgXPf2hCD0rXTg8yasMPOJx0bwKCKE8L5G4O+38Jjx/TLQ7Dwvwu6T9Ubx4wS85a7+tuV06wLzEgPK8GPzdOwUQOTw2DI08Ls/+uqcagTwwpwy8FLeAPA8HOTxpfYu7afYePc/3Gr05nzO8D1IcPXmFt7wotvm8GtKMvEbENLwMEiy9geStugLAhDyEJoo8G7y/u72u37x9Q7E8pxuRPLtJqbvjOBK8YdJ9vLKT0ryYTg49+vJ7vHBYojtf32e9XSDEungT67z9Cju9NwL8Oo0WVbzgdc88gcZeulfTdzz47EQ8iORdOmaqzbvB6w680lqVvLwRojwiZs28vVobPD6Hnjz9VYE8glVgu9vomzyHdUi8nMn0O4f55ztdfqM8e6v3O5lDQDwtjJK8ysAqvMIoYzxhJQK8A5O1O10zfrzr2gE8VAa+vCckHbiueLm5RmIZvfDoaLxZ/pm84PqePNd6yLwPiAS8Y9JCPCrJZTx/jok8Ktb8Ow+5ybwdjHE7sCZ+uwkcBLoYgYg88WYHvdK5Ab10NEU8lbvaunruIrxj+Ne7334iPPStcLyug4Q8iOa4vBnn5TwjV207g3ljug4fCbvp3IC77FoHvLXoC7xZM5G7AG9IvGtLcT3WCcQ8vn+oPBp9nLpkEyk8SNnQOw/+yzvqLRi9/4bIunfGlryCs+E66yAIPcX0gzwn9J68tbBjPIcBoryXEYG8hUgDPadpoTyy8cy7rDDDPFVFsTy6R628YvHEu36UqDs/kzk8tQWfOpE4EjvvLDK8s2aCu/9+G7t7DxW8GBkqPIQ9fTzdrwK9DI26uwT06jrvt9M82yCqvL4VIbxNW7K8GhjHPFiGKTvHjBQ9KyMjPCtakzyL95i8SK57vFPdMj2UjXS8u8B9PNZzDrz8ucW8W4mWu8D7/rvT2rO7bU0NPDihHbnxf5q8SMRCu3ZoGbtQDQ69WUa7PFvDALxql5G8D8AZPeO7Ej3OTDa9UToavbywajz2PSQ95dfivHPyGzwA9DQ8HLhIusx0LD3pbDm8o59oO3RqfbsnIg691REIvIX14TyM3mo9XOvPuQGdlTyObx48ndzDO/0xhTxW0pW8lNtfOn/jYbxNvAw7mhpKvJgbKbxeLbA8GaSIPNo/rbzL3as7v1ckvAlcTTzL4FE7cMrBvNuIn7qshNO8HQTgPCqrJ7x9JD69jsriO6D5vbulKRi9lWneOzKtt7yXbHy785cUvRIbgDxGnZC7c5gIvRl1Zz1ZXiY9hiKXu749lLx/ZP68toCHPNrCt7uu3IC7Nms/PHWs4bzwDus7Z3hOPBpgL7wVsza9TUcBvP+mBj068348rpITPTryHr2hqmo8KVlpPF0onzsFknI7v6EUPNndoTvGayG7p+BnvAdOijt4Ncg7JAQ5u6+yiLyB2EC8GWQiO9FsnLv/Qc284xZAugl2c7wAvhw8rvIsu7BoyDtMPIo8ImmNOw9TUzwonEm7b+anOoFSGbyTWNw8iyWcvHvPDbyf3Iy8CKG+vBras7s9JNo80a6QPKfU97yM0vs8ROb4PGcxwzyYEQO8XmKcPCnyqDz5wyK9+zV0OygdKb3+axu80GFYPMG4Izz0hDQ82bQkug6dUDzUKu+8ls3wu1DS6zrTsJG81GAevBFPNLy86Cs92fIkvMqg1Dyxefu8QYjHO2cnmTyq6628yjiMPK3dEzyKUL88Ncp9vJtIKjxuKdA7iOgCvexRtrxLkhu9U56OvKAdobzHthE8dJSQu221CrwwEuE7yzIHO0dKkDtp0qA874pCPRV0FryR0gM8cTrGuwjE/zw5eHe7VQ3VvMUOojpU1ka8dFfOvIfLBjzoQlg8Sauvu+yH8LvATBq8VRYPPflSEbvBz1Q7sS0NPYPvK7xCQ5Q85CrBPF2RMLzj5Q28Y4LzO/UmI7wSYf48vZq2O6w3CL0UIig77ttKu3LLN7ypb4C8P6rrvEPLjjx8+iQ8nlhxPHSdij38NI48FT39O1PVnLw1iUo7QI2PPCrVFr3yAqI760JyvESZbLyFEZE4+VYJO7ar1Lwu5ps8CbaCvPDrA72mXCg7XygbvOMBN7wl4mc8MqOnvMqd0DwWGx29kgLFvPnuAjzCiQO8SQmYPH20gLw/HKK7L2nru4qip7wgXPM7X6lfO9DeojstAcO7DO0gve1CnLzfw8+8MVSKvL6QgTzrSdo7ZbS2vOFB67wF1kU8DNPVuyrM/zyaQla8p9cnPWKQLL2zWpo7pg6Uu+W6ar06jao73KOQPE0dqDrqbFs8tv+LO0rYHLtd9ku8WhuEvMOmLTwFbJM8ZB8SPJRIxrwiIvA7RxzLPP3AwTzW2ic8flGxuzu5l7wSXLk87k87PSuxBzyNxDo8hZu7PKcKC7xpWUw8YoyvO1pwUTuKiq47DLatvF+isjxLKtm5m686PKgk3Trw6sm889nQu7pDTT2RQJg5ajyDO0wpZbwzmAG85fs9vCA+TLs8g8Q7LY2mOv63iLxPi6i8RcRsu3YnnzwffO48XOKNvHm/D7zKWXc7apYPPH4E+jxpn1o8sR+zPESu9TsJwQy7SWwAvNXLCj3QKLU8oXkBPLHjojyCm5M8neeLPBmu+rwz7m888VKUPFdM8LphskK8uPcKPYKxDTxRu+U6LEB2OhliuDvKXY88EToYPdVQUzwvTSe8SkZDPKA2q7uqzU+8j0jVPMXKlrw82tY7dvjMu+J52Ttvg1S6WCs6vEv+C7yxFXa84qFYOukooTyV4d+8HjekPEu5JzwAtrq7/P/JOvK6UbthBdc87DLbvOssO7wzIPm6r7s8PMISQjxuPge9D0yAPC0Xrruyjq889g6vuz557rw2i0O7X0XbPEOjBbtHQbu8dnfLvBa2Lb1Fzr28xnfPO5udPr16dJe8m8sEO/WIPjoLIiq9KYgCPM4K2byh3wC7cDzZPD7cejncvhI6DsDCvOtOBjz+DnM6nFxXvLvGWzxJPYE87okdvBKZQTzV5Im8XGJUPA8TCD2yu8O7R7j+PFuxGrynlK68BKnvOmDCjLseVgO8+xCBO4dmGb3u4BA9EHbruyzHtLy8p2+3F+GOPAqGI7tvbPS7Tq3AvAtwmbwpPPe8wl/6utMVSTyjTkQ7vMQcO4z1/DsvD+q8gKG8PKK3FzyuP7K8zItFPMVPHzsrPlc8BXMAPXmSezo0DkS91/OxuEm2J7xFQII8WXk/POJIXbxQqmc8XVwsPYMei7zD8jS8w1SyvFZYjrzq5Mu8EiaXPMP4TTyciZs8amjhvG7zk7ycBsS8m8MCvVxoZzygQhE9ZfHkvDf6HTwhZRe9lSonPQTdGTxYwBO9jw6EvFXe8bsOrqU7VyF2PKpQ9ztKFP87UjifvBbn5DvYOX+8S6wKvCPiqDxjHUC8Bq6zvH7y4DuBSIm8AgpsOz4YFrv7DNS8mmb8vPcfZDxYgJy8pvVXvDbfmrz6NJE8QlKaO5kmAL0ECgM82v5VO5j05jsMqaC85wKDPL1LRz3hB8S7LC6FPIlnjDzeSg28z7tePBnH0DuGiWK86dG1PFR3GzzjXrU4g7GSPDjEhzykrcW8KLeRvHBL7byuD9y8CDLFPKjNvLzuvh088ZubvJ+yQrxwol69edWkvG3hFDn3sSU8i85iOvDHQryQu6E8rb2uPJhxBrxtytE7Jvl4PI1ZnLzCJ8u6/FkAvYHp+7xqg0S8RDWNOqU+pjzXrki6MqMIPFvdUzsP3Ni8vFoUPFk1h7oYMS686erQPFApAj1hiZG7SqKuu/hgaDuOSXG7snbKPCAFXTysPuW6jd8Hu0tuB7vwV5k8zW4FPOSbK70egu66Uv99OyShzzujf4I7CTY1PYhmpry6T9g6YAxZvP5FIDyFTAq8sRumPBgMFb1gtQ+8YURuvJzvMrwpOMO8USkUPeDXZbuE65o7WonJvGbnabqCnL26/kbmvM30XTx2CSK7dG2zPJGdq7wPb1A6YBAXPDiB0bxSU4M8LT2KvMDx+jwRWPE8YxjPOz9dPLyTrtE8My8nPC2b0ziqpo08Ukw6PIoukrv77S29p1MXPIKOsrwenQi870SRvHnHBj2njMQ62TmIvI9aALrdXzq8ZCgfPRRFBbwryXa827SNu3vNtrwZZ0A8VsOxO45kCzza2c88xVWPvMm9DTxQGEq8YlKyPO3M77xndzo8wTu3PBrkJzyo/Fe7XMOpO++sMT3FEAe99jjGuy+1Abte3k07zU8FPf0ftbybWew7pCCEvC9NTTxAmb47o7F9PIpZKD2HJYy8/u/FO92Zirw9a7+7A9HHPBiHPzu4Cp28iY4lvITByzkaoLC71n+7vLFk4bwRkWg8f3kWPDEFpTvVPIK7ufZGPMi/i7z/n8w8qGHbvCyc37kun+c8P3YWO8HiLjyYKNk7uFIiOsQSX7rJ9cS8FdazvCZnB72dVf27gtmLPCoh0ryevEE84ErrOzASODxTcR08bImSvHAhyDwGIXu882GWPBozsLt+dsk8EqylvKYrBbxN+Oa8AQyGvGQPkLz09om7WuBZPde3Yzy3JYM8vRqIu7sGCzzM+DK8jzGzPIbAgLz/WZ08YWDXvJVoczzH06e8v2ePvC4LPrycBIg81OwPu7ERzjuKn4U77HuWvO9VnbxJZ/25V/jSPK3v9zsy+7U8I1+EOyujNr1t/ow7J7VkvXBAWblCHiI8rCHSvOCcBbwoszM8WeI8PGPcHjw4xtQ8VJOxu98dtLvhBKG5+/3wO0aSPrz0e528/1KkvJAv27xlPfo6eXVpO43cjrt+A4O8tlMNvYHR3btDqio9F6DjO8u3WTyNtfk7+2JmvNZcCDxq6gq9+dHiO1ZFcrwJUhK9inYbvctn8zm4Kke8qHD6OmqLRrxGgpO8UhqcvLj51zzAtWO88vdIvCyBa7w+pPy86l4XuyiA77rLXGM9DIzwOtGFqbxH0lM8kUADvDZRLL02Lai7Jk7HuwfuKjzwfnq8wbCQPEeGxLybirA7qtnXPCpZG7w4tOA71VwkPNgBhrq7cCc8POoiueDLfTw15+U6G3kzvUzvEDtrBow8/qWpvIC4Fj2IAva7wdufO3tWOryCK4480NDBPF8667xga9E834+pNyFApbxV0Si9/ZamuxRA/Lsw3tS7HvyFO5yoIrrxoJ28qfY2vCBJVDzTQr670UwEvDW+BjwjvKu83yOkO38GXbzSJ+g7df/rvE1fEjykry083suevDD41TxHJHm8zDcpPBtYszzIWJM8XrPsOk3b1ry9dbE6KISfO3Gkjzwwg4K8mQukPEzJlbvj/dA7+pFKO06LEz2LVCy8uyhIPMg1+rtwe1+8pv6kPNs6Kjwa/r465ET5PKOJTjm8l0q8g9QMPfcIXTtuB8Q8/3YtvOHABD1wCk48uc2uPMgOyDwOCIw87kLCPFaBQLyDTYK5WqWpOlbg0Dx6R0E8hKDVvDsyEzyZXF+7Uyc+PA0ohLukjaW8t3gfvOFyEbl0DYs8pG7jOwx3CLzQGDI80b0ju2LO7LkkSQa9fyL1vMlPQbvPSL078k5Fux504Tk+lJa8V92MPKNxQ7t2kbU7+R3OvINUjztg/4Y7DrIYvDBWXrvAX3288p7EPJ/FiLyH3vU8A732u70qJzso0hS8S6xSu/n+zbt/LrW82rYcPJkUPrzbR4E7CayYO66UijzQ2bw7DPjfvF7dC7pdcCW8zxiLu4Rdq7s6Npg88JyDO8EDpjy4UCW8V5nzu+s/sjyT3927mlvQvC1qvjrDui07Yd6SPKoFBzsPzss7D0CYPPo7jzx2EqO8tIkmOe9737wdz8G88yyVOwiTCT1GWJY5xsrUPMKTkrwD7Xs8ldV2PIvXKzz1DJ88/2HJOrHZgTztawO9k7KqPAOx7bw9lTW8o/fAPGyPGr0O3LC82HUSvdc2V7wKEls8uX6YPNWkGTwdms87b7W+O2n0+zzhsAE82AhlvFIWhDvAg2Y8JGFLuw==
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: 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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:
|
|
- '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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to print results.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to print results.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to print results.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
Need to return JSON, not markdown. Let's output JSON array with fields.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to print results.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
Need to return JSON, not markdown. Let's output JSON array with fields.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to print results.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
Need to return JSON, not markdown. Let's output JSON array with fields.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to wrap within {"answer": {...}}.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to print results.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
Need to return JSON, not markdown. Let's output JSON array with fields.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to wrap within {"answer": {...}}.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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: |-
|
|
<think>
|
|
Check documents variable.
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''dir'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_1uonnu1t
|
|
- content: |-
|
|
<think>
|
|
dir not defined; we can use globals(). Let's check if 'documents' in globals().
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''globals'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_40ur54cl
|
|
- content: |-
|
|
<think>
|
|
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())".
|
|
</think>
|
|
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
|
|
\"<string>\", line 1, in <module>\nNameError: name ''__dict__'' is not defined\n","success":false}'
|
|
role: tool
|
|
tool_call_id: call_xwupy2ag
|
|
- content: |-
|
|
<think>
|
|
The sandbox likely restricts introspection. Maybe the preloaded documents are not available. We can search.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to print results.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
Need to return JSON, not markdown. Let's output JSON array with fields.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
We need to wrap within {"answer": {...}}.
|
|
</think>
|
|
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: |-
|
|
<think>
|
|
Need answer field be string. So output should be {"answer":"..."} where string contains info. Let's create string summary.
|
|
</think>
|
|
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: |-
|
|
<summary>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.</summary>
|
|
<returns>
|
|
<description>Structured result with success status, stdout, and stderr.</description>
|
|
</returns>
|
|
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
|