From 1b4932dbd7533a87242cc6012dfb6db857378d4a Mon Sep 17 00:00:00 2001 From: ignacioct Date: Wed, 21 Feb 2024 11:44:26 +0100 Subject: [PATCH 01/24] README example added as ipynb --- docs/examples/usage_example.ipynb | 194 ++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 docs/examples/usage_example.ipynb diff --git a/docs/examples/usage_example.ipynb b/docs/examples/usage_example.ipynb new file mode 100644 index 0000000..8c5be0e --- /dev/null +++ b/docs/examples/usage_example.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# โœจ๐Ÿฆ™ Getting started with Argilla's LlamaIndex Integration\n", + "\n", + "This integration allows the user to include the feedback loop that Argilla offers into the LlamaIndex ecosystem. It's based on a callback handler to be run within the LlamaIndex workflow. \n", + "\n", + "Don't hesitate to check out both [LlamaIndex](https://github.com/run-llama/llama_index) and [Argilla](https://github.com/argilla-io/argilla)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Getting started\n", + "\n", + "You first need to install argilla and argilla-llama-index as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%pip install argilla-llama-index" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You will need to an Argilla Server running to monitor the LLM. You can either install the server locally or have it on HuggingFace Spaces. For a complete guide on how to install and initialize the server, you can refer to the [Quickstart Guide](https://docs.argilla.io/en/latest/getting_started/quickstart_installation.html)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Usage\n", + "\n", + "It requires just a simple step to log your data into Argilla within your LlamaIndex workflow. We just need to call the handler before starting production with your LLM.\n", + "\n", + "We will use GPT3.5 from OpenAI as our LLM. For this, you will need a valid API key from OpenAI. You can have more info and get one via [this link](https://openai.com/blog/openai-api).\n", + "\n", + "After you get your API key, the easiest way to import it is through an environment variable, or via *getpass()*." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "openai_api_key = os.getenv(\"OPENAI_API_KEY\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's now write all the necessary imports" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from llama_index.core import VectorStoreIndex, ServiceContext, SimpleDirectoryReader, set_global_handler\n", + "from llama_index.llms.openai import OpenAI" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What we need to do is to set Argilla as the global handler as below. Within the handler, we need to provide the dataset name that we will use. If the dataset does not exist, it will be created with the given name. You can also set the API KEY, API URL, and the Workspace name. You can learn more about the variables that controls Argilla initialization [here](https://docs.argilla.io/en/latest/getting_started/installation/configurations/workspace_management.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import argilla as rg\n", + "\n", + "rg.init(\n", + " api_url=\"http://localhost:6900\",\n", + " api_key=\"owner.apikey\",\n", + " workspace=\"admin\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "set_global_handler(\"argilla\", dataset_name=\"query_model\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's now create the llm instance, using GPT-3.5 from OpenAI." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "llm = OpenAI(model=\"gpt-3.5-turbo\", temperature=0.8, openai_api_key=openai_api_key)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the code snippet below, you can create a basic workflow with LlamaIndex. You will also need a txt file as the data source within a folder named \"data\". For a sample data file and more info regarding the use of Llama Index, you can refer to the [Llama Index documentation](https://docs.llamaindex.ai/en/stable/getting_started/starter_example.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "service_context = ServiceContext.from_defaults(llm=llm)\n", + "docs = SimpleDirectoryReader(\"data\").load_data()\n", + "index = VectorStoreIndex.from_documents(docs, service_context=service_context)\n", + "query_engine = index.as_query_engine()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's run the `query_engine` to have a response from the model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "response = query_engine.query(\"What did the author do growing up?\")\n", + "response" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The prompt given and the response obtained will be logged in to Argilla server. You can check the data on Argilla's UI:\n", + "\n", + "![Argilla Dataset](../assets/argilla-ui-dataset.png)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From da043cc3928aea00851145f8867e6c08f6adbe3e Mon Sep 17 00:00:00 2001 From: ignacioct Date: Wed, 21 Feb 2024 11:47:04 +0100 Subject: [PATCH 02/24] paul graham essay added as data into the docs section --- docs/data/paul_graham_essay.txt | 353 ++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 docs/data/paul_graham_essay.txt diff --git a/docs/data/paul_graham_essay.txt b/docs/data/paul_graham_essay.txt new file mode 100644 index 0000000..7f0350d --- /dev/null +++ b/docs/data/paul_graham_essay.txt @@ -0,0 +1,353 @@ + + +What I Worked On + +February 2021 + +Before college the two main things I worked on, outside of school, were writing and programming. I didn't write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep. + +The first programs I tried writing were on the IBM 1401 that our school district used for what was then called "data processing." This was in 9th grade, so I was 13 or 14. The school district's 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain's lair down there, with all these alien-looking machines โ€” CPU, disk drives, printer, card reader โ€” sitting up on a raised floor under bright fluorescent lights. + +The language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer. + +I was puzzled by the 1401. I couldn't figure out what to do with it. And in retrospect there's not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn't have any data stored on punched cards. The only other option was to do things that didn't rely on any input, like calculate approximations of pi, but I didn't know enough math to do anything interesting of that type. So I'm not surprised I can't remember any programs I wrote, because they can't have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn't. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager's expression made clear. + +With microcomputers, everything changed. Now you could have a computer sitting right in front of you, on a desk, that could respond to your keystrokes as it was running instead of just churning through a stack of punch cards and then stopping. [1] + +The first of my friends to get a microcomputer built it himself. It was sold as a kit by Heathkit. I remember vividly how impressed and envious I felt watching him sitting in front of it, typing programs right into the computer. + +Computers were expensive in those days and it took me years of nagging before I convinced my father to buy one, a TRS-80, in about 1980. The gold standard then was the Apple II, but a TRS-80 was good enough. This was when I really started programming. I wrote simple games, a program to predict how high my model rockets would fly, and a word processor that my father used to write at least one book. There was only room in memory for about 2 pages of text, so he'd write 2 pages at a time and then print them out, but it was a lot better than a typewriter. + +Though I liked programming, I didn't plan to study it in college. In college I was going to study philosophy, which sounded much more powerful. It seemed, to my naive high school self, to be the study of the ultimate truths, compared to which the things studied in other fields would be mere domain knowledge. What I discovered when I got to college was that the other fields took up so much of the space of ideas that there wasn't much left for these supposed ultimate truths. All that seemed left for philosophy were edge cases that people in other fields felt could safely be ignored. + +I couldn't have put this into words when I was 18. All I knew at the time was that I kept taking philosophy courses and they kept being boring. So I decided to switch to AI. + +AI was in the air in the mid 1980s, but there were two things especially that made me want to work on it: a novel by Heinlein called The Moon is a Harsh Mistress, which featured an intelligent computer called Mike, and a PBS documentary that showed Terry Winograd using SHRDLU. I haven't tried rereading The Moon is a Harsh Mistress, so I don't know how well it has aged, but when I read it I was drawn entirely into its world. It seemed only a matter of time before we'd have Mike, and when I saw Winograd using SHRDLU, it seemed like that time would be a few years at most. All you had to do was teach SHRDLU more words. + +There weren't any classes in AI at Cornell then, not even graduate classes, so I started trying to teach myself. Which meant learning Lisp, since in those days Lisp was regarded as the language of AI. The commonly used programming languages then were pretty primitive, and programmers' ideas correspondingly so. The default language at Cornell was a Pascal-like language called PL/I, and the situation was similar elsewhere. Learning Lisp expanded my concept of a program so fast that it was years before I started to have a sense of where the new limits were. This was more like it; this was what I had expected college to do. It wasn't happening in a class, like it was supposed to, but that was ok. For the next couple years I was on a roll. I knew what I was going to do. + +For my undergraduate thesis, I reverse-engineered SHRDLU. My God did I love working on that program. It was a pleasing bit of code, but what made it even more exciting was my belief โ€” hard to imagine now, but not unique in 1985 โ€” that it was already climbing the lower slopes of intelligence. + +I had gotten into a program at Cornell that didn't make you choose a major. You could take whatever classes you liked, and choose whatever you liked to put on your degree. I of course chose "Artificial Intelligence." When I got the actual physical diploma, I was dismayed to find that the quotes had been included, which made them read as scare-quotes. At the time this bothered me, but now it seems amusingly accurate, for reasons I was about to discover. + +I applied to 3 grad schools: MIT and Yale, which were renowned for AI at the time, and Harvard, which I'd visited because Rich Draves went there, and was also home to Bill Woods, who'd invented the type of parser I used in my SHRDLU clone. Only Harvard accepted me, so that was where I went. + +I don't remember the moment it happened, or if there even was a specific moment, but during the first year of grad school I realized that AI, as practiced at the time, was a hoax. By which I mean the sort of AI in which a program that's told "the dog is sitting on the chair" translates this into some formal representation and adds it to the list of things it knows. + +What these programs really showed was that there's a subset of natural language that's a formal language. But a very proper subset. It was clear that there was an unbridgeable gap between what they could do and actually understanding natural language. It was not, in fact, simply a matter of teaching SHRDLU more words. That whole way of doing AI, with explicit data structures representing concepts, was not going to work. Its brokenness did, as so often happens, generate a lot of opportunities to write papers about various band-aids that could be applied to it, but it was never going to get us Mike. + +So I looked around to see what I could salvage from the wreckage of my plans, and there was Lisp. I knew from experience that Lisp was interesting for its own sake and not just for its association with AI, even though that was the main reason people cared about it at the time. So I decided to focus on Lisp. In fact, I decided to write a book about Lisp hacking. It's scary to think how little I knew about Lisp hacking when I started writing that book. But there's nothing like writing a book about something to help you learn it. The book, On Lisp, wasn't published till 1993, but I wrote much of it in grad school. + +Computer Science is an uneasy alliance between two halves, theory and systems. The theory people prove things, and the systems people build things. I wanted to build things. I had plenty of respect for theory โ€” indeed, a sneaking suspicion that it was the more admirable of the two halves โ€” but building things seemed so much more exciting. + +The problem with systems work, though, was that it didn't last. Any program you wrote today, no matter how good, would be obsolete in a couple decades at best. People might mention your software in footnotes, but no one would actually use it. And indeed, it would seem very feeble work. Only people with a sense of the history of the field would even realize that, in its time, it had been good. + +There were some surplus Xerox Dandelions floating around the computer lab at one point. Anyone who wanted one to play around with could have one. I was briefly tempted, but they were so slow by present standards; what was the point? No one else wanted one either, so off they went. That was what happened to systems work. + +I wanted not just to build things, but to build things that would last. + +In this dissatisfied state I went in 1988 to visit Rich Draves at CMU, where he was in grad school. One day I went to visit the Carnegie Institute, where I'd spent a lot of time as a kid. While looking at a painting there I realized something that might seem obvious, but was a big surprise to me. There, right on the wall, was something you could make that would last. Paintings didn't become obsolete. Some of the best ones were hundreds of years old. + +And moreover this was something you could make a living doing. Not as easily as you could by writing software, of course, but I thought if you were really industrious and lived really cheaply, it had to be possible to make enough to survive. And as an artist you could be truly independent. You wouldn't have a boss, or even need to get research funding. + +I had always liked looking at paintings. Could I make them? I had no idea. I'd never imagined it was even possible. I knew intellectually that people made art โ€” that it didn't just appear spontaneously โ€” but it was as if the people who made it were a different species. They either lived long ago or were mysterious geniuses doing strange things in profiles in Life magazine. The idea of actually being able to make art, to put that verb before that noun, seemed almost miraculous. + +That fall I started taking art classes at Harvard. Grad students could take classes in any department, and my advisor, Tom Cheatham, was very easy going. If he even knew about the strange classes I was taking, he never said anything. + +So now I was in a PhD program in computer science, yet planning to be an artist, yet also genuinely in love with Lisp hacking and working away at On Lisp. In other words, like many a grad student, I was working energetically on multiple projects that were not my thesis. + +I didn't see a way out of this situation. I didn't want to drop out of grad school, but how else was I going to get out? I remember when my friend Robert Morris got kicked out of Cornell for writing the internet worm of 1988, I was envious that he'd found such a spectacular way to get out of grad school. + +Then one day in April 1990 a crack appeared in the wall. I ran into professor Cheatham and he asked if I was far enough along to graduate that June. I didn't have a word of my dissertation written, but in what must have been the quickest bit of thinking in my life, I decided to take a shot at writing one in the 5 weeks or so that remained before the deadline, reusing parts of On Lisp where I could, and I was able to respond, with no perceptible delay "Yes, I think so. I'll give you something to read in a few days." + +I picked applications of continuations as the topic. In retrospect I should have written about macros and embedded languages. There's a whole world there that's barely been explored. But all I wanted was to get out of grad school, and my rapidly written dissertation sufficed, just barely. + +Meanwhile I was applying to art schools. I applied to two: RISD in the US, and the Accademia di Belli Arti in Florence, which, because it was the oldest art school, I imagined would be good. RISD accepted me, and I never heard back from the Accademia, so off to Providence I went. + +I'd applied for the BFA program at RISD, which meant in effect that I had to go to college again. This was not as strange as it sounds, because I was only 25, and art schools are full of people of different ages. RISD counted me as a transfer sophomore and said I had to do the foundation that summer. The foundation means the classes that everyone has to take in fundamental subjects like drawing, color, and design. + +Toward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they'd sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I'd done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian. + +Only stranieri (foreigners) had to take this entrance exam. In retrospect it may well have been a way of excluding them, because there were so many stranieri attracted by the idea of studying art in Florence that the Italian students would otherwise have been outnumbered. I was in decent shape at painting and drawing from the RISD foundation that summer, but I still don't know how I managed to pass the written exam. I remember that I answered the essay question by writing about Cezanne, and that I cranked up the intellectual level as high as I could to make the most of my limited vocabulary. [2] + +I'm only up to age 25 and already there are such conspicuous patterns. Here I was, yet again about to attend some august institution in the hopes of learning about some prestigious subject, and yet again about to be disappointed. The students and faculty in the painting department at the Accademia were the nicest people you could imagine, but they had long since arrived at an arrangement whereby the students wouldn't require the faculty to teach anything, and in return the faculty wouldn't require the students to learn anything. And at the same time all involved would adhere outwardly to the conventions of a 19th century atelier. We actually had one of those little stoves, fed with kindling, that you see in 19th century studio paintings, and a nude model sitting as close to it as possible without getting burned. Except hardly anyone else painted her besides me. The rest of the students spent their time chatting or occasionally trying to imitate things they'd seen in American art magazines. + +Our model turned out to live just down the street from me. She made a living from a combination of modelling and making fakes for a local antique dealer. She'd copy an obscure old painting out of a book, and then he'd take the copy and maltreat it to make it look old. [3] + +While I was a student at the Accademia I started painting still lives in my bedroom at night. These paintings were tiny, because the room was, and because I painted them on leftover scraps of canvas, which was all I could afford at the time. Painting still lives is different from painting people, because the subject, as its name suggests, can't move. People can't sit for more than about 15 minutes at a time, and when they do they don't sit very still. So the traditional m.o. for painting people is to know how to paint a generic person, which you then modify to match the specific person you're painting. Whereas a still life you can, if you want, copy pixel by pixel from what you're seeing. You don't want to stop there, of course, or you get merely photographic accuracy, and what makes a still life interesting is that it's been through a head. You want to emphasize the visual cues that tell you, for example, that the reason the color changes suddenly at a certain point is that it's the edge of an object. By subtly emphasizing such things you can make paintings that are more realistic than photographs not just in some metaphorical sense, but in the strict information-theoretic sense. [4] + +I liked painting still lives because I was curious about what I was seeing. In everyday life, we aren't consciously aware of much we're seeing. Most visual perception is handled by low-level processes that merely tell your brain "that's a water droplet" without telling you details like where the lightest and darkest points are, or "that's a bush" without telling you the shape and position of every leaf. This is a feature of brains, not a bug. In everyday life it would be distracting to notice every leaf on every bush. But when you have to paint something, you have to look more closely, and when you do there's a lot to see. You can still be noticing new things after days of trying to paint something people usually take for granted, just as you can after days of trying to write an essay about something people usually take for granted. + +This is not the only way to paint. I'm not 100% sure it's even a good way to paint. But it seemed a good enough bet to be worth trying. + +Our teacher, professor Ulivi, was a nice guy. He could see I worked hard, and gave me a good grade, which he wrote down in a sort of passport each student had. But the Accademia wasn't teaching me anything except Italian, and my money was running out, so at the end of the first year I went back to the US. + +I wanted to go back to RISD, but I was now broke and RISD was very expensive, so I decided to get a job for a year and then return to RISD the next fall. I got one at a company called Interleaf, which made software for creating documents. You mean like Microsoft Word? Exactly. That was how I learned that low end software tends to eat high end software. But Interleaf still had a few years to live yet. [5] + +Interleaf had done something pretty bold. Inspired by Emacs, they'd added a scripting language, and even made the scripting language a dialect of Lisp. Now they wanted a Lisp hacker to write things in it. This was the closest thing I've had to a normal job, and I hereby apologize to my boss and coworkers, because I was a bad employee. Their Lisp was the thinnest icing on a giant C cake, and since I didn't know C and didn't want to learn it, I never understood most of the software. Plus I was terribly irresponsible. This was back when a programming job meant showing up every day during certain working hours. That seemed unnatural to me, and on this point the rest of the world is coming around to my way of thinking, but at the time it caused a lot of friction. Toward the end of the year I spent much of my time surreptitiously working on On Lisp, which I had by this time gotten a contract to publish. + +The good part was that I got paid huge amounts of money, especially by art student standards. In Florence, after paying my part of the rent, my budget for everything else had been $7 a day. Now I was getting paid more than 4 times that every hour, even when I was just sitting in a meeting. By living cheaply I not only managed to save enough to go back to RISD, but also paid off my college loans. + +I learned some useful things at Interleaf, though they were mostly about what not to do. I learned that it's better for technology companies to be run by product people than sales people (though sales is a real skill and people who are good at it are really good at it), that it leads to bugs when code is edited by too many people, that cheap office space is no bargain if it's depressing, that planned meetings are inferior to corridor conversations, that big, bureaucratic customers are a dangerous source of money, and that there's not much overlap between conventional office hours and the optimal time for hacking, or conventional offices and the optimal place for it. + +But the most important thing I learned, and which I used in both Viaweb and Y Combinator, is that the low end eats the high end: that it's good to be the "entry level" option, even though that will be less prestigious, because if you're not, someone else will be, and will squash you against the ceiling. Which in turn means that prestige is a danger sign. + +When I left to go back to RISD the next fall, I arranged to do freelance work for the group that did projects for customers, and this was how I survived for the next several years. When I came back to visit for a project later on, someone told me about a new thing called HTML, which was, as he described it, a derivative of SGML. Markup language enthusiasts were an occupational hazard at Interleaf and I ignored him, but this HTML thing later became a big part of my life. + +In the fall of 1992 I moved back to Providence to continue at RISD. The foundation had merely been intro stuff, and the Accademia had been a (very civilized) joke. Now I was going to see what real art school was like. But alas it was more like the Accademia than not. Better organized, certainly, and a lot more expensive, but it was now becoming clear that art school did not bear the same relationship to art that medical school bore to medicine. At least not the painting department. The textile department, which my next door neighbor belonged to, seemed to be pretty rigorous. No doubt illustration and architecture were too. But painting was post-rigorous. Painting students were supposed to express themselves, which to the more worldly ones meant to try to cook up some sort of distinctive signature style. + +A signature style is the visual equivalent of what in show business is known as a "schtick": something that immediately identifies the work as yours and no one else's. For example, when you see a painting that looks like a certain kind of cartoon, you know it's by Roy Lichtenstein. So if you see a big painting of this type hanging in the apartment of a hedge fund manager, you know he paid millions of dollars for it. That's not always why artists have a signature style, but it's usually why buyers pay a lot for such work. [6] + +There were plenty of earnest students too: kids who "could draw" in high school, and now had come to what was supposed to be the best art school in the country, to learn to draw even better. They tended to be confused and demoralized by what they found at RISD, but they kept going, because painting was what they did. I was not one of the kids who could draw in high school, but at RISD I was definitely closer to their tribe than the tribe of signature style seekers. + +I learned a lot in the color class I took at RISD, but otherwise I was basically teaching myself to paint, and I could do that for free. So in 1993 I dropped out. I hung around Providence for a bit, and then my college friend Nancy Parmet did me a big favor. A rent-controlled apartment in a building her mother owned in New York was becoming vacant. Did I want it? It wasn't much more than my current place, and New York was supposed to be where the artists were. So yes, I wanted it! [7] + +Asterix comics begin by zooming in on a tiny corner of Roman Gaul that turns out not to be controlled by the Romans. You can do something similar on a map of New York City: if you zoom in on the Upper East Side, there's a tiny corner that's not rich, or at least wasn't in 1993. It's called Yorkville, and that was my new home. Now I was a New York artist โ€” in the strictly technical sense of making paintings and living in New York. + +I was nervous about money, because I could sense that Interleaf was on the way down. Freelance Lisp hacking work was very rare, and I didn't want to have to program in another language, which in those days would have meant C++ if I was lucky. So with my unerring nose for financial opportunity, I decided to write another book on Lisp. This would be a popular book, the sort of book that could be used as a textbook. I imagined myself living frugally off the royalties and spending all my time painting. (The painting on the cover of this book, ANSI Common Lisp, is one that I painted around this time.) + +The best thing about New York for me was the presence of Idelle and Julian Weber. Idelle Weber was a painter, one of the early photorealists, and I'd taken her painting class at Harvard. I've never known a teacher more beloved by her students. Large numbers of former students kept in touch with her, including me. After I moved to New York I became her de facto studio assistant. + +She liked to paint on big, square canvases, 4 to 5 feet on a side. One day in late 1994 as I was stretching one of these monsters there was something on the radio about a famous fund manager. He wasn't that much older than me, and was super rich. The thought suddenly occurred to me: why don't I become rich? Then I'll be able to work on whatever I want. + +Meanwhile I'd been hearing more and more about this new thing called the World Wide Web. Robert Morris showed it to me when I visited him in Cambridge, where he was now in grad school at Harvard. It seemed to me that the web would be a big deal. I'd seen what graphical user interfaces had done for the popularity of microcomputers. It seemed like the web would do the same for the internet. + +If I wanted to get rich, here was the next train leaving the station. I was right about that part. What I got wrong was the idea. I decided we should start a company to put art galleries online. I can't honestly say, after reading so many Y Combinator applications, that this was the worst startup idea ever, but it was up there. Art galleries didn't want to be online, and still don't, not the fancy ones. That's not how they sell. I wrote some software to generate web sites for galleries, and Robert wrote some to resize images and set up an http server to serve the pages. Then we tried to sign up galleries. To call this a difficult sale would be an understatement. It was difficult to give away. A few galleries let us make sites for them for free, but none paid us. + +Then some online stores started to appear, and I realized that except for the order buttons they were identical to the sites we'd been generating for galleries. This impressive-sounding thing called an "internet storefront" was something we already knew how to build. + +So in the summer of 1995, after I submitted the camera-ready copy of ANSI Common Lisp to the publishers, we started trying to write software to build online stores. At first this was going to be normal desktop software, which in those days meant Windows software. That was an alarming prospect, because neither of us knew how to write Windows software or wanted to learn. We lived in the Unix world. But we decided we'd at least try writing a prototype store builder on Unix. Robert wrote a shopping cart, and I wrote a new site generator for stores โ€” in Lisp, of course. + +We were working out of Robert's apartment in Cambridge. His roommate was away for big chunks of time, during which I got to sleep in his room. For some reason there was no bed frame or sheets, just a mattress on the floor. One morning as I was lying on this mattress I had an idea that made me sit up like a capital L. What if we ran the software on the server, and let users control it by clicking on links? Then we'd never have to write anything to run on users' computers. We could generate the sites on the same server we'd serve them from. Users wouldn't need anything more than a browser. + +This kind of software, known as a web app, is common now, but at the time it wasn't clear that it was even possible. To find out, we decided to try making a version of our store builder that you could control through the browser. A couple days later, on August 12, we had one that worked. The UI was horrible, but it proved you could build a whole store through the browser, without any client software or typing anything into the command line on the server. + +Now we felt like we were really onto something. I had visions of a whole new generation of software working this way. You wouldn't need versions, or ports, or any of that crap. At Interleaf there had been a whole group called Release Engineering that seemed to be at least as big as the group that actually wrote the software. Now you could just update the software right on the server. + +We started a new company we called Viaweb, after the fact that our software worked via the web, and we got $10,000 in seed funding from Idelle's husband Julian. In return for that and doing the initial legal work and giving us business advice, we gave him 10% of the company. Ten years later this deal became the model for Y Combinator's. We knew founders needed something like this, because we'd needed it ourselves. + +At this stage I had a negative net worth, because the thousand dollars or so I had in the bank was more than counterbalanced by what I owed the government in taxes. (Had I diligently set aside the proper proportion of the money I'd made consulting for Interleaf? No, I had not.) So although Robert had his graduate student stipend, I needed that seed funding to live on. + +We originally hoped to launch in September, but we got more ambitious about the software as we worked on it. Eventually we managed to build a WYSIWYG site builder, in the sense that as you were creating pages, they looked exactly like the static ones that would be generated later, except that instead of leading to static pages, the links all referred to closures stored in a hash table on the server. + +It helped to have studied art, because the main goal of an online store builder is to make users look legit, and the key to looking legit is high production values. If you get page layouts and fonts and colors right, you can make a guy running a store out of his bedroom look more legit than a big company. + +(If you're curious why my site looks so old-fashioned, it's because it's still made with this software. It may look clunky today, but in 1996 it was the last word in slick.) + +In September, Robert rebelled. "We've been working on this for a month," he said, "and it's still not done." This is funny in retrospect, because he would still be working on it almost 3 years later. But I decided it might be prudent to recruit more programmers, and I asked Robert who else in grad school with him was really good. He recommended Trevor Blackwell, which surprised me at first, because at that point I knew Trevor mainly for his plan to reduce everything in his life to a stack of notecards, which he carried around with him. But Rtm was right, as usual. Trevor turned out to be a frighteningly effective hacker. + +It was a lot of fun working with Robert and Trevor. They're the two most independent-minded people I know, and in completely different ways. If you could see inside Rtm's brain it would look like a colonial New England church, and if you could see inside Trevor's it would look like the worst excesses of Austrian Rococo. + +We opened for business, with 6 stores, in January 1996. It was just as well we waited a few months, because although we worried we were late, we were actually almost fatally early. There was a lot of talk in the press then about ecommerce, but not many people actually wanted online stores. [8] + +There were three main parts to the software: the editor, which people used to build sites and which I wrote, the shopping cart, which Robert wrote, and the manager, which kept track of orders and statistics, and which Trevor wrote. In its time, the editor was one of the best general-purpose site builders. I kept the code tight and didn't have to integrate with any other software except Robert's and Trevor's, so it was quite fun to work on. If all I'd had to do was work on this software, the next 3 years would have been the easiest of my life. Unfortunately I had to do a lot more, all of it stuff I was worse at than programming, and the next 3 years were instead the most stressful. + +There were a lot of startups making ecommerce software in the second half of the 90s. We were determined to be the Microsoft Word, not the Interleaf. Which meant being easy to use and inexpensive. It was lucky for us that we were poor, because that caused us to make Viaweb even more inexpensive than we realized. We charged $100 a month for a small store and $300 a month for a big one. This low price was a big attraction, and a constant thorn in the sides of competitors, but it wasn't because of some clever insight that we set the price low. We had no idea what businesses paid for things. $300 a month seemed like a lot of money to us. + +We did a lot of things right by accident like that. For example, we did what's now called "doing things that don't scale," although at the time we would have described it as "being so lame that we're driven to the most desperate measures to get users." The most common of which was building stores for them. This seemed particularly humiliating, since the whole raison d'etre of our software was that people could use it to make their own stores. But anything to get users. + +We learned a lot more about retail than we wanted to know. For example, that if you could only have a small image of a man's shirt (and all images were small then by present standards), it was better to have a closeup of the collar than a picture of the whole shirt. The reason I remember learning this was that it meant I had to rescan about 30 images of men's shirts. My first set of scans were so beautiful too. + +Though this felt wrong, it was exactly the right thing to be doing. Building stores for users taught us about retail, and about how it felt to use our software. I was initially both mystified and repelled by "business" and thought we needed a "business person" to be in charge of it, but once we started to get users, I was converted, in much the same way I was converted to fatherhood once I had kids. Whatever users wanted, I was all theirs. Maybe one day we'd have so many users that I couldn't scan their images for them, but in the meantime there was nothing more important to do. + +Another thing I didn't get at the time is that growth rate is the ultimate test of a startup. Our growth rate was fine. We had about 70 stores at the end of 1996 and about 500 at the end of 1997. I mistakenly thought the thing that mattered was the absolute number of users. And that is the thing that matters in the sense that that's how much money you're making, and if you're not making enough, you might go out of business. But in the long term the growth rate takes care of the absolute number. If we'd been a startup I was advising at Y Combinator, I would have said: Stop being so stressed out, because you're doing fine. You're growing 7x a year. Just don't hire too many more people and you'll soon be profitable, and then you'll control your own destiny. + +Alas I hired lots more people, partly because our investors wanted me to, and partly because that's what startups did during the Internet Bubble. A company with just a handful of employees would have seemed amateurish. So we didn't reach breakeven until about when Yahoo bought us in the summer of 1998. Which in turn meant we were at the mercy of investors for the entire life of the company. And since both we and our investors were noobs at startups, the result was a mess even by startup standards. + +It was a huge relief when Yahoo bought us. In principle our Viaweb stock was valuable. It was a share in a business that was profitable and growing rapidly. But it didn't feel very valuable to me; I had no idea how to value a business, but I was all too keenly aware of the near-death experiences we seemed to have every few months. Nor had I changed my grad student lifestyle significantly since we started. So when Yahoo bought us it felt like going from rags to riches. Since we were going to California, I bought a car, a yellow 1998 VW GTI. I remember thinking that its leather seats alone were by far the most luxurious thing I owned. + +The next year, from the summer of 1998 to the summer of 1999, must have been the least productive of my life. I didn't realize it at the time, but I was worn out from the effort and stress of running Viaweb. For a while after I got to California I tried to continue my usual m.o. of programming till 3 in the morning, but fatigue combined with Yahoo's prematurely aged culture and grim cube farm in Santa Clara gradually dragged me down. After a few months it felt disconcertingly like working at Interleaf. + +Yahoo had given us a lot of options when they bought us. At the time I thought Yahoo was so overvalued that they'd never be worth anything, but to my astonishment the stock went up 5x in the next year. I hung on till the first chunk of options vested, then in the summer of 1999 I left. It had been so long since I'd painted anything that I'd half forgotten why I was doing this. My brain had been entirely full of software and men's shirts for 4 years. But I had done this to get rich so I could paint, I reminded myself, and now I was rich, so I should go paint. + +When I said I was leaving, my boss at Yahoo had a long conversation with me about my plans. I told him all about the kinds of pictures I wanted to paint. At the time I was touched that he took such an interest in me. Now I realize it was because he thought I was lying. My options at that point were worth about $2 million a month. If I was leaving that kind of money on the table, it could only be to go and start some new startup, and if I did, I might take people with me. This was the height of the Internet Bubble, and Yahoo was ground zero of it. My boss was at that moment a billionaire. Leaving then to start a new startup must have seemed to him an insanely, and yet also plausibly, ambitious plan. + +But I really was quitting to paint, and I started immediately. There was no time to lose. I'd already burned 4 years getting rich. Now when I talk to founders who are leaving after selling their companies, my advice is always the same: take a vacation. That's what I should have done, just gone off somewhere and done nothing for a month or two, but the idea never occurred to me. + +So I tried to paint, but I just didn't seem to have any energy or ambition. Part of the problem was that I didn't know many people in California. I'd compounded this problem by buying a house up in the Santa Cruz Mountains, with a beautiful view but miles from anywhere. I stuck it out for a few more months, then in desperation I went back to New York, where unless you understand about rent control you'll be surprised to hear I still had my apartment, sealed up like a tomb of my old life. Idelle was in New York at least, and there were other people trying to paint there, even though I didn't know any of them. + +When I got back to New York I resumed my old life, except now I was rich. It was as weird as it sounds. I resumed all my old patterns, except now there were doors where there hadn't been. Now when I was tired of walking, all I had to do was raise my hand, and (unless it was raining) a taxi would stop to pick me up. Now when I walked past charming little restaurants I could go in and order lunch. It was exciting for a while. Painting started to go better. I experimented with a new kind of still life where I'd paint one painting in the old way, then photograph it and print it, blown up, on canvas, and then use that as the underpainting for a second still life, painted from the same objects (which hopefully hadn't rotted yet). + +Meanwhile I looked for an apartment to buy. Now I could actually choose what neighborhood to live in. Where, I asked myself and various real estate agents, is the Cambridge of New York? Aided by occasional visits to actual Cambridge, I gradually realized there wasn't one. Huh. + +Around this time, in the spring of 2000, I had an idea. It was clear from our experience with Viaweb that web apps were the future. Why not build a web app for making web apps? Why not let people edit code on our server through the browser, and then host the resulting applications for them? [9] You could run all sorts of services on the servers that these applications could use just by making an API call: making and receiving phone calls, manipulating images, taking credit card payments, etc. + +I got so excited about this idea that I couldn't think about anything else. It seemed obvious that this was the future. I didn't particularly want to start another company, but it was clear that this idea would have to be embodied as one, so I decided to move to Cambridge and start it. I hoped to lure Robert into working on it with me, but there I ran into a hitch. Robert was now a postdoc at MIT, and though he'd made a lot of money the last time I'd lured him into working on one of my schemes, it had also been a huge time sink. So while he agreed that it sounded like a plausible idea, he firmly refused to work on it. + +Hmph. Well, I'd do it myself then. I recruited Dan Giffin, who had worked for Viaweb, and two undergrads who wanted summer jobs, and we got to work trying to build what it's now clear is about twenty companies and several open source projects worth of software. The language for defining applications would of course be a dialect of Lisp. But I wasn't so naive as to assume I could spring an overt Lisp on a general audience; we'd hide the parentheses, like Dylan did. + +By then there was a name for the kind of company Viaweb was, an "application service provider," or ASP. This name didn't last long before it was replaced by "software as a service," but it was current for long enough that I named this new company after it: it was going to be called Aspra. + +I started working on the application builder, Dan worked on network infrastructure, and the two undergrads worked on the first two services (images and phone calls). But about halfway through the summer I realized I really didn't want to run a company โ€” especially not a big one, which it was looking like this would have to be. I'd only started Viaweb because I needed the money. Now that I didn't need money anymore, why was I doing this? If this vision had to be realized as a company, then screw the vision. I'd build a subset that could be done as an open source project. + +Much to my surprise, the time I spent working on this stuff was not wasted after all. After we started Y Combinator, I would often encounter startups working on parts of this new architecture, and it was very useful to have spent so much time thinking about it and even trying to write some of it. + +The subset I would build as an open source project was the new Lisp, whose parentheses I now wouldn't even have to hide. A lot of Lisp hackers dream of building a new Lisp, partly because one of the distinctive features of the language is that it has dialects, and partly, I think, because we have in our minds a Platonic form of Lisp that all existing dialects fall short of. I certainly did. So at the end of the summer Dan and I switched to working on this new dialect of Lisp, which I called Arc, in a house I bought in Cambridge. + +The following spring, lightning struck. I was invited to give a talk at a Lisp conference, so I gave one about how we'd used Lisp at Viaweb. Afterward I put a postscript file of this talk online, on paulgraham.com, which I'd created years before using Viaweb but had never used for anything. In one day it got 30,000 page views. What on earth had happened? The referring urls showed that someone had posted it on Slashdot. [10] + +Wow, I thought, there's an audience. If I write something and put it on the web, anyone can read it. That may seem obvious now, but it was surprising then. In the print era there was a narrow channel to readers, guarded by fierce monsters known as editors. The only way to get an audience for anything you wrote was to get it published as a book, or in a newspaper or magazine. Now anyone could publish anything. + +This had been possible in principle since 1993, but not many people had realized it yet. I had been intimately involved with building the infrastructure of the web for most of that time, and a writer as well, and it had taken me 8 years to realize it. Even then it took me several years to understand the implications. It meant there would be a whole new generation of essays. [11] + +In the print era, the channel for publishing essays had been vanishingly small. Except for a few officially anointed thinkers who went to the right parties in New York, the only people allowed to publish essays were specialists writing about their specialties. There were so many essays that had never been written, because there had been no way to publish them. Now they could be, and I was going to write them. [12] + +I've worked on several different things, but to the extent there was a turning point where I figured out what to work on, it was when I started publishing essays online. From then on I knew that whatever else I did, I'd always write essays too. + +I knew that online essays would be a marginal medium at first. Socially they'd seem more like rants posted by nutjobs on their GeoCities sites than the genteel and beautifully typeset compositions published in The New Yorker. But by this point I knew enough to find that encouraging instead of discouraging. + +One of the most conspicuous patterns I've noticed in my life is how well it has worked, for me at least, to work on things that weren't prestigious. Still life has always been the least prestigious form of painting. Viaweb and Y Combinator both seemed lame when we started them. I still get the glassy eye from strangers when they ask what I'm writing, and I explain that it's an essay I'm going to publish on my web site. Even Lisp, though prestigious intellectually in something like the way Latin is, also seems about as hip. + +It's not that unprestigious types of work are good per se. But when you find yourself drawn to some kind of work despite its current lack of prestige, it's a sign both that there's something real to be discovered there, and that you have the right kind of motives. Impure motives are a big danger for the ambitious. If anything is going to lead you astray, it will be the desire to impress people. So while working on things that aren't prestigious doesn't guarantee you're on the right track, it at least guarantees you're not on the most common type of wrong one. + +Over the next several years I wrote lots of essays about all kinds of different topics. O'Reilly reprinted a collection of them as a book, called Hackers & Painters after one of the essays in it. I also worked on spam filters, and did some more painting. I used to have dinners for a group of friends every thursday night, which taught me how to cook for groups. And I bought another building in Cambridge, a former candy factory (and later, twas said, porn studio), to use as an office. + +One night in October 2003 there was a big party at my house. It was a clever idea of my friend Maria Daniels, who was one of the thursday diners. Three separate hosts would all invite their friends to one party. So for every guest, two thirds of the other guests would be people they didn't know but would probably like. One of the guests was someone I didn't know but would turn out to like a lot: a woman called Jessica Livingston. A couple days later I asked her out. + +Jessica was in charge of marketing at a Boston investment bank. This bank thought it understood startups, but over the next year, as she met friends of mine from the startup world, she was surprised how different reality was. And how colorful their stories were. So she decided to compile a book of interviews with startup founders. + +When the bank had financial problems and she had to fire half her staff, she started looking for a new job. In early 2005 she interviewed for a marketing job at a Boston VC firm. It took them weeks to make up their minds, and during this time I started telling her about all the things that needed to be fixed about venture capital. They should make a larger number of smaller investments instead of a handful of giant ones, they should be funding younger, more technical founders instead of MBAs, they should let the founders remain as CEO, and so on. + +One of my tricks for writing essays had always been to give talks. The prospect of having to stand up in front of a group of people and tell them something that won't waste their time is a great spur to the imagination. When the Harvard Computer Society, the undergrad computer club, asked me to give a talk, I decided I would tell them how to start a startup. Maybe they'd be able to avoid the worst of the mistakes we'd made. + +So I gave this talk, in the course of which I told them that the best sources of seed funding were successful startup founders, because then they'd be sources of advice too. Whereupon it seemed they were all looking expectantly at me. Horrified at the prospect of having my inbox flooded by business plans (if I'd only known), I blurted out "But not me!" and went on with the talk. But afterward it occurred to me that I should really stop procrastinating about angel investing. I'd been meaning to since Yahoo bought us, and now it was 7 years later and I still hadn't done one angel investment. + +Meanwhile I had been scheming with Robert and Trevor about projects we could work on together. I missed working with them, and it seemed like there had to be something we could collaborate on. + +As Jessica and I were walking home from dinner on March 11, at the corner of Garden and Walker streets, these three threads converged. Screw the VCs who were taking so long to make up their minds. We'd start our own investment firm and actually implement the ideas we'd been talking about. I'd fund it, and Jessica could quit her job and work for it, and we'd get Robert and Trevor as partners too. [13] + +Once again, ignorance worked in our favor. We had no idea how to be angel investors, and in Boston in 2005 there were no Ron Conways to learn from. So we just made what seemed like the obvious choices, and some of the things we did turned out to be novel. + +There are multiple components to Y Combinator, and we didn't figure them all out at once. The part we got first was to be an angel firm. In those days, those two words didn't go together. There were VC firms, which were organized companies with people whose job it was to make investments, but they only did big, million dollar investments. And there were angels, who did smaller investments, but these were individuals who were usually focused on other things and made investments on the side. And neither of them helped founders enough in the beginning. We knew how helpless founders were in some respects, because we remembered how helpless we'd been. For example, one thing Julian had done for us that seemed to us like magic was to get us set up as a company. We were fine writing fairly difficult software, but actually getting incorporated, with bylaws and stock and all that stuff, how on earth did you do that? Our plan was not only to make seed investments, but to do for startups everything Julian had done for us. + +YC was not organized as a fund. It was cheap enough to run that we funded it with our own money. That went right by 99% of readers, but professional investors are thinking "Wow, that means they got all the returns." But once again, this was not due to any particular insight on our part. We didn't know how VC firms were organized. It never occurred to us to try to raise a fund, and if it had, we wouldn't have known where to start. [14] + +The most distinctive thing about YC is the batch model: to fund a bunch of startups all at once, twice a year, and then to spend three months focusing intensively on trying to help them. That part we discovered by accident, not merely implicitly but explicitly due to our ignorance about investing. We needed to get experience as investors. What better way, we thought, than to fund a whole bunch of startups at once? We knew undergrads got temporary jobs at tech companies during the summer. Why not organize a summer program where they'd start startups instead? We wouldn't feel guilty for being in a sense fake investors, because they would in a similar sense be fake founders. So while we probably wouldn't make much money out of it, we'd at least get to practice being investors on them, and they for their part would probably have a more interesting summer than they would working at Microsoft. + +We'd use the building I owned in Cambridge as our headquarters. We'd all have dinner there once a week โ€” on tuesdays, since I was already cooking for the thursday diners on thursdays โ€” and after dinner we'd bring in experts on startups to give talks. + +We knew undergrads were deciding then about summer jobs, so in a matter of days we cooked up something we called the Summer Founders Program, and I posted an announcement on my site, inviting undergrads to apply. I had never imagined that writing essays would be a way to get "deal flow," as investors call it, but it turned out to be the perfect source. [15] We got 225 applications for the Summer Founders Program, and we were surprised to find that a lot of them were from people who'd already graduated, or were about to that spring. Already this SFP thing was starting to feel more serious than we'd intended. + +We invited about 20 of the 225 groups to interview in person, and from those we picked 8 to fund. They were an impressive group. That first batch included reddit, Justin Kan and Emmett Shear, who went on to found Twitch, Aaron Swartz, who had already helped write the RSS spec and would a few years later become a martyr for open access, and Sam Altman, who would later become the second president of YC. I don't think it was entirely luck that the first batch was so good. You had to be pretty bold to sign up for a weird thing like the Summer Founders Program instead of a summer job at a legit place like Microsoft or Goldman Sachs. + +The deal for startups was based on a combination of the deal we did with Julian ($10k for 10%) and what Robert said MIT grad students got for the summer ($6k). We invested $6k per founder, which in the typical two-founder case was $12k, in return for 6%. That had to be fair, because it was twice as good as the deal we ourselves had taken. Plus that first summer, which was really hot, Jessica brought the founders free air conditioners. [16] + +Fairly quickly I realized that we had stumbled upon the way to scale startup funding. Funding startups in batches was more convenient for us, because it meant we could do things for a lot of startups at once, but being part of a batch was better for the startups too. It solved one of the biggest problems faced by founders: the isolation. Now you not only had colleagues, but colleagues who understood the problems you were facing and could tell you how they were solving them. + +As YC grew, we started to notice other advantages of scale. The alumni became a tight community, dedicated to helping one another, and especially the current batch, whose shoes they remembered being in. We also noticed that the startups were becoming one another's customers. We used to refer jokingly to the "YC GDP," but as YC grows this becomes less and less of a joke. Now lots of startups get their initial set of customers almost entirely from among their batchmates. + +I had not originally intended YC to be a full-time job. I was going to do three things: hack, write essays, and work on YC. As YC grew, and I grew more excited about it, it started to take up a lot more than a third of my attention. But for the first few years I was still able to work on other things. + +In the summer of 2006, Robert and I started working on a new version of Arc. This one was reasonably fast, because it was compiled into Scheme. To test this new Arc, I wrote Hacker News in it. It was originally meant to be a news aggregator for startup founders and was called Startup News, but after a few months I got tired of reading about nothing but startups. Plus it wasn't startup founders we wanted to reach. It was future startup founders. So I changed the name to Hacker News and the topic to whatever engaged one's intellectual curiosity. + +HN was no doubt good for YC, but it was also by far the biggest source of stress for me. If all I'd had to do was select and help founders, life would have been so easy. And that implies that HN was a mistake. Surely the biggest source of stress in one's work should at least be something close to the core of the work. Whereas I was like someone who was in pain while running a marathon not from the exertion of running, but because I had a blister from an ill-fitting shoe. When I was dealing with some urgent problem during YC, there was about a 60% chance it had to do with HN, and a 40% chance it had do with everything else combined. [17] + +As well as HN, I wrote all of YC's internal software in Arc. But while I continued to work a good deal in Arc, I gradually stopped working on Arc, partly because I didn't have time to, and partly because it was a lot less attractive to mess around with the language now that we had all this infrastructure depending on it. So now my three projects were reduced to two: writing essays and working on YC. + +YC was different from other kinds of work I've done. Instead of deciding for myself what to work on, the problems came to me. Every 6 months there was a new batch of startups, and their problems, whatever they were, became our problems. It was very engaging work, because their problems were quite varied, and the good founders were very effective. If you were trying to learn the most you could about startups in the shortest possible time, you couldn't have picked a better way to do it. + +There were parts of the job I didn't like. Disputes between cofounders, figuring out when people were lying to us, fighting with people who maltreated the startups, and so on. But I worked hard even at the parts I didn't like. I was haunted by something Kevin Hale once said about companies: "No one works harder than the boss." He meant it both descriptively and prescriptively, and it was the second part that scared me. I wanted YC to be good, so if how hard I worked set the upper bound on how hard everyone else worked, I'd better work very hard. + +One day in 2010, when he was visiting California for interviews, Robert Morris did something astonishing: he offered me unsolicited advice. I can only remember him doing that once before. One day at Viaweb, when I was bent over double from a kidney stone, he suggested that it would be a good idea for him to take me to the hospital. That was what it took for Rtm to offer unsolicited advice. So I remember his exact words very clearly. "You know," he said, "you should make sure Y Combinator isn't the last cool thing you do." + +At the time I didn't understand what he meant, but gradually it dawned on me that he was saying I should quit. This seemed strange advice, because YC was doing great. But if there was one thing rarer than Rtm offering advice, it was Rtm being wrong. So this set me thinking. It was true that on my current trajectory, YC would be the last thing I did, because it was only taking up more of my attention. It had already eaten Arc, and was in the process of eating essays too. Either YC was my life's work or I'd have to leave eventually. And it wasn't, so I would. + +In the summer of 2012 my mother had a stroke, and the cause turned out to be a blood clot caused by colon cancer. The stroke destroyed her balance, and she was put in a nursing home, but she really wanted to get out of it and back to her house, and my sister and I were determined to help her do it. I used to fly up to Oregon to visit her regularly, and I had a lot of time to think on those flights. On one of them I realized I was ready to hand YC over to someone else. + +I asked Jessica if she wanted to be president, but she didn't, so we decided we'd try to recruit Sam Altman. We talked to Robert and Trevor and we agreed to make it a complete changing of the guard. Up till that point YC had been controlled by the original LLC we four had started. But we wanted YC to last for a long time, and to do that it couldn't be controlled by the founders. So if Sam said yes, we'd let him reorganize YC. Robert and I would retire, and Jessica and Trevor would become ordinary partners. + +When we asked Sam if he wanted to be president of YC, initially he said no. He wanted to start a startup to make nuclear reactors. But I kept at it, and in October 2013 he finally agreed. We decided he'd take over starting with the winter 2014 batch. For the rest of 2013 I left running YC more and more to Sam, partly so he could learn the job, and partly because I was focused on my mother, whose cancer had returned. + +She died on January 15, 2014. We knew this was coming, but it was still hard when it did. + +I kept working on YC till March, to help get that batch of startups through Demo Day, then I checked out pretty completely. (I still talk to alumni and to new startups working on things I'm interested in, but that only takes a few hours a week.) + +What should I do next? Rtm's advice hadn't included anything about that. I wanted to do something completely different, so I decided I'd paint. I wanted to see how good I could get if I really focused on it. So the day after I stopped working on YC, I started painting. I was rusty and it took a while to get back into shape, but it was at least completely engaging. [18] + +I spent most of the rest of 2014 painting. I'd never been able to work so uninterruptedly before, and I got to be better than I had been. Not good enough, but better. Then in November, right in the middle of a painting, I ran out of steam. Up till that point I'd always been curious to see how the painting I was working on would turn out, but suddenly finishing this one seemed like a chore. So I stopped working on it and cleaned my brushes and haven't painted since. So far anyway. + +I realize that sounds rather wimpy. But attention is a zero sum game. If you can choose what to work on, and you choose a project that's not the best one (or at least a good one) for you, then it's getting in the way of another project that is. And at 50 there was some opportunity cost to screwing around. + +I started writing essays again, and wrote a bunch of new ones over the next few months. I even wrote a couple that weren't about startups. Then in March 2015 I started working on Lisp again. + +The distinctive thing about Lisp is that its core is a language defined by writing an interpreter in itself. It wasn't originally intended as a programming language in the ordinary sense. It was meant to be a formal model of computation, an alternative to the Turing machine. If you want to write an interpreter for a language in itself, what's the minimum set of predefined operators you need? The Lisp that John McCarthy invented, or more accurately discovered, is an answer to that question. [19] + +McCarthy didn't realize this Lisp could even be used to program computers till his grad student Steve Russell suggested it. Russell translated McCarthy's interpreter into IBM 704 machine language, and from that point Lisp started also to be a programming language in the ordinary sense. But its origins as a model of computation gave it a power and elegance that other languages couldn't match. It was this that attracted me in college, though I didn't understand why at the time. + +McCarthy's 1960 Lisp did nothing more than interpret Lisp expressions. It was missing a lot of things you'd want in a programming language. So these had to be added, and when they were, they weren't defined using McCarthy's original axiomatic approach. That wouldn't have been feasible at the time. McCarthy tested his interpreter by hand-simulating the execution of programs. But it was already getting close to the limit of interpreters you could test that way โ€” indeed, there was a bug in it that McCarthy had overlooked. To test a more complicated interpreter, you'd have had to run it, and computers then weren't powerful enough. + +Now they are, though. Now you could continue using McCarthy's axiomatic approach till you'd defined a complete programming language. And as long as every change you made to McCarthy's Lisp was a discoveredness-preserving transformation, you could, in principle, end up with a complete language that had this quality. Harder to do than to talk about, of course, but if it was possible in principle, why not try? So I decided to take a shot at it. It took 4 years, from March 26, 2015 to October 12, 2019. It was fortunate that I had a precisely defined goal, or it would have been hard to keep at it for so long. + +I wrote this new Lisp, called Bel, in itself in Arc. That may sound like a contradiction, but it's an indication of the sort of trickery I had to engage in to make this work. By means of an egregious collection of hacks I managed to make something close enough to an interpreter written in itself that could actually run. Not fast, but fast enough to test. + +I had to ban myself from writing essays during most of this time, or I'd never have finished. In late 2015 I spent 3 months writing essays, and when I went back to working on Bel I could barely understand the code. Not so much because it was badly written as because the problem is so convoluted. When you're working on an interpreter written in itself, it's hard to keep track of what's happening at what level, and errors can be practically encrypted by the time you get them. + +So I said no more essays till Bel was done. But I told few people about Bel while I was working on it. So for years it must have seemed that I was doing nothing, when in fact I was working harder than I'd ever worked on anything. Occasionally after wrestling for hours with some gruesome bug I'd check Twitter or HN and see someone asking "Does Paul Graham still code?" + +Working on Bel was hard but satisfying. I worked on it so intensively that at any given time I had a decent chunk of the code in my head and could write more there. I remember taking the boys to the coast on a sunny day in 2015 and figuring out how to deal with some problem involving continuations while I watched them play in the tide pools. It felt like I was doing life right. I remember that because I was slightly dismayed at how novel it felt. The good news is that I had more moments like this over the next few years. + +In the summer of 2016 we moved to England. We wanted our kids to see what it was like living in another country, and since I was a British citizen by birth, that seemed the obvious choice. We only meant to stay for a year, but we liked it so much that we still live there. So most of Bel was written in England. + +In the fall of 2019, Bel was finally finished. Like McCarthy's original Lisp, it's a spec rather than an implementation, although like McCarthy's Lisp it's a spec expressed as code. + +Now that I could write essays again, I wrote a bunch about topics I'd had stacked up. I kept writing essays through 2020, but I also started to think about other things I could work on. How should I choose what to do? Well, how had I chosen what to work on in the past? I wrote an essay for myself to answer that question, and I was surprised how long and messy the answer turned out to be. If this surprised me, who'd lived it, then I thought perhaps it would be interesting to other people, and encouraging to those with similarly messy lives. So I wrote a more detailed version for others to read, and this is the last sentence of it. + + + + + + + + + +Notes + +[1] My experience skipped a step in the evolution of computers: time-sharing machines with interactive OSes. I went straight from batch processing to microcomputers, which made microcomputers seem all the more exciting. + +[2] Italian words for abstract concepts can nearly always be predicted from their English cognates (except for occasional traps like polluzione). It's the everyday words that differ. So if you string together a lot of abstract concepts with a few simple verbs, you can make a little Italian go a long way. + +[3] I lived at Piazza San Felice 4, so my walk to the Accademia went straight down the spine of old Florence: past the Pitti, across the bridge, past Orsanmichele, between the Duomo and the Baptistery, and then up Via Ricasoli to Piazza San Marco. I saw Florence at street level in every possible condition, from empty dark winter evenings to sweltering summer days when the streets were packed with tourists. + +[4] You can of course paint people like still lives if you want to, and they're willing. That sort of portrait is arguably the apex of still life painting, though the long sitting does tend to produce pained expressions in the sitters. + +[5] Interleaf was one of many companies that had smart people and built impressive technology, and yet got crushed by Moore's Law. In the 1990s the exponential growth in the power of commodity (i.e. Intel) processors rolled up high-end, special-purpose hardware and software companies like a bulldozer. + +[6] The signature style seekers at RISD weren't specifically mercenary. In the art world, money and coolness are tightly coupled. Anything expensive comes to be seen as cool, and anything seen as cool will soon become equally expensive. + +[7] Technically the apartment wasn't rent-controlled but rent-stabilized, but this is a refinement only New Yorkers would know or care about. The point is that it was really cheap, less than half market price. + +[8] Most software you can launch as soon as it's done. But when the software is an online store builder and you're hosting the stores, if you don't have any users yet, that fact will be painfully obvious. So before we could launch publicly we had to launch privately, in the sense of recruiting an initial set of users and making sure they had decent-looking stores. + +[9] We'd had a code editor in Viaweb for users to define their own page styles. They didn't know it, but they were editing Lisp expressions underneath. But this wasn't an app editor, because the code ran when the merchants' sites were generated, not when shoppers visited them. + +[10] This was the first instance of what is now a familiar experience, and so was what happened next, when I read the comments and found they were full of angry people. How could I claim that Lisp was better than other languages? Weren't they all Turing complete? People who see the responses to essays I write sometimes tell me how sorry they feel for me, but I'm not exaggerating when I reply that it has always been like this, since the very beginning. It comes with the territory. An essay must tell readers things they don't already know, and some people dislike being told such things. + +[11] People put plenty of stuff on the internet in the 90s of course, but putting something online is not the same as publishing it online. Publishing online means you treat the online version as the (or at least a) primary version. + +[12] There is a general lesson here that our experience with Y Combinator also teaches: Customs continue to constrain you long after the restrictions that caused them have disappeared. Customary VC practice had once, like the customs about publishing essays, been based on real constraints. Startups had once been much more expensive to start, and proportionally rare. Now they could be cheap and common, but the VCs' customs still reflected the old world, just as customs about writing essays still reflected the constraints of the print era. + +Which in turn implies that people who are independent-minded (i.e. less influenced by custom) will have an advantage in fields affected by rapid change (where customs are more likely to be obsolete). + +Here's an interesting point, though: you can't always predict which fields will be affected by rapid change. Obviously software and venture capital will be, but who would have predicted that essay writing would be? + +[13] Y Combinator was not the original name. At first we were called Cambridge Seed. But we didn't want a regional name, in case someone copied us in Silicon Valley, so we renamed ourselves after one of the coolest tricks in the lambda calculus, the Y combinator. + +I picked orange as our color partly because it's the warmest, and partly because no VC used it. In 2005 all the VCs used staid colors like maroon, navy blue, and forest green, because they were trying to appeal to LPs, not founders. The YC logo itself is an inside joke: the Viaweb logo had been a white V on a red circle, so I made the YC logo a white Y on an orange square. + +[14] YC did become a fund for a couple years starting in 2009, because it was getting so big I could no longer afford to fund it personally. But after Heroku got bought we had enough money to go back to being self-funded. + +[15] I've never liked the term "deal flow," because it implies that the number of new startups at any given time is fixed. This is not only false, but it's the purpose of YC to falsify it, by causing startups to be founded that would not otherwise have existed. + +[16] She reports that they were all different shapes and sizes, because there was a run on air conditioners and she had to get whatever she could, but that they were all heavier than she could carry now. + +[17] Another problem with HN was a bizarre edge case that occurs when you both write essays and run a forum. When you run a forum, you're assumed to see if not every conversation, at least every conversation involving you. And when you write essays, people post highly imaginative misinterpretations of them on forums. Individually these two phenomena are tedious but bearable, but the combination is disastrous. You actually have to respond to the misinterpretations, because the assumption that you're present in the conversation means that not responding to any sufficiently upvoted misinterpretation reads as a tacit admission that it's correct. But that in turn encourages more; anyone who wants to pick a fight with you senses that now is their chance. + +[18] The worst thing about leaving YC was not working with Jessica anymore. We'd been working on YC almost the whole time we'd known each other, and we'd neither tried nor wanted to separate it from our personal lives, so leaving was like pulling up a deeply rooted tree. + +[19] One way to get more precise about the concept of invented vs discovered is to talk about space aliens. Any sufficiently advanced alien civilization would certainly know about the Pythagorean theorem, for example. I believe, though with less certainty, that they would also know about the Lisp in McCarthy's 1960 paper. + +But if so there's no reason to suppose that this is the limit of the language that might be known to them. Presumably aliens need numbers and errors and I/O too. So it seems likely there exists at least one path out of McCarthy's Lisp along which discoveredness is preserved. + + + +Thanks to Trevor Blackwell, John Collison, Patrick Collison, Daniel Gackle, Ralph Hazell, Jessica Livingston, Robert Morris, and Harj Taggar for reading drafts of this. \ No newline at end of file From abcd104ef2278c1e1b09d59779160e619baa3f48 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Wed, 21 Feb 2024 11:49:32 +0100 Subject: [PATCH 03/24] fixing path from example --- docs/examples/usage_example.ipynb | 57 ++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/docs/examples/usage_example.ipynb b/docs/examples/usage_example.ipynb index 8c5be0e..7e0214f 100644 --- a/docs/examples/usage_example.ipynb +++ b/docs/examples/usage_example.ipynb @@ -51,7 +51,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -86,9 +86,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/client.py:195: UserWarning: You're connecting to Argilla Server 1.21.0 using a different client version (1.24.0).\n", + "This may lead to potential compatibility issues during your experience.\n", + "To ensure a seamless and optimized connection, we highly recommend aligning your client version with the server version.\n", + " warnings.warn(\n" + ] + } + ], "source": [ "import argilla as rg\n", "\n", @@ -101,7 +112,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -117,7 +128,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -133,12 +144,21 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/s0/4h4_2s7n3wxbm06wx8y43mm80000gn/T/ipykernel_86259/2413633764.py:1: DeprecationWarning: Call to deprecated class method from_defaults. (ServiceContext is deprecated, please use `llama_index.settings.Settings` instead.) -- Deprecated since version 0.10.0.\n", + " service_context = ServiceContext.from_defaults(llm=llm)\n" + ] + } + ], "source": [ "service_context = ServiceContext.from_defaults(llm=llm)\n", - "docs = SimpleDirectoryReader(\"data\").load_data()\n", + "docs = SimpleDirectoryReader(\"../data\").load_data()\n", "index = VectorStoreIndex.from_documents(docs, service_context=service_context)\n", "query_engine = index.as_query_engine()" ] @@ -152,9 +172,20 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Response(response='The author worked on writing and programming before college.', source_nodes=[NodeWithScore(node=TextNode(id_='c9202a57-b440-4d86-9a5e-795ada63ba29', embedding=None, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={: RelatedNodeInfo(node_id='5ea14634-052e-4b7f-b930-9025ae6202b3', node_type=, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, hash='d2f61ad5c414d7e0b68273550ae08d00f8931141e7666b3f86f68b0f81a6abdc'), : RelatedNodeInfo(node_id='a09c8100-edf6-4ccb-9cb1-dcf80bb979ef', node_type=, metadata={}, hash='692d74391b6ad961556d19669374a543e4752bab10e415d8eeeda9ccf682a597')}, text='What I Worked On\\n\\nFebruary 2021\\n\\nBefore college the two main things I worked on, outside of school, were writing and programming. I didn\\'t write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep.\\n\\nThe first programs I tried writing were on the IBM 1401 that our school district used for what was then called \"data processing.\" This was in 9th grade, so I was 13 or 14. The school district\\'s 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain\\'s lair down there, with all these alien-looking machines โ€” CPU, disk drives, printer, card reader โ€” sitting up on a raised floor under bright fluorescent lights.\\n\\nThe language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer.\\n\\nI was puzzled by the 1401. I couldn\\'t figure out what to do with it. And in retrospect there\\'s not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn\\'t have any data stored on punched cards. The only other option was to do things that didn\\'t rely on any input, like calculate approximations of pi, but I didn\\'t know enough math to do anything interesting of that type. So I\\'m not surprised I can\\'t remember any programs I wrote, because they can\\'t have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn\\'t. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager\\'s expression made clear.\\n\\nWith microcomputers, everything changed. Now you could have a computer sitting right in front of you, on a desk, that could respond to your keystrokes as it was running instead of just churning through a stack of punch cards and then stopping. [1]\\n\\nThe first of my friends to get a microcomputer built it himself. It was sold as a kit by Heathkit. I remember vividly how impressed and envious I felt watching him sitting in front of it, typing programs right into the computer.\\n\\nComputers were expensive in those days and it took me years of nagging before I convinced my father to buy one, a TRS-80, in about 1980. The gold standard then was the Apple II, but a TRS-80 was good enough. This was when I really started programming. I wrote simple games, a program to predict how high my model rockets would fly, and a word processor that my father used to write at least one book. There was only room in memory for about 2 pages of text, so he\\'d write 2 pages at a time and then print them out, but it was a lot better than a typewriter.\\n\\nThough I liked programming, I didn\\'t plan to study it in college. In college I was going to study philosophy, which sounded much more powerful. It seemed, to my naive high school self, to be the study of the ultimate truths, compared to which the things studied in other fields would be mere domain knowledge. What I discovered when I got to college was that the other fields took up so much of the space of ideas that there wasn\\'t much left for these supposed ultimate truths. All that seemed left for philosophy were edge cases that people in other fields felt could safely be ignored.\\n\\nI couldn\\'t have put this into words when I was 18. All I knew at the time was that I kept taking philosophy courses and they kept being boring. So I decided to switch to AI.\\n\\nAI was in the air in the mid 1980s, but there were two things especially that made me want to work on it: a novel by Heinlein called The Moon is a Harsh Mistress, which featured an intelligent computer called Mike, and a PBS documentary that showed Terry Winograd using SHRDLU. I haven\\'t tried rereading The Moon is a Harsh Mistress, so I don\\'t know how well it has aged, but when I read it I was drawn entirely into its world. It seemed only a matter of time before we\\'d have Mike, and when I saw Winograd using SHRDLU, it seemed like that time would be a few years at most.', start_char_idx=2, end_char_idx=4320, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n'), score=0.8174733404525298), NodeWithScore(node=TextNode(id_='8222d396-1cd5-4c5f-8e15-f44be1213d6a', embedding=None, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={: RelatedNodeInfo(node_id='5ea14634-052e-4b7f-b930-9025ae6202b3', node_type=, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, hash='d2f61ad5c414d7e0b68273550ae08d00f8931141e7666b3f86f68b0f81a6abdc'), : RelatedNodeInfo(node_id='a9c7fecd-4294-40f1-a3cd-4ac17d353690', node_type=, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, hash='d400a52be04e5618ab70268c1d968c31994c6dac8f5bbf42b0718b20a20a87d1'), : RelatedNodeInfo(node_id='5414fc88-0d20-42e0-ac85-c0657e5b2495', node_type=, metadata={}, hash='e2113e037176fee3ca0a39e438391443ddef7be5532d5af8ec3fac40179c5a22')}, text='I didn\\'t want to drop out of grad school, but how else was I going to get out? I remember when my friend Robert Morris got kicked out of Cornell for writing the internet worm of 1988, I was envious that he\\'d found such a spectacular way to get out of grad school.\\n\\nThen one day in April 1990 a crack appeared in the wall. I ran into professor Cheatham and he asked if I was far enough along to graduate that June. I didn\\'t have a word of my dissertation written, but in what must have been the quickest bit of thinking in my life, I decided to take a shot at writing one in the 5 weeks or so that remained before the deadline, reusing parts of On Lisp where I could, and I was able to respond, with no perceptible delay \"Yes, I think so. I\\'ll give you something to read in a few days.\"\\n\\nI picked applications of continuations as the topic. In retrospect I should have written about macros and embedded languages. There\\'s a whole world there that\\'s barely been explored. But all I wanted was to get out of grad school, and my rapidly written dissertation sufficed, just barely.\\n\\nMeanwhile I was applying to art schools. I applied to two: RISD in the US, and the Accademia di Belli Arti in Florence, which, because it was the oldest art school, I imagined would be good. RISD accepted me, and I never heard back from the Accademia, so off to Providence I went.\\n\\nI\\'d applied for the BFA program at RISD, which meant in effect that I had to go to college again. This was not as strange as it sounds, because I was only 25, and art schools are full of people of different ages. RISD counted me as a transfer sophomore and said I had to do the foundation that summer. The foundation means the classes that everyone has to take in fundamental subjects like drawing, color, and design.\\n\\nToward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they\\'d sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I\\'d done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian.\\n\\nOnly stranieri (foreigners) had to take this entrance exam. In retrospect it may well have been a way of excluding them, because there were so many stranieri attracted by the idea of studying art in Florence that the Italian students would otherwise have been outnumbered. I was in decent shape at painting and drawing from the RISD foundation that summer, but I still don\\'t know how I managed to pass the written exam. I remember that I answered the essay question by writing about Cezanne, and that I cranked up the intellectual level as high as I could to make the most of my limited vocabulary. [2]\\n\\nI\\'m only up to age 25 and already there are such conspicuous patterns. Here I was, yet again about to attend some august institution in the hopes of learning about some prestigious subject, and yet again about to be disappointed. The students and faculty in the painting department at the Accademia were the nicest people you could imagine, but they had long since arrived at an arrangement whereby the students wouldn\\'t require the faculty to teach anything, and in return the faculty wouldn\\'t require the students to learn anything. And at the same time all involved would adhere outwardly to the conventions of a 19th century atelier. We actually had one of those little stoves, fed with kindling, that you see in 19th century studio paintings, and a nude model sitting as close to it as possible without getting burned. Except hardly anyone else painted her besides me. The rest of the students spent their time chatting or occasionally trying to imitate things they\\'d seen in American art magazines.\\n\\nOur model turned out to live just down the street from me. She made a living from a combination of modelling and making fakes for a local antique dealer. She\\'d copy an obscure old painting out of a book, and then he\\'d take the copy and maltreat it to make it look old. [3]\\n\\nWhile I was a student at the Accademia I started painting still lives in my bedroom at night. These paintings were tiny, because the room was, and because I painted them on leftover scraps of canvas, which was all I could afford at the time.', start_char_idx=10764, end_char_idx=15165, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n'), score=0.8070322562070888)], metadata={'c9202a57-b440-4d86-9a5e-795ada63ba29': {'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, '8222d396-1cd5-4c5f-8e15-f44be1213d6a': {'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}})" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "response = query_engine.query(\"What did the author do growing up?\")\n", "response" From 6a770ad1c4b22eba8ade9c2212251fb9114ae509 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Wed, 21 Feb 2024 11:50:34 +0100 Subject: [PATCH 04/24] handler linting --- .../llama_index_handler.py | 328 +++++++++++------- 1 file changed, 197 insertions(+), 131 deletions(-) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index a4e928b..5261a52 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -18,9 +18,10 @@ global_stack_trace = ContextVar("trace", default=[BASE_TRACE_EVENT]) + class ArgillaCallbackHandler(BaseCallbackHandler): """Callback handler for Argilla. - + Args: dataset_name: The name of the dataset to log the events to. If the dataset does not exist, a new one will be created. @@ -31,12 +32,12 @@ class ArgillaCallbackHandler(BaseCallbackHandler): event_starts_to_ignore: A list of event types to ignore when they start. event_ends_to_ignore: A list of event types to ignore when they end. handlers: A list of handlers to run when an event starts or ends. - + Raises: ImportError: If the `argilla` Python package is not installed or the one installed is not compatible ConnectionError: If the connection to Argilla fails FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails - + Example: >>> from argilla_llama_index import ArgillaCallbackHandler >>> from llama_index import VectorStoreIndex, ServiceContext, SimpleDirectoryReader @@ -66,7 +67,7 @@ def __init__( handlers: Optional[List[BaseCallbackHandler]] = None, ) -> None: """Initialize the Argilla callback handler. - + Args: dataset_name: The name of the dataset to log the events to. If the dataset does not exist, a new one will be created. @@ -77,22 +78,23 @@ def __init__( event_starts_to_ignore: A list of event types to ignore when they start. event_ends_to_ignore: A list of event types to ignore when they end. handlers: A list of handlers to run when an event starts or ends. - + Raises: ImportError: If the `argilla` Python package is not installed or the one installed is not compatible ConnectionError: If the connection to Argilla fails FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails - + """ - + self.event_starts_to_ignore = event_starts_to_ignore or [] self.event_ends_to_ignore = event_ends_to_ignore or [] self.handlers = handlers or [] self.number_of_retrievals = number_of_retrievals - # Import Argilla + # Import Argilla try: import argilla as rg + self.ARGILLA_VERSION = rg.__version__ except ImportError: @@ -108,7 +110,7 @@ def __init__( "`ArgillaCallbackHandler` requires at least version 1.18.0. Please " "upgrade `argilla` with `pip install --upgrade argilla`." ) - + # API_URL and API_KEY # Show a warning message if Argilla will assume the default values will be used if api_url is None and os.getenv("ARGILLA_API_URL") is None: @@ -130,13 +132,10 @@ def __init__( ), ) api_key = DEFAULT_API_KEY - + # Connect to Argilla with the provided credentials, if applicable try: - rg.init( - api_key=api_key, - api_url=api_url - ) + rg.init(api_key=api_key, api_url=api_url) except Exception as e: raise ConnectionError( f"Could not connect to Argilla with exception: '{e}'.\n" @@ -144,7 +143,7 @@ def __init__( "the Argilla server is up and running. If the problem persists " f"please report it to {self.ISSUES_URL} as an `integration` issue." ) from e - + # Set the Argilla variables self.dataset_name = dataset_name self.workspace_name = workspace_name or rg.get_workspace() @@ -159,12 +158,31 @@ def __init__( self.is_new_dataset_created = False if number_of_retrievals > 0: - required_context_fields = self._add_context_fields(number_of_retrievals) - required_context_questions = self._add_context_questions(number_of_retrievals) - existing_fields = [field.to_local() for field in self.dataset.fields] - existing_questions = [question.to_local() for question in self.dataset.questions] + required_context_fields = self._add_context_fields( + number_of_retrievals + ) + required_context_questions = self._add_context_questions( + number_of_retrievals + ) + existing_fields = [ + field.to_local() for field in self.dataset.fields + ] + existing_questions = [ + question.to_local() for question in self.dataset.questions + ] # If the required fields and questions do not match with the existing ones, update the dataset and upload it again with "-updated" added to the name - if all(element in existing_fields for element in required_context_fields) == False or all(element in existing_questions for element in required_context_questions) == False: + if ( + all( + element in existing_fields + for element in required_context_fields + ) + == False + or all( + element in existing_questions + for element in required_context_questions + ) + == False + ): local_dataset = self.dataset.pull() fields_to_pop = [] @@ -175,7 +193,7 @@ def __init__( else: for index in fields_to_pop: local_dataset.fields.pop(index) - + questions_to_pop = [] for index, question in enumerate(local_dataset.questions): if question.name.startswith("rating_retrieved_document_"): @@ -189,7 +207,9 @@ def __init__( local_dataset.fields.append(field) for question in required_context_questions: local_dataset.questions.append(question) - self.dataset = local_dataset.push_to_argilla(self.dataset_name+"-updated") + self.dataset = local_dataset.push_to_argilla( + self.dataset_name + "-updated" + ) # If the dataset does not exist, create a new one with the given name else: @@ -197,8 +217,11 @@ def __init__( fields=[ rg.TextField(name="prompt", required=True), rg.TextField(name="response", required=False), - rg.TextField(name="time-details", title="Time Details", use_markdown=True) - ] + self._add_context_fields(number_of_retrievals), + rg.TextField( + name="time-details", title="Time Details", use_markdown=True + ), + ] + + self._add_context_fields(number_of_retrievals), questions=[ rg.RatingQuestion( name="response-rating", @@ -213,21 +236,22 @@ def __init__( description="What feedback do you have for the response?", required=False, ), - ] + self._add_context_questions(number_of_retrievals), - guidelines="You're asked to rate the quality of the response and provide feedback.", - allow_extra_metadata=True, + ] + + self._add_context_questions(number_of_retrievals), + guidelines="You're asked to rate the quality of the response and provide feedback.", + allow_extra_metadata=True, ) self.dataset = dataset.push_to_argilla(self.dataset_name) self.is_new_dataset_created = True warnings.warn( - ( - f"No dataset with the name {self.dataset_name} was found in workspace " - f"{self.workspace_name}. A new dataset with the name {self.dataset_name} " - "has been created with the question fields `prompt` and `response`" - "and the rating question `response-rating` with values 1-7 and text question" - " named `response-feedback`." - ), - ) + ( + f"No dataset with the name {self.dataset_name} was found in workspace " + f"{self.workspace_name}. A new dataset with the name {self.dataset_name} " + "has been created with the question fields `prompt` and `response`" + "and the rating question `response-rating` with values 1-7 and text question" + " named `response-feedback`." + ), + ) except Exception as e: raise FileNotFoundError( @@ -235,9 +259,15 @@ def __init__( f" If the problem persists please report it to {self.ISSUES_URL} " f"as an `integration` issue." ) from e - - supported_context_fields = [f"retrieved_document_{i+1}" for i in range(number_of_retrievals)] - supported_fields = ["prompt", "response", "time-details"] + supported_context_fields + + supported_context_fields = [ + f"retrieved_document_{i+1}" for i in range(number_of_retrievals) + ] + supported_fields = [ + "prompt", + "response", + "time-details", + ] + supported_context_fields if supported_fields != [field.name for field in self.dataset.fields]: raise ValueError( f"`FeedbackDataset` with name={self.dataset_name} in the workspace=" @@ -245,17 +275,14 @@ def __init__( f"`llama-index` integration. Supported fields are: {supported_fields}," f" and the current `FeedbackDataset` fields are {[field.name for field in self.dataset.fields]}." ) - + self.events_data: Dict[str, List[CBEvent]] = defaultdict(list) self.event_map_id_to_name = {} self._ignore_components_in_tree = ["templating"] self.components_to_log = set() self.event_ids_traced = set() - def _add_context_fields( - self, - number_of_retrievals: int - ) -> List: + def _add_context_fields(self, number_of_retrievals: int) -> List: """Create the context fields to be added to the dataset.""" context_fields = [ rg.TextField( @@ -267,29 +294,25 @@ def _add_context_fields( for doc in range(number_of_retrievals) ] return context_fields - - def _add_context_questions( - self, - number_of_retrievals: int - ) -> List: + + def _add_context_questions(self, number_of_retrievals: int) -> List: """Create the context questions to be added to the dataset.""" rating_questions = [ rg.RatingQuestion( name="rating_retrieved_document_" + str(doc + 1), - title="Rate the relevance of the Retrieved Document " + str(doc + 1) + " (if present)", + title="Rate the relevance of the Retrieved Document " + + str(doc + 1) + + " (if present)", values=list(range(1, 8)), # After https://github.com/argilla-io/argilla/issues/4523 is fixed, we can use the description - description=None, #"Rate the relevance of the retrieved document." + description=None, # "Rate the relevance of the retrieved document." required=False, ) for doc in range(number_of_retrievals) ] return rating_questions - def _create_root_and_other_nodes( - self, - trace_map: Dict[str, List[str]] - ) -> None: + def _create_root_and_other_nodes(self, trace_map: Dict[str, List[str]]) -> None: """Create the root node and the other nodes in the tree.""" self.root_node = self._get_event_name_by_id(trace_map["root"][0]) self.event_ids_traced = set(trace_map.keys()) - {"root"} @@ -297,17 +320,15 @@ def _create_root_and_other_nodes( for id in self.event_ids_traced: self.components_to_log.add(self._get_event_name_by_id(id)) - def _get_event_name_by_id( - self, - event_id: str - ) -> str: + def _get_event_name_by_id(self, event_id: str) -> str: """Get the name of the event by its id.""" return str(self.events_data[event_id][0].event_type).split(".")[1].lower() - + # TODO: If we have a component more than once, properties currently don't account for those after the first one and get overwritten + def _add_missing_metadata_properties( - self, - dataset: rg.FeedbackDataset, + self, + dataset: rg.FeedbackDataset, ) -> None: """Add missing metadata properties to the dataset.""" required_metadata_properties = [] @@ -317,15 +338,22 @@ def _add_missing_metadata_properties( metadata_name = "total_time" required_metadata_properties.append(metadata_name) - existing_metadata_properties = [property.name for property in dataset.metadata_properties] - missing_metadata_properties = [property for property in required_metadata_properties if property not in existing_metadata_properties] + existing_metadata_properties = [ + property.name for property in dataset.metadata_properties + ] + missing_metadata_properties = [ + property + for property in required_metadata_properties + if property not in existing_metadata_properties + ] for property in missing_metadata_properties: - title= " ".join([word.capitalize() for word in property.split('_')]) + title = " ".join([word.capitalize() for word in property.split("_")]) if title == "Llm Time": title = "LLM Time" dataset.add_metadata_property( - rg.FloatMetadataProperty(name=property, title=title)) + rg.FloatMetadataProperty(name=property, title=title) + ) if self.is_new_dataset_created == False: warnings.warn( ( @@ -334,14 +362,13 @@ def _add_missing_metadata_properties( f"Properties have been added to the dataset with " ), ) - + def _check_components_for_tree( - self, - tree_structure_dict: Dict[str, List[str]] + self, tree_structure_dict: Dict[str, List[str]] ) -> Dict[str, List[str]]: """ Check whether the components in the tree are in the components to log. - Removes components that are not in the components to log so that they are not shown in the tree. + Removes components that are not in the components to log so that they are not shown in the tree. """ final_components_in_tree = self.components_to_log.copy() final_components_in_tree.add("root") @@ -353,13 +380,15 @@ def _check_components_for_tree( del tree_structure_dict[key] for key, value in tree_structure_dict.items(): if isinstance(value, list): - tree_structure_dict[key] = [element for element in value if element.strip("0") in final_components_in_tree] + tree_structure_dict[key] = [ + element + for element in value + if element.strip("0") in final_components_in_tree + ] return tree_structure_dict - + def _get_events_map_with_names( - self, - events_data: Dict[str, List[CBEvent]], - trace_map: Dict[str, List[str]] + self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] ) -> Dict[str, List[str]]: """ Returns a dictionary where trace_map is mapped with the event names instead of the event ids. @@ -369,16 +398,19 @@ def _get_events_map_with_names( for event_id in self.event_ids_traced: event_name = str(events_data[event_id][0].event_type).split(".")[1].lower() while event_name in self.event_map_id_to_name.values(): - event_name = event_name + "0" + event_name = event_name + "0" self.event_map_id_to_name[event_id] = event_name - events_trace_map = {self.event_map_id_to_name.get(k, k): [self.event_map_id_to_name.get(v, v) for v in values] for k, values in trace_map.items()} + events_trace_map = { + self.event_map_id_to_name.get(k, k): [ + self.event_map_id_to_name.get(v, v) for v in values + ] + for k, values in trace_map.items() + } return events_trace_map - + def _extract_and_log_info( - self, - events_data: Dict[str, List[CBEvent]], - trace_map: Dict[str, List[str]] + self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] ) -> None: """ Main function that extracts the information from the events and logs it to Argilla. @@ -398,9 +430,13 @@ def _extract_and_log_info( query_start_time = event.time # Event end event = events_data[root_node[0]][1] - data_to_log["response"] = event.payload.get(EventPayload.RESPONSE).response + data_to_log["response"] = event.payload.get( + EventPayload.RESPONSE + ).response query_end_time = event.time - data_to_log["agent_step_time"] = _get_time_diff(query_start_time, query_end_time) + data_to_log["agent_step_time"] = _get_time_diff( + query_start_time, query_end_time + ) elif self.root_node == "query": # Event start @@ -409,13 +445,17 @@ def _extract_and_log_info( query_start_time = event.time # Event end event = events_data[root_node[0]][1] - data_to_log["response"] = event.payload.get(EventPayload.RESPONSE).response + data_to_log["response"] = event.payload.get( + EventPayload.RESPONSE + ).response query_end_time = event.time - data_to_log["query_time"] = _get_time_diff(query_start_time, query_end_time) - + data_to_log["query_time"] = _get_time_diff( + query_start_time, query_end_time + ) + else: return - + # Create logging data for the rest of the components self.event_ids_traced.remove(root_node[0]) @@ -436,18 +476,34 @@ def _extract_and_log_info( data_to_log[f"{event_name}_time"] = _calc_time(events_data, id) if event_name_reduced == "llm": - data_to_log[f"{event_name}_system_prompt"] = events_data[id][0].payload.get(EventPayload.MESSAGES)[0].content - data_to_log[f"{event_name}_model_name"] = events_data[id][0].payload.get(EventPayload.SERIALIZED)["model"] + data_to_log[f"{event_name}_system_prompt"] = ( + events_data[id][0].payload.get(EventPayload.MESSAGES)[0].content + ) + data_to_log[f"{event_name}_model_name"] = events_data[id][ + 0 + ].payload.get(EventPayload.SERIALIZED)["model"] retrieved_document_counter = 1 if event_name_reduced == "retrieve": - for retrieval_node in events_data[id][1].payload.get(EventPayload.NODES): + for retrieval_node in events_data[id][1].payload.get( + EventPayload.NODES + ): retrieve_dict = retrieval_node.to_dict() - retrieval_metadata[f"{event_name}_document_{retrieved_document_counter}_score"] = retrieval_node.score - retrieval_metadata[f"{event_name}_document_{retrieved_document_counter}_filename"] = retrieve_dict["node"]["metadata"]["file_name"] - retrieval_metadata[f"{event_name}_document_{retrieved_document_counter}_text"] = retrieve_dict["node"]["text"] - retrieval_metadata[f"{event_name}_document_{retrieved_document_counter}_start_character"] = retrieve_dict["node"]["start_char_idx"] - retrieval_metadata[f"{event_name}_document_{retrieved_document_counter}_end_character"] = retrieve_dict["node"]["end_char_idx"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_score" + ] = retrieval_node.score + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_filename" + ] = retrieve_dict["node"]["metadata"]["file_name"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_text" + ] = retrieve_dict["node"]["text"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_start_character" + ] = retrieve_dict["node"]["start_char_idx"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_end_character" + ] = retrieve_dict["node"]["end_char_idx"] retrieved_document_counter += 1 if retrieved_document_counter > self.number_of_retrievals: break @@ -461,59 +517,75 @@ def _extract_and_log_info( metadata_to_log[keys] = data_to_log[keys] elif keys != "query" and keys != "response": metadata_to_log[keys] = data_to_log[keys] - + if len(number_of_components_used) > 0: for key, value in number_of_components_used.items(): metadata_to_log[f"number_of_{key}_used"] = value + 1 - + metadata_to_log.update(retrieval_metadata) - + tree_structure = self._create_tree_structure(events_trace_map, data_to_log) tree = self._create_svg(tree_structure) fields = { - "prompt": data_to_log["query"], + "prompt": data_to_log["query"], "response": data_to_log["response"], - "time-details": tree + "time-details": tree, } if self.number_of_retrievals > 0: for key, value in list(retrieval_metadata.items()): if key.endswith("_text"): - fields[f"retrieved_document_{key[-6]}"] = f"DOCUMENT SCORE: {retrieval_metadata[key[:-5]+'_score']}\n\n" + value + fields[f"retrieved_document_{key[-6]}"] = ( + f"DOCUMENT SCORE: {retrieval_metadata[key[:-5]+'_score']}\n\n" + + value + ) del metadata_to_log[key] self.dataset.add_records( records=[ - { - "fields": fields, - "metadata": metadata_to_log - }, + {"fields": fields, "metadata": metadata_to_log}, ] ) - + def _create_tree_structure( - self, - events_trace_map: Dict[str, List[str]], - data_to_log: Dict[str, Any] + self, events_trace_map: Dict[str, List[str]], data_to_log: Dict[str, Any] ) -> List: """Create the tree data to be converted to an SVG.""" events_trace_map = self._check_components_for_tree(events_trace_map) data = [] - data.append((0, 0, self.root_node.strip("0").upper(), data_to_log[f"{self.root_node}_time"])) + data.append( + ( + 0, + 0, + self.root_node.strip("0").upper(), + data_to_log[f"{self.root_node}_time"], + ) + ) current_row = 1 for root_child in events_trace_map[self.root_node]: - data.append((current_row, 1, root_child.strip("0").upper(), data_to_log[f"{root_child}_time"])) + data.append( + ( + current_row, + 1, + root_child.strip("0").upper(), + data_to_log[f"{root_child}_time"], + ) + ) current_row += 1 for child in events_trace_map[root_child]: - data.append((current_row, 2, child.strip("0").upper(), data_to_log[f"{child}_time"])) + data.append( + ( + current_row, + 2, + child.strip("0").upper(), + data_to_log[f"{child}_time"], + ) + ) current_row += 1 return data - - def _create_svg( - self, - data: List - ) -> str: + + def _create_svg(self, data: List) -> str: # changing only the box height changes all other values as well # others can be adjusted individually if needed box_height = 47 @@ -525,7 +597,7 @@ def _create_svg( text_centering = box_height * 0.6341 node_name_indent = box_height * 0.35 time_indent = box_height * 7.15 - + body = "" for each in data: row, indent, node_name, node_time = each @@ -537,7 +609,9 @@ def _create_svg( """ body += body_raw - base = base =f""" + base = ( + base + ) = f""" {body} @@ -546,10 +620,7 @@ def _create_svg( base = base.strip() return base - def start_trace( - self, - trace_id: Optional[str] = None - ) -> None: + def start_trace(self, trace_id: Optional[str] = None) -> None: """Launch a trace.""" self._trace_map = defaultdict(list) self._cur_trace_id = trace_id @@ -592,10 +663,8 @@ def on_event_end( event = CBEvent(event_type, payload=payload, id_=event_id) self.events_data[event_id].append(event) -def _get_time_diff( - event_1_time_str: str, - event_2_time_str: str -) -> float: + +def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: """Get the time difference between two events.""" time_format = "%m/%d/%Y, %H:%M:%S.%f" @@ -604,12 +673,9 @@ def _get_time_diff( return round((event_2_time - event_1_time).total_seconds(), 4) -def _calc_time( - events_data: Dict[str, List[CBEvent]], - id: str -) -> float: + +def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: """Calculate the time difference between the start and end of an event using the events_data.""" start_time = events_data[id][0].time end_time = events_data[id][1].time return _get_time_diff(start_time, end_time) - \ No newline at end of file From c6fb6d8c1ad2e77ab4ddc96f7cf9d8875caa50ce Mon Sep 17 00:00:00 2001 From: ignacioct Date: Mon, 26 Feb 2024 11:14:51 +0100 Subject: [PATCH 05/24] fix new version to 1.0 --- src/argilla_llama_index/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/argilla_llama_index/__init__.py b/src/argilla_llama_index/__init__.py index 43488e3..4dc2a4a 100644 --- a/src/argilla_llama_index/__init__.py +++ b/src/argilla_llama_index/__init__.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.0.1-alpha" +__version__ = "1.0.0" from argilla_llama_index.llama_index_handler import ArgillaCallbackHandler From 24b089c1623368455bed190920db7a0d3d799094 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Mon, 26 Feb 2024 12:19:50 +0100 Subject: [PATCH 06/24] now requiring 0.10 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ea2e85f..893ea52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ classifiers = [ ] dependencies = [ "argilla >= 1.18.0", - "llama-index >= 0.9.32", + "llama-index >= 0.10.0", "packaging >= 23.2", "typing-extensions >= 4.3.0" ] From c21edd83361fa481b6595c6aa1e63ec60727c045 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Mon, 26 Feb 2024 12:22:25 +0100 Subject: [PATCH 07/24] started changes, legacy version renamed and used for code rebasing --- .../legacy_llama_index_handler.py | 694 ++++++++++++++++++ .../llama_index_handler.py | 621 +++------------- 2 files changed, 776 insertions(+), 539 deletions(-) create mode 100644 src/argilla_llama_index/legacy_llama_index_handler.py diff --git a/src/argilla_llama_index/legacy_llama_index_handler.py b/src/argilla_llama_index/legacy_llama_index_handler.py new file mode 100644 index 0000000..645ae58 --- /dev/null +++ b/src/argilla_llama_index/legacy_llama_index_handler.py @@ -0,0 +1,694 @@ +from argilla._constants import DEFAULT_API_KEY, DEFAULT_API_URL +import argilla as rg +from typing import Any, Dict, List, Optional +from packaging.version import parse +import warnings +import os +from datetime import datetime +from collections import defaultdict +from contextvars import ContextVar + +from llama_index.core.callbacks.base_handler import BaseCallbackHandler +from llama_index.core.callbacks.schema import ( + BASE_TRACE_EVENT, + CBEventType, + EventPayload, + CBEvent, +) + +global_stack_trace = ContextVar("trace", default=[BASE_TRACE_EVENT]) + + +class ArgillaCallbackHandler(BaseCallbackHandler): + """Callback handler for Argilla. + + Args: + dataset_name: The name of the dataset to log the events to. If the dataset does not exist, + a new one will be created. + number_of_retrievals: The number of retrieved documents to log. + workspace_name: The name of the workspace to log the events to. + api_url: The URL of the Argilla server. + api_key: The API key to use to connect to Argilla. + event_starts_to_ignore: A list of event types to ignore when they start. + event_ends_to_ignore: A list of event types to ignore when they end. + handlers: A list of handlers to run when an event starts or ends. + + Raises: + ImportError: If the `argilla` Python package is not installed or the one installed is not compatible + ConnectionError: If the connection to Argilla fails + FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails + + Example: + >>> from argilla_llama_index import ArgillaCallbackHandler + >>> from llama_index import VectorStoreIndex, ServiceContext, SimpleDirectoryReader + >>> from llama_index.llms import OpenAI + >>> from llama_index import set_global_handler + >>> set_global_handler("argilla", dataset_name="query_model") + >>> llm = OpenAI(model="gpt-3.5-turbo", temperature=0.8) + >>> service_context = ServiceContext.from_defaults(llm=llm) + >>> docs = SimpleDirectoryReader("data").load_data() + >>> index = VectorStoreIndex.from_documents(docs, service_context=service_context) + >>> query_engine = index.as_query_engine() + >>> response = query_engine.query("What did the author do growing up dude?") + """ + + REPO_URL: str = "https://github.com/argilla-io/argilla" + ISSUES_URL: str = f"{REPO_URL}/issues" + + def __init__( + self, + dataset_name: str, + number_of_retrievals: int = 0, + workspace_name: Optional[str] = None, + api_url: Optional[str] = None, + api_key: Optional[str] = None, + event_starts_to_ignore: Optional[List[CBEventType]] = None, + event_ends_to_ignore: Optional[List[CBEventType]] = None, + handlers: Optional[List[BaseCallbackHandler]] = None, + ) -> None: + """Initialize the Argilla callback handler. + + Args: + dataset_name: The name of the dataset to log the events to. If the dataset does not exist, + a new one will be created. + number_of_retrievals: The number of retrieved documents to log. + workspace_name: The name of the workspace to log the events to. + api_url: The URL of the Argilla server. + api_key: The API key to use to connect to Argilla. + event_starts_to_ignore: A list of event types to ignore when they start. + event_ends_to_ignore: A list of event types to ignore when they end. + handlers: A list of handlers to run when an event starts or ends. + + Raises: + ImportError: If the `argilla` Python package is not installed or the one installed is not compatible + ConnectionError: If the connection to Argilla fails + FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails + + """ + + self.event_starts_to_ignore = event_starts_to_ignore or [] + self.event_ends_to_ignore = event_ends_to_ignore or [] + self.handlers = handlers or [] + self.number_of_retrievals = number_of_retrievals + + # Import Argilla + try: + import argilla as rg + + self.ARGILLA_VERSION = rg.__version__ + + except ImportError: + raise ImportError( + "To use the Argilla callback manager you need to have the `argilla` " + "Python package installed. Please install it with `pip install argilla`" + ) + + # Check whether the Argilla version is compatible + if parse(self.ARGILLA_VERSION) < parse("1.18.0"): + raise ImportError( + f"The installed `argilla` version is {self.ARGILLA_VERSION} but " + "`ArgillaCallbackHandler` requires at least version 1.18.0. Please " + "upgrade `argilla` with `pip install --upgrade argilla`." + ) + + # API_URL and API_KEY + # Show a warning message if Argilla will assume the default values will be used + if api_url is None and os.getenv("ARGILLA_API_URL") is None: + warnings.warn( + ( + "Since `api_url` is None, and the env var `ARGILLA_API_URL` is not" + f" set, it will default to `{DEFAULT_API_URL}`, which is the" + " default API URL in Argilla Quickstart." + ), + ) + api_url = DEFAULT_API_URL + + if api_key is None and os.getenv("ARGILLA_API_KEY") is None: + warnings.warn( + ( + "Since `api_key` is None, and the env var `ARGILLA_API_KEY` is not" + f" set, it will default to `{DEFAULT_API_KEY}`, which is the" + " default API key in Argilla Quickstart." + ), + ) + api_key = DEFAULT_API_KEY + + # Connect to Argilla with the provided credentials, if applicable + try: + rg.init(api_key=api_key, api_url=api_url) + except Exception as e: + raise ConnectionError( + f"Could not connect to Argilla with exception: '{e}'.\n" + "Please check your `api_key` and `api_url`, and make sure that " + "the Argilla server is up and running. If the problem persists " + f"please report it to {self.ISSUES_URL} as an `integration` issue." + ) from e + + # Set the Argilla variables + self.dataset_name = dataset_name + self.workspace_name = workspace_name or rg.get_workspace() + + # Retrieve the `FeedbackDataset` from Argilla + try: + if self.dataset_name in [ds.name for ds in rg.FeedbackDataset.list()]: + self.dataset = rg.FeedbackDataset.from_argilla( + name=self.dataset_name, + workspace=self.workspace_name, + ) + self.is_new_dataset_created = False + + if number_of_retrievals > 0: + required_context_fields = self._add_context_fields( + number_of_retrievals + ) + required_context_questions = self._add_context_questions( + number_of_retrievals + ) + existing_fields = [ + field.to_local() for field in self.dataset.fields + ] + existing_questions = [ + question.to_local() for question in self.dataset.questions + ] + # If the required fields and questions do not match with the existing ones, update the dataset and upload it again with "-updated" added to the name + if ( + all( + element in existing_fields + for element in required_context_fields + ) + == False + or all( + element in existing_questions + for element in required_context_questions + ) + == False + ): + local_dataset = self.dataset.pull() + + fields_to_pop = [] + for index, field in enumerate(local_dataset.fields): + if field.name.startswith("retrieved_document_"): + fields_to_pop.append(index) + fields_to_pop.sort(reverse=True) + else: + for index in fields_to_pop: + local_dataset.fields.pop(index) + + questions_to_pop = [] + for index, question in enumerate(local_dataset.questions): + if question.name.startswith("rating_retrieved_document_"): + questions_to_pop.append(index) + questions_to_pop.sort(reverse=True) + else: + for index in questions_to_pop: + local_dataset.questions.pop(index) + + for field in required_context_fields: + local_dataset.fields.append(field) + for question in required_context_questions: + local_dataset.questions.append(question) + self.dataset = local_dataset.push_to_argilla( + self.dataset_name + "-updated" + ) + + # If the dataset does not exist, create a new one with the given name + else: + dataset = rg.FeedbackDataset( + fields=[ + rg.TextField(name="prompt", required=True), + rg.TextField(name="response", required=False), + rg.TextField( + name="time-details", title="Time Details", use_markdown=True + ), + ] + + self._add_context_fields(number_of_retrievals), + questions=[ + rg.RatingQuestion( + name="response-rating", + title="Rating for the response", + description="How would you rate the quality of the response?", + values=[1, 2, 3, 4, 5, 6, 7], + required=True, + ), + rg.TextQuestion( + name="response-feedback", + title="Feedback for the response", + description="What feedback do you have for the response?", + required=False, + ), + ] + + self._add_context_questions(number_of_retrievals), + guidelines="You're asked to rate the quality of the response and provide feedback.", + allow_extra_metadata=True, + ) + self.dataset = dataset.push_to_argilla(self.dataset_name) + self.is_new_dataset_created = True + warnings.warn( + ( + f"No dataset with the name {self.dataset_name} was found in workspace " + f"{self.workspace_name}. A new dataset with the name {self.dataset_name} " + "has been created with the question fields `prompt` and `response`" + "and the rating question `response-rating` with values 1-7 and text question" + " named `response-feedback`." + ), + ) + + except Exception as e: + raise FileNotFoundError( + f"`FeedbackDataset` retrieval and creation both failed with exception `{e}`." + f" If the problem persists please report it to {self.ISSUES_URL} " + f"as an `integration` issue." + ) from e + + supported_context_fields = [ + f"retrieved_document_{i+1}" for i in range(number_of_retrievals) + ] + supported_fields = [ + "prompt", + "response", + "time-details", + ] + supported_context_fields + if supported_fields != [field.name for field in self.dataset.fields]: + raise ValueError( + f"`FeedbackDataset` with name={self.dataset_name} in the workspace=" + f"{self.workspace_name} had fields that are not supported yet for the" + f"`llama-index` integration. Supported fields are: {supported_fields}," + f" and the current `FeedbackDataset` fields are {[field.name for field in self.dataset.fields]}." + ) + + self.events_data: Dict[str, List[CBEvent]] = defaultdict(list) + self.event_map_id_to_name = {} + self._ignore_components_in_tree = ["templating"] + self.components_to_log = set() + self.event_ids_traced = set() + + def _add_context_fields(self, number_of_retrievals: int) -> List: + """Create the context fields to be added to the dataset.""" + context_fields = [ + rg.TextField( + name="retrieved_document_" + str(doc + 1), + title="Retrieved Document " + str(doc + 1), + use_markdown=True, + required=False, + ) + for doc in range(number_of_retrievals) + ] + return context_fields + + def _add_context_questions(self, number_of_retrievals: int) -> List: + """Create the context questions to be added to the dataset.""" + rating_questions = [ + rg.RatingQuestion( + name="rating_retrieved_document_" + str(doc + 1), + title="Rate the relevance of the Retrieved Document " + + str(doc + 1) + + " (if present)", + values=list(range(1, 8)), + # After https://github.com/argilla-io/argilla/issues/4523 is fixed, we can use the description + description=None, # "Rate the relevance of the retrieved document." + required=False, + ) + for doc in range(number_of_retrievals) + ] + return rating_questions + + def _create_root_and_other_nodes(self, trace_map: Dict[str, List[str]]) -> None: + """Create the root node and the other nodes in the tree.""" + self.root_node = self._get_event_name_by_id(trace_map["root"][0]) + self.event_ids_traced = set(trace_map.keys()) - {"root"} + print(trace_map) + self.event_ids_traced.update(*trace_map.values()) + for id in self.event_ids_traced: + self.components_to_log.add(self._get_event_name_by_id(id)) + + def _get_event_name_by_id(self, event_id: str) -> str: + """Get the name of the event by its id.""" + return str(self.events_data[event_id][0].event_type).split(".")[1].lower() + + # TODO: If we have a component more than once, properties currently don't account for those after the first one and get overwritten + + def _add_missing_metadata_properties( + self, + dataset: rg.FeedbackDataset, + ) -> None: + """Add missing metadata properties to the dataset.""" + required_metadata_properties = [] + for property in self.components_to_log: + metadata_name = f"{property}_time" + if property == self.root_node: + metadata_name = "total_time" + required_metadata_properties.append(metadata_name) + + existing_metadata_properties = [ + property.name for property in dataset.metadata_properties + ] + missing_metadata_properties = [ + property + for property in required_metadata_properties + if property not in existing_metadata_properties + ] + + for property in missing_metadata_properties: + title = " ".join([word.capitalize() for word in property.split("_")]) + if title == "Llm Time": + title = "LLM Time" + dataset.add_metadata_property( + rg.FloatMetadataProperty(name=property, title=title) + ) + if self.is_new_dataset_created == False: + warnings.warn( + ( + f"The dataset given was missing some required metadata properties. " + f"Missing properties were {missing_metadata_properties}. " + f"Properties have been added to the dataset with " + ), + ) + + def _check_components_for_tree( + self, tree_structure_dict: Dict[str, List[str]] + ) -> Dict[str, List[str]]: + """ + Check whether the components in the tree are in the components to log. + Removes components that are not in the components to log so that they are not shown in the tree. + """ + final_components_in_tree = self.components_to_log.copy() + final_components_in_tree.add("root") + for component in self._ignore_components_in_tree: + if component in final_components_in_tree: + final_components_in_tree.remove(component) + for key in list(tree_structure_dict.keys()): + if key.strip("0") not in final_components_in_tree: + del tree_structure_dict[key] + for key, value in tree_structure_dict.items(): + if isinstance(value, list): + tree_structure_dict[key] = [ + element + for element in value + if element.strip("0") in final_components_in_tree + ] + return tree_structure_dict + + def _get_events_map_with_names( + self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] + ) -> Dict[str, List[str]]: + """ + Returns a dictionary where trace_map is mapped with the event names instead of the event ids. + Also returns a set of the event ids that were traced. + """ + self.event_map_id_to_name = {} + for event_id in self.event_ids_traced: + event_name = str(events_data[event_id][0].event_type).split(".")[1].lower() + while event_name in self.event_map_id_to_name.values(): + event_name = event_name + "0" + self.event_map_id_to_name[event_id] = event_name + events_trace_map = { + self.event_map_id_to_name.get(k, k): [ + self.event_map_id_to_name.get(v, v) for v in values + ] + for k, values in trace_map.items() + } + + print("Events trace map with names:") + print(events_trace_map) + + return events_trace_map + + def _extract_and_log_info( + self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] + ) -> None: + """ + Main function that extracts the information from the events and logs it to Argilla. + We currently log data if the root node is either "agent_step" or "query". + Otherwise, we do not log anything. + If we want to account for more root nodes, we just need to add them to the if statement. + """ + print(f"Events data:") + for key, value in events_data.items(): + print(f"{key}: {value}") + print(f"Trace map {trace_map}") + events_trace_map = self._get_events_map_with_names(events_data, trace_map) + root_node = trace_map["root"] + data_to_log = {} + + + if len(root_node) == 1: + + # Create logging data for the root node + if self.root_node == "agent_step": + # Event start + event = events_data[root_node[0]][0] + data_to_log["query"] = event.payload.get(EventPayload.MESSAGES)[0] + query_start_time = event.time + # Event end + event = events_data[root_node[0]][1] + data_to_log["response"] = event.payload.get( + EventPayload.RESPONSE + ).response + query_end_time = event.time + data_to_log["agent_step_time"] = _get_time_diff( + query_start_time, query_end_time + ) + + elif self.root_node == "query": + # Event start + event = events_data[root_node[0]][0] + data_to_log["query"] = event.payload.get(EventPayload.QUERY_STR) + query_start_time = event.time + # Event end + event = events_data[root_node[0]][1] + data_to_log["response"] = event.payload.get( + EventPayload.RESPONSE + ).response + query_end_time = event.time + data_to_log["query_time"] = _get_time_diff( + query_start_time, query_end_time + ) + + else: + return + + # Create logging data for the rest of the components + self.event_ids_traced.remove(root_node[0]) + number_of_components_used = defaultdict(int) + components_to_log_without_root_node = self.components_to_log.copy() + components_to_log_without_root_node.remove(self.root_node) + retrieval_metadata = {} + for id in self.event_ids_traced: + event_name = self.event_map_id_to_name[id] + if event_name.endswith("0"): + event_name_reduced = event_name.strip("0") + number_of_components_used[event_name_reduced] += 1 + else: + event_name_reduced = event_name + + for component in components_to_log_without_root_node: + if event_name_reduced == component: + data_to_log[f"{event_name}_time"] = _calc_time(events_data, id) + + if event_name_reduced == "llm": + data_to_log[f"{event_name}_system_prompt"] = ( + events_data[id][0].payload.get(EventPayload.MESSAGES)[0].content + ) + data_to_log[f"{event_name}_model_name"] = events_data[id][ + 0 + ].payload.get(EventPayload.SERIALIZED)["model"] + + retrieved_document_counter = 1 + if event_name_reduced == "retrieve": + for retrieval_node in events_data[id][1].payload.get( + EventPayload.NODES + ): + retrieve_dict = retrieval_node.to_dict() + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_score" + ] = retrieval_node.score + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_filename" + ] = retrieve_dict["node"]["metadata"]["file_name"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_text" + ] = retrieve_dict["node"]["text"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_start_character" + ] = retrieve_dict["node"]["start_char_idx"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_end_character" + ] = retrieve_dict["node"]["end_char_idx"] + retrieved_document_counter += 1 + if retrieved_document_counter > self.number_of_retrievals: + break + + metadata_to_log = {} + + for keys in data_to_log.keys(): + if keys == "query_time" or keys == "agent_step_time": + metadata_to_log["total_time"] = data_to_log[keys] + elif keys.endswith("_time"): + metadata_to_log[keys] = data_to_log[keys] + elif keys != "query" and keys != "response": + metadata_to_log[keys] = data_to_log[keys] + + if len(number_of_components_used) > 0: + for key, value in number_of_components_used.items(): + metadata_to_log[f"number_of_{key}_used"] = value + 1 + + metadata_to_log.update(retrieval_metadata) + + tree_structure = self._create_tree_structure(events_trace_map, data_to_log) + tree = self._create_svg(tree_structure) + + fields = { + "prompt": data_to_log["query"], + "response": data_to_log["response"], + "time-details": tree, + } + + if self.number_of_retrievals > 0: + for key, value in list(retrieval_metadata.items()): + if key.endswith("_text"): + fields[f"retrieved_document_{key[-6]}"] = ( + f"DOCUMENT SCORE: {retrieval_metadata[key[:-5]+'_score']}\n\n" + + value + ) + del metadata_to_log[key] + + self.dataset.add_records( + records=[ + {"fields": fields, "metadata": metadata_to_log}, + ] + ) + + def _create_tree_structure( + self, events_trace_map: Dict[str, List[str]], data_to_log: Dict[str, Any] + ) -> List: + """Create the tree data to be converted to an SVG.""" + events_trace_map = self._check_components_for_tree(events_trace_map) + data = [] + data.append( + ( + 0, + 0, + self.root_node.strip("0").upper(), + data_to_log[f"{self.root_node}_time"], + ) + ) + current_row = 1 + for root_child in events_trace_map[self.root_node]: + data.append( + ( + current_row, + 1, + root_child.strip("0").upper(), + data_to_log[f"{root_child}_time"], + ) + ) + current_row += 1 + for child in events_trace_map[root_child]: + data.append( + ( + current_row, + 2, + child.strip("0").upper(), + data_to_log[f"{child}_time"], + ) + ) + current_row += 1 + return data + + def _create_svg(self, data: List) -> str: + # changing only the box height changes all other values as well + # others can be adjusted individually if needed + box_height = 47 + box_width = box_height * 8.65 + row_constant = box_height + 7 + indent_constant = 40 + font_size_node_name = box_height * 0.4188 + font_size_time = font_size_node_name - 4 + text_centering = box_height * 0.6341 + node_name_indent = box_height * 0.35 + time_indent = box_height * 7.15 + + body = "" + for each in data: + row, indent, node_name, node_time = each + body_raw = f""" + + +{node_name} +{node_time} + + """ + body += body_raw + base = ( + base + ) = f""" + + +{body} + + """ + base = base.strip() + return base + + def start_trace(self, trace_id: Optional[str] = None) -> None: + """Launch a trace.""" + self._trace_map = defaultdict(list) + self._cur_trace_id = trace_id + self._start_time = datetime.now() + + # Clearing the events and the components prior to running the query. They are usually events related to creating + # the docs and the index. + self.events_data.clear() + self.components_to_log.clear() + + def end_trace( + self, + trace_id: Optional[str] = None, + trace_map: Optional[Dict[str, List[str]]] = None, + ) -> None: + """End a trace.""" + self._trace_map = trace_map or defaultdict(list) + self._end_time = datetime.now() + self._create_root_and_other_nodes(trace_map) + self._add_missing_metadata_properties(self.dataset) + self._extract_and_log_info(self.events_data, trace_map) + + def on_event_start( + self, + event_type: CBEventType, + payload: Optional[Dict[str, Any]] = None, + event_id: Optional[str] = None, + parent_id: Optional[str] = None, + **kwargs: Any, + ) -> None: + """Run handlers when an event starts.""" + event = CBEvent(event_type, payload=payload, id_=event_id) + self.events_data[event_id].append(event) + + def on_event_end( + self, + event_type: CBEventType, + payload: Optional[Dict[str, Any]] = None, + event_id: Optional[str] = None, + **kwargs: Any, + ) -> None: + """Run handlers when an event ends.""" + event = CBEvent(event_type, payload=payload, id_=event_id) + self.events_data[event_id].append(event) + + +def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: + """Get the time difference between two events.""" + time_format = "%m/%d/%Y, %H:%M:%S.%f" + + event_1_time = datetime.strptime(event_1_time_str, time_format) + event_2_time = datetime.strptime(event_2_time_str, time_format) + + return round((event_2_time - event_1_time).total_seconds(), 4) + + +def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: + """Calculate the time difference between the start and end of an event using the events_data.""" + start_time = events_data[id][0].time + end_time = events_data[id][1].time + return _get_time_diff(start_time, end_time) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index 5261a52..11f1156 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -1,13 +1,10 @@ -from argilla._constants import DEFAULT_API_KEY, DEFAULT_API_URL -import argilla as rg -from typing import Any, Dict, List, Optional +from collections import defaultdict +import os from packaging.version import parse +from typing import Any, Dict, List, Optional import warnings -import os -from datetime import datetime -from collections import defaultdict -from contextvars import ContextVar +from argilla._constants import DEFAULT_API_KEY, DEFAULT_API_URL from llama_index.core.callbacks.base_handler import BaseCallbackHandler from llama_index.core.callbacks.schema import ( BASE_TRACE_EVENT, @@ -16,44 +13,16 @@ CBEvent, ) -global_stack_trace = ContextVar("trace", default=[BASE_TRACE_EVENT]) - class ArgillaCallbackHandler(BaseCallbackHandler): - """Callback handler for Argilla. - - Args: - dataset_name: The name of the dataset to log the events to. If the dataset does not exist, - a new one will be created. - number_of_retrievals: The number of retrieved documents to log. - workspace_name: The name of the workspace to log the events to. - api_url: The URL of the Argilla server. - api_key: The API key to use to connect to Argilla. - event_starts_to_ignore: A list of event types to ignore when they start. - event_ends_to_ignore: A list of event types to ignore when they end. - handlers: A list of handlers to run when an event starts or ends. - - Raises: - ImportError: If the `argilla` Python package is not installed or the one installed is not compatible - ConnectionError: If the connection to Argilla fails - FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails - - Example: - >>> from argilla_llama_index import ArgillaCallbackHandler - >>> from llama_index import VectorStoreIndex, ServiceContext, SimpleDirectoryReader - >>> from llama_index.llms import OpenAI - >>> from llama_index import set_global_handler - >>> set_global_handler("argilla", dataset_name="query_model") - >>> llm = OpenAI(model="gpt-3.5-turbo", temperature=0.8) - >>> service_context = ServiceContext.from_defaults(llm=llm) - >>> docs = SimpleDirectoryReader("data").load_data() - >>> index = VectorStoreIndex.from_documents(docs, service_context=service_context) - >>> query_engine = index.as_query_engine() - >>> response = query_engine.query("What did the author do growing up dude?") """ + Callback handler that logs predictions to Argilla. - REPO_URL: str = "https://github.com/argilla-io/argilla" - ISSUES_URL: str = f"{REPO_URL}/issues" + This handler automatically logs the predictions made with LlamaIndex to Argilla, + without the need to create a dataset and log the predictions manually. Events relevant + to the predictions are automatically logged to Argilla as well, including timestamps of + all the different steps of the retrieval and prediction process. + """ def __init__( self, @@ -66,25 +35,6 @@ def __init__( event_ends_to_ignore: Optional[List[CBEventType]] = None, handlers: Optional[List[BaseCallbackHandler]] = None, ) -> None: - """Initialize the Argilla callback handler. - - Args: - dataset_name: The name of the dataset to log the events to. If the dataset does not exist, - a new one will be created. - number_of_retrievals: The number of retrieved documents to log. - workspace_name: The name of the workspace to log the events to. - api_url: The URL of the Argilla server. - api_key: The API key to use to connect to Argilla. - event_starts_to_ignore: A list of event types to ignore when they start. - event_ends_to_ignore: A list of event types to ignore when they end. - handlers: A list of handlers to run when an event starts or ends. - - Raises: - ImportError: If the `argilla` Python package is not installed or the one installed is not compatible - ConnectionError: If the connection to Argilla fails - FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails - - """ self.event_starts_to_ignore = event_starts_to_ignore or [] self.event_ends_to_ignore = event_ends_to_ignore or [] @@ -94,7 +44,6 @@ def __init__( # Import Argilla try: import argilla as rg - self.ARGILLA_VERSION = rg.__version__ except ImportError: @@ -103,7 +52,6 @@ def __init__( "Python package installed. Please install it with `pip install argilla`" ) - # Check whether the Argilla version is compatible if parse(self.ARGILLA_VERSION) < parse("1.18.0"): raise ImportError( f"The installed `argilla` version is {self.ARGILLA_VERSION} but " @@ -111,12 +59,11 @@ def __init__( "upgrade `argilla` with `pip install --upgrade argilla`." ) - # API_URL and API_KEY - # Show a warning message if Argilla will assume the default values will be used + # Ensure the API URL and API key are set, or assume the default values if api_url is None and os.getenv("ARGILLA_API_URL") is None: warnings.warn( ( - "Since `api_url` is None, and the env var `ARGILLA_API_URL` is not" + "Since `api_url` is None, and the environment var `ARGILLA_API_URL` is not" f" set, it will default to `{DEFAULT_API_URL}`, which is the" " default API URL in Argilla Quickstart." ), @@ -126,14 +73,14 @@ def __init__( if api_key is None and os.getenv("ARGILLA_API_KEY") is None: warnings.warn( ( - "Since `api_key` is None, and the env var `ARGILLA_API_KEY` is not" + "Since `api_key` is None, and the environment var `ARGILLA_API_KEY` is not" f" set, it will default to `{DEFAULT_API_KEY}`, which is the" " default API key in Argilla Quickstart." ), ) api_key = DEFAULT_API_KEY - # Connect to Argilla with the provided credentials, if applicable + # Initialize the Argilla client try: rg.init(api_key=api_key, api_url=api_url) except Exception as e: @@ -148,71 +95,9 @@ def __init__( self.dataset_name = dataset_name self.workspace_name = workspace_name or rg.get_workspace() - # Retrieve the `FeedbackDataset` from Argilla + # Either create a new dataset or use an existing one, updating it if necessary try: - if self.dataset_name in [ds.name for ds in rg.FeedbackDataset.list()]: - self.dataset = rg.FeedbackDataset.from_argilla( - name=self.dataset_name, - workspace=self.workspace_name, - ) - self.is_new_dataset_created = False - - if number_of_retrievals > 0: - required_context_fields = self._add_context_fields( - number_of_retrievals - ) - required_context_questions = self._add_context_questions( - number_of_retrievals - ) - existing_fields = [ - field.to_local() for field in self.dataset.fields - ] - existing_questions = [ - question.to_local() for question in self.dataset.questions - ] - # If the required fields and questions do not match with the existing ones, update the dataset and upload it again with "-updated" added to the name - if ( - all( - element in existing_fields - for element in required_context_fields - ) - == False - or all( - element in existing_questions - for element in required_context_questions - ) - == False - ): - local_dataset = self.dataset.pull() - - fields_to_pop = [] - for index, field in enumerate(local_dataset.fields): - if field.name.startswith("retrieved_document_"): - fields_to_pop.append(index) - fields_to_pop.sort(reverse=True) - else: - for index in fields_to_pop: - local_dataset.fields.pop(index) - - questions_to_pop = [] - for index, question in enumerate(local_dataset.questions): - if question.name.startswith("rating_retrieved_document_"): - questions_to_pop.append(index) - questions_to_pop.sort(reverse=True) - else: - for index in questions_to_pop: - local_dataset.questions.pop(index) - - for field in required_context_fields: - local_dataset.fields.append(field) - for question in required_context_questions: - local_dataset.questions.append(question) - self.dataset = local_dataset.push_to_argilla( - self.dataset_name + "-updated" - ) - - # If the dataset does not exist, create a new one with the given name - else: + if self.dataset_name not in [ds.name for ds in rg.FeedbackDataset.list()]: dataset = rg.FeedbackDataset( fields=[ rg.TextField(name="prompt", required=True), @@ -241,17 +126,73 @@ def __init__( guidelines="You're asked to rate the quality of the response and provide feedback.", allow_extra_metadata=True, ) + self.dataset = dataset.push_to_argilla(self.dataset_name) - self.is_new_dataset_created = True - warnings.warn( - ( - f"No dataset with the name {self.dataset_name} was found in workspace " - f"{self.workspace_name}. A new dataset with the name {self.dataset_name} " - "has been created with the question fields `prompt` and `response`" - "and the rating question `response-rating` with values 1-7 and text question" - " named `response-feedback`." - ), - ) + else: + # Update the existing dataset. If the fields and questions do not match, the dataset will be updated using the + # -updated flag in the name. + if self.dataset_name in [ds.name for ds in rg.FeedbackDataset.list()]: + self.dataset = rg.FeedbackDataset.from_argilla( + name=self.dataset_name, + workspace=self.workspace_name, + ) + self.is_new_dataset_created = False + + if number_of_retrievals > 0: + required_context_fields = self._add_context_fields( + number_of_retrievals + ) + required_context_questions = self._add_context_questions( + number_of_retrievals + ) + existing_fields = [ + field.to_local() for field in self.dataset.fields + ] + existing_questions = [ + question.to_local() for question in self.dataset.questions + ] + # If the required fields and questions do not match with the existing ones, update the dataset and upload it again with "-updated" added to the name + if ( + all( + element in existing_fields + for element in required_context_fields + ) + == False + or all( + element in existing_questions + for element in required_context_questions + ) + == False + ): + local_dataset = self.dataset.pull() + + fields_to_pop = [] + for index, field in enumerate(local_dataset.fields): + if field.name.startswith("retrieved_document_"): + fields_to_pop.append(index) + fields_to_pop.sort(reverse=True) + else: + for index in fields_to_pop: + local_dataset.fields.pop(index) + + questions_to_pop = [] + for index, question in enumerate(local_dataset.questions): + if question.name.startswith( + "rating_retrieved_document_" + ): + questions_to_pop.append(index) + questions_to_pop.sort(reverse=True) + else: + for index in questions_to_pop: + local_dataset.questions.pop(index) + + for field in required_context_fields: + local_dataset.fields.append(field) + for question in required_context_questions: + local_dataset.questions.append(question) + self.dataset = local_dataset.push_to_argilla( + self.dataset_name + "-updated" + ) except Exception as e: raise FileNotFoundError( @@ -281,401 +222,3 @@ def __init__( self._ignore_components_in_tree = ["templating"] self.components_to_log = set() self.event_ids_traced = set() - - def _add_context_fields(self, number_of_retrievals: int) -> List: - """Create the context fields to be added to the dataset.""" - context_fields = [ - rg.TextField( - name="retrieved_document_" + str(doc + 1), - title="Retrieved Document " + str(doc + 1), - use_markdown=True, - required=False, - ) - for doc in range(number_of_retrievals) - ] - return context_fields - - def _add_context_questions(self, number_of_retrievals: int) -> List: - """Create the context questions to be added to the dataset.""" - rating_questions = [ - rg.RatingQuestion( - name="rating_retrieved_document_" + str(doc + 1), - title="Rate the relevance of the Retrieved Document " - + str(doc + 1) - + " (if present)", - values=list(range(1, 8)), - # After https://github.com/argilla-io/argilla/issues/4523 is fixed, we can use the description - description=None, # "Rate the relevance of the retrieved document." - required=False, - ) - for doc in range(number_of_retrievals) - ] - return rating_questions - - def _create_root_and_other_nodes(self, trace_map: Dict[str, List[str]]) -> None: - """Create the root node and the other nodes in the tree.""" - self.root_node = self._get_event_name_by_id(trace_map["root"][0]) - self.event_ids_traced = set(trace_map.keys()) - {"root"} - self.event_ids_traced.update(*trace_map.values()) - for id in self.event_ids_traced: - self.components_to_log.add(self._get_event_name_by_id(id)) - - def _get_event_name_by_id(self, event_id: str) -> str: - """Get the name of the event by its id.""" - return str(self.events_data[event_id][0].event_type).split(".")[1].lower() - - # TODO: If we have a component more than once, properties currently don't account for those after the first one and get overwritten - - def _add_missing_metadata_properties( - self, - dataset: rg.FeedbackDataset, - ) -> None: - """Add missing metadata properties to the dataset.""" - required_metadata_properties = [] - for property in self.components_to_log: - metadata_name = f"{property}_time" - if property == self.root_node: - metadata_name = "total_time" - required_metadata_properties.append(metadata_name) - - existing_metadata_properties = [ - property.name for property in dataset.metadata_properties - ] - missing_metadata_properties = [ - property - for property in required_metadata_properties - if property not in existing_metadata_properties - ] - - for property in missing_metadata_properties: - title = " ".join([word.capitalize() for word in property.split("_")]) - if title == "Llm Time": - title = "LLM Time" - dataset.add_metadata_property( - rg.FloatMetadataProperty(name=property, title=title) - ) - if self.is_new_dataset_created == False: - warnings.warn( - ( - f"The dataset given was missing some required metadata properties. " - f"Missing properties were {missing_metadata_properties}. " - f"Properties have been added to the dataset with " - ), - ) - - def _check_components_for_tree( - self, tree_structure_dict: Dict[str, List[str]] - ) -> Dict[str, List[str]]: - """ - Check whether the components in the tree are in the components to log. - Removes components that are not in the components to log so that they are not shown in the tree. - """ - final_components_in_tree = self.components_to_log.copy() - final_components_in_tree.add("root") - for component in self._ignore_components_in_tree: - if component in final_components_in_tree: - final_components_in_tree.remove(component) - for key in list(tree_structure_dict.keys()): - if key.strip("0") not in final_components_in_tree: - del tree_structure_dict[key] - for key, value in tree_structure_dict.items(): - if isinstance(value, list): - tree_structure_dict[key] = [ - element - for element in value - if element.strip("0") in final_components_in_tree - ] - return tree_structure_dict - - def _get_events_map_with_names( - self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] - ) -> Dict[str, List[str]]: - """ - Returns a dictionary where trace_map is mapped with the event names instead of the event ids. - Also returns a set of the event ids that were traced. - """ - self.event_map_id_to_name = {} - for event_id in self.event_ids_traced: - event_name = str(events_data[event_id][0].event_type).split(".")[1].lower() - while event_name in self.event_map_id_to_name.values(): - event_name = event_name + "0" - self.event_map_id_to_name[event_id] = event_name - events_trace_map = { - self.event_map_id_to_name.get(k, k): [ - self.event_map_id_to_name.get(v, v) for v in values - ] - for k, values in trace_map.items() - } - - return events_trace_map - - def _extract_and_log_info( - self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] - ) -> None: - """ - Main function that extracts the information from the events and logs it to Argilla. - We currently log data if the root node is either "agent_step" or "query". - Otherwise, we do not log anything. - If we want to account for more root nodes, we just need to add them to the if statement. - """ - events_trace_map = self._get_events_map_with_names(events_data, trace_map) - root_node = trace_map["root"] - data_to_log = {} - if len(root_node) == 1: - # Create logging data for the root node - if self.root_node == "agent_step": - # Event start - event = events_data[root_node[0]][0] - data_to_log["query"] = event.payload.get(EventPayload.MESSAGES)[0] - query_start_time = event.time - # Event end - event = events_data[root_node[0]][1] - data_to_log["response"] = event.payload.get( - EventPayload.RESPONSE - ).response - query_end_time = event.time - data_to_log["agent_step_time"] = _get_time_diff( - query_start_time, query_end_time - ) - - elif self.root_node == "query": - # Event start - event = events_data[root_node[0]][0] - data_to_log["query"] = event.payload.get(EventPayload.QUERY_STR) - query_start_time = event.time - # Event end - event = events_data[root_node[0]][1] - data_to_log["response"] = event.payload.get( - EventPayload.RESPONSE - ).response - query_end_time = event.time - data_to_log["query_time"] = _get_time_diff( - query_start_time, query_end_time - ) - - else: - return - - # Create logging data for the rest of the components - self.event_ids_traced.remove(root_node[0]) - - number_of_components_used = defaultdict(int) - components_to_log_without_root_node = self.components_to_log.copy() - components_to_log_without_root_node.remove(self.root_node) - retrieval_metadata = {} - for id in self.event_ids_traced: - event_name = self.event_map_id_to_name[id] - if event_name.endswith("0"): - event_name_reduced = event_name.strip("0") - number_of_components_used[event_name_reduced] += 1 - else: - event_name_reduced = event_name - - for component in components_to_log_without_root_node: - if event_name_reduced == component: - data_to_log[f"{event_name}_time"] = _calc_time(events_data, id) - - if event_name_reduced == "llm": - data_to_log[f"{event_name}_system_prompt"] = ( - events_data[id][0].payload.get(EventPayload.MESSAGES)[0].content - ) - data_to_log[f"{event_name}_model_name"] = events_data[id][ - 0 - ].payload.get(EventPayload.SERIALIZED)["model"] - - retrieved_document_counter = 1 - if event_name_reduced == "retrieve": - for retrieval_node in events_data[id][1].payload.get( - EventPayload.NODES - ): - retrieve_dict = retrieval_node.to_dict() - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_score" - ] = retrieval_node.score - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_filename" - ] = retrieve_dict["node"]["metadata"]["file_name"] - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_text" - ] = retrieve_dict["node"]["text"] - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_start_character" - ] = retrieve_dict["node"]["start_char_idx"] - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_end_character" - ] = retrieve_dict["node"]["end_char_idx"] - retrieved_document_counter += 1 - if retrieved_document_counter > self.number_of_retrievals: - break - - metadata_to_log = {} - - for keys in data_to_log.keys(): - if keys == "query_time" or keys == "agent_step_time": - metadata_to_log["total_time"] = data_to_log[keys] - elif keys.endswith("_time"): - metadata_to_log[keys] = data_to_log[keys] - elif keys != "query" and keys != "response": - metadata_to_log[keys] = data_to_log[keys] - - if len(number_of_components_used) > 0: - for key, value in number_of_components_used.items(): - metadata_to_log[f"number_of_{key}_used"] = value + 1 - - metadata_to_log.update(retrieval_metadata) - - tree_structure = self._create_tree_structure(events_trace_map, data_to_log) - tree = self._create_svg(tree_structure) - - fields = { - "prompt": data_to_log["query"], - "response": data_to_log["response"], - "time-details": tree, - } - - if self.number_of_retrievals > 0: - for key, value in list(retrieval_metadata.items()): - if key.endswith("_text"): - fields[f"retrieved_document_{key[-6]}"] = ( - f"DOCUMENT SCORE: {retrieval_metadata[key[:-5]+'_score']}\n\n" - + value - ) - del metadata_to_log[key] - - self.dataset.add_records( - records=[ - {"fields": fields, "metadata": metadata_to_log}, - ] - ) - - def _create_tree_structure( - self, events_trace_map: Dict[str, List[str]], data_to_log: Dict[str, Any] - ) -> List: - """Create the tree data to be converted to an SVG.""" - events_trace_map = self._check_components_for_tree(events_trace_map) - data = [] - data.append( - ( - 0, - 0, - self.root_node.strip("0").upper(), - data_to_log[f"{self.root_node}_time"], - ) - ) - current_row = 1 - for root_child in events_trace_map[self.root_node]: - data.append( - ( - current_row, - 1, - root_child.strip("0").upper(), - data_to_log[f"{root_child}_time"], - ) - ) - current_row += 1 - for child in events_trace_map[root_child]: - data.append( - ( - current_row, - 2, - child.strip("0").upper(), - data_to_log[f"{child}_time"], - ) - ) - current_row += 1 - return data - - def _create_svg(self, data: List) -> str: - # changing only the box height changes all other values as well - # others can be adjusted individually if needed - box_height = 47 - box_width = box_height * 8.65 - row_constant = box_height + 7 - indent_constant = 40 - font_size_node_name = box_height * 0.4188 - font_size_time = font_size_node_name - 4 - text_centering = box_height * 0.6341 - node_name_indent = box_height * 0.35 - time_indent = box_height * 7.15 - - body = "" - for each in data: - row, indent, node_name, node_time = each - body_raw = f""" - - -{node_name} -{node_time} - - """ - body += body_raw - base = ( - base - ) = f""" - - -{body} - - """ - base = base.strip() - return base - - def start_trace(self, trace_id: Optional[str] = None) -> None: - """Launch a trace.""" - self._trace_map = defaultdict(list) - self._cur_trace_id = trace_id - self._start_time = datetime.now() - self.events_data.clear() - self.components_to_log.clear() - - def end_trace( - self, - trace_id: Optional[str] = None, - trace_map: Optional[Dict[str, List[str]]] = None, - ) -> None: - """End a trace.""" - self._trace_map = trace_map or defaultdict(list) - self._end_time = datetime.now() - self._create_root_and_other_nodes(trace_map) - self._add_missing_metadata_properties(self.dataset) - self._extract_and_log_info(self.events_data, trace_map) - - def on_event_start( - self, - event_type: CBEventType, - payload: Optional[Dict[str, Any]] = None, - event_id: Optional[str] = None, - parent_id: Optional[str] = None, - **kwargs: Any, - ) -> None: - """Run handlers when an event starts.""" - event = CBEvent(event_type, payload=payload, id_=event_id) - self.events_data[event_id].append(event) - - def on_event_end( - self, - event_type: CBEventType, - payload: Optional[Dict[str, Any]] = None, - event_id: Optional[str] = None, - **kwargs: Any, - ) -> None: - """Run handlers when an event ends.""" - event = CBEvent(event_type, payload=payload, id_=event_id) - self.events_data[event_id].append(event) - - -def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: - """Get the time difference between two events.""" - time_format = "%m/%d/%Y, %H:%M:%S.%f" - - event_1_time = datetime.strptime(event_1_time_str, time_format) - event_2_time = datetime.strptime(event_2_time_str, time_format) - - return round((event_2_time - event_1_time).total_seconds(), 4) - - -def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: - """Calculate the time difference between the start and end of an event using the events_data.""" - start_time = events_data[id][0].time - end_time = events_data[id][1].time - return _get_time_diff(start_time, end_time) From 9a611e9d5220d985ce4632982ae7e3648fd2a789 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Thu, 29 Feb 2024 09:57:19 +0100 Subject: [PATCH 08/24] current progress --- .../llama_index_handler.py | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index 11f1156..5724d14 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -1,4 +1,5 @@ from collections import defaultdict +from datetime import datetime import os from packaging.version import parse from typing import Any, Dict, List, Optional @@ -44,6 +45,7 @@ def __init__( # Import Argilla try: import argilla as rg + self.ARGILLA_VERSION = rg.__version__ except ImportError: @@ -222,3 +224,134 @@ def __init__( self._ignore_components_in_tree = ["templating"] self.components_to_log = set() self.event_ids_traced = set() + + + + # The four methods required by the abstrac class BaseCallbackHandler. + # These methods are the one being executed on the different events, by the llama-index + # BaseCallbackHandler class. + + def start_trace(self, trace_id: Optional[str] = None) -> None: + """ + Start tracing events. + + Args: + trace_id (str, optional): The trace_id to start tracing. + """ + + self._trace_map = defaultdict(list) + self._cur_trace_id = trace_id + self._start_time = datetime.now() + + # Clear the events and the components prior to running the query. + # They are usually events related to creating the docs and indexing. + self.events_data.clear() + self.components_to_log.clear() + + def end_trace( + self, + trace_id: Optional[str] = None, + trace_map: Optional[Dict[str, List[str]]] = None, + ) -> None: + """ + End tracing events. + + Args: + trace_id (str, optional): The trace_id to end tracing. + trace_map (Dict[str, List[str]], optional): The trace_map to end. This map has been obtained from the parent class. + """ + + self._trace_map = trace_map or defaultdict(list) + self._end_time = datetime.now() + print("Events data on end_trace()") + for key, value in self.events_data.items(): + print(key, value) + print("Trace map on end_trace()") + print(self._trace_map) + print() + + # The trace_map is a dictionary with the event_id as the key and the list of components as the value. However, + # it only register those events which payload is of type EventPayload.QUERY_STR. We must manually introduce + # the events that are not of this type, but are relevant to the prediction process. + # for node_id in self._trace_map: + # for event_id, event_id_object in self.events_data.items(): + + def on_event_start( + self, + event_type: CBEventType, + payload: Optional[Dict[str, Any]] = None, + event_id: Optional[str] = None, + parent_id: str = None, + ) -> str: + """ + Store event start data by event type. + + Args: + event_type (CBEventType): The event type to store. + payload (Dict[str, Any], optional): The payload to store. + event_id (str, optional): The event id to store. + parent_id (str, optional): The parent id to store. + + Returns: + str: The event id. + """ + + event = CBEvent(event_type, payload=payload, id_=event_id) + self.events_data[event_id].append(event) + + return event.id_ + + def on_event_end( + self, + event_type: CBEventType, + payload: Optional[Dict[str, Any]] = None, + event_id: str = None, + ) -> None: + """ + Store event end data by event type. + + Args: + event_type (CBEventType): The event type to store. + payload (Dict[str, Any], optional): The payload to store. + event_id (str, optional): The event id to store. + """ + + event = CBEvent(event_type, payload=payload, id_=event_id) + self.events_data[event_id].append(event) + self._trace_map = defaultdict(list) + + # Auxiliary methods + + def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: + """ + Get the time difference between two events Follows the American format (month, day, year). + + Args: + event_1_time_str (str): The first event time. + event_2_time_str (str): The second event time. + + Returns: + float: The time difference between the two events. + """ + time_format = "%m/%d/%Y, %H:%M:%S.%f" + + event_1_time = datetime.strptime(event_1_time_str, time_format) + event_2_time = datetime.strptime(event_2_time_str, time_format) + + return round((event_2_time - event_1_time).total_seconds(), 4) + + def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: + """ + Calculate the time difference between the start and end of an event using the events_data. + + Args: + events_data (Dict[str, List[CBEvent]]): The events data, stored in a dictionary. + id (str): The event id to calculate the time difference between start and finish timestamps. + + Returns: + float: The time difference between the start and end of the event. + """ + + start_time = events_data[id][0].time + end_time = events_data[id][1].time + return _get_time_diff(start_time, end_time) From ba7e7d8c3afbd0e02bc368b9be6dec0166aafab5 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 10:39:58 +0200 Subject: [PATCH 09/24] code cleaned, example updated and legacy code removed --- .gitignore | 2 + docs/assets/argilla-ui-dataset.png | Bin 357432 -> 102735 bytes docs/examples/usage_example.ipynb | 57 +- .../legacy_llama_index_handler.py | 694 ------------------ .../llama_index_handler.py | 441 +++++++++-- 5 files changed, 415 insertions(+), 779 deletions(-) delete mode 100644 src/argilla_llama_index/legacy_llama_index_handler.py diff --git a/.gitignore b/.gitignore index 68bc17f..795a783 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ __pycache__/ *.py[cod] *$py.class +.DS_Store + # C extensions *.so diff --git a/docs/assets/argilla-ui-dataset.png b/docs/assets/argilla-ui-dataset.png index 1f0897d8de5e2197f5955db1c7d6a83ce35f765a..2d4b25b33e47675d3f6ae84f9914e75aae20d253 100644 GIT binary patch literal 102735 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Πx%7=9meH-4JjXh3rDDtjf><+fO)uu`jj2 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 z z%Nsmw{jN7ZYz!i4x3w|gRzl#$V=wf|HYUf;T`cMhY;I)^DyJyRD4Y_EwyZWAPm>^o zx1uS3L3&SI;D>uIN=~)(4jX8M0T}2CXRD;%(T20^TN^9p7?^u>@11QNQ-O~-`I{$!3uT_AAL z(a~XIWQ>01_}AFR$9LeZ@cONpi6tJzz>WCK-#AO;ul(oWzyvXnbM(=^d-ty6RyaVE zOz>D&e+_-bC$4Mkv2TU2eagNbKX%&uy*&zNi?cVLcJs#|_Bo8PT%KfxDjigI_28g( z?Uu4Xe$_@;P5v6sK_MKz&P8GL$Je29Z)+HBx3)#N?;bhg7ZmFg6hy^?-rsiSwk^@d z%+OsbAbIUtb|4E_U>tUL z<(QDy6a0IEJwCA$7c8-E+i0qdyWw&DHC_%&uD$xUDb%)U5&%*?!OAKHINcK` zPrldB`0M?9kF^n#zt<@s3Vg)lkGB9BEF7SxUZcMo=WSq$YBA&GZ+SB*9oqqaQKSdzInRE)ohU-&yBPx* zyQ2K+mT%zi?I8HI?reo0*b=~QY3+Z^*ABSUzvubk&3W}NuK;ib z>*C-eSF)|2-v|o-`JNtfsjaB`?>F}6F$R1xl>HVXp3$}!pyPou$Z?Yul$3n|*cr%W zGc+}YKcsVDWqNwfIw>ulqeq{dwO z44vZb=s=qt39l$vBLJSIn$s8qYhcH{Sq=V{vglPuwx#OrkseD-(H#vXJRH?09n$QrYTTV8ceYc z0!znN9Uy~J4cQS^MC2v7C2=L!QZSm$lPK>O^ETtCm0cYM-RT^uQzf&WIdB?;c;k=t<~J zB?mjpZ_Ldt-J4*9M?i4AX!ft}@0>mc&Yz?j^!((bSacXmyT0`#WTlr@JGHS6w^0=G znRO33E49AnFenY`2tj|so6vk1#^uaIl_Kn{d`tc-@rZ%AgR-x#{!`s49^rz)du~As zg6vl&1SuCex=d*GOb)j;$X{D@-VqePFdvqi-4sS>?UY_vxDr-K5VlV)Ri`SfX3GAI ziCCc6kYC-*o2syPTC#JA9saF-v;ED3XNw6!nwZX}p+1{DZ9aeh%gMI0;!XC9#YNf^ zjw<#I^(-;!nYvGkAqiy#s#aZE&yJqG#8EhM{0APVBU2B-AxW&S;Rc^_mOck?hY}QD zh53M39SgPXFfEJr3=yt92#mKe*X%|C07zm%2Rdv~${}h#+o@((DF`Kg1xedQU50?> zNyw_5K#VPf(L(_!Z@WzXde^F(*;v7>(J7C4|o0BR44CEgvtro=0mKjqz8J8)mUa_j)=C zr$;zNc1RxRS5-d16}{2nuI~F1KZ<#*Oil!JNCQy0V6zgH3(bEEAc zePBCcNUHuLYr)Yc#Zhn>(BNj+mC0ny{9$_Te9%gb0d$PjU;D*B0QKP%qBm|w5w`6X z!VvLMmaiZvQOO3=cc8HHCmZM%%kwZwrW>}3mi@ff7DLUCJ-1kM?ld>Qr&`1<+1U7G zNM(+4KX5nK$ZZV2!eHpgv(6uZ2d+X&oF=rH%Sp*;KA`gT1foRr5FO~hM+N4qTlZ=? ztt03L@OS9aGhZL=%tlq>7bnx&ev!hic;bdwmqpUMp#S`?=f z;mp%-P7cHiJbCc$+XcKQPxha4W&K7jZu(8-euj(@I2PP3Yc=hko3jq?NEYS6hP(mI z^vnt^gV2!?L$z$f7qgA?I?Braus3$D#2TrzwTyoOS*k8`m%%E(Oi*lTc-D7Q?EXjK z^=FY%AsBHhB+c1xn=yZPnpK+)28_LgHZJ z!8)393Y%w)x7!U|?mm1Ou<97UlnH1g4}GF^sN~K@R{)4hDF5ytgVa!6I48h;vT`Jw z(iTLroNZK%oqAzaZMde#D>l4@0}RjQN8WVj^`F(?weorWq3VF_Lri-{0v7ozIe!Md z7`a`ISx3kC4sniMaW5x3zt^FYa$UVPku0xib|1u0h;YT;YB)d66Re z*MVh`cgKngIZNhzK85fpaJd%VdP_)o=BBG51CLz8vYQRFeyYHo&zC6$9kRdot>eNG zyxReKdJ7eFlX;eY4T4?DM8^k`m;1skSA!XhUZoeUPk1;d0z~-)<}Ia1#=`-o*0Jmc z!21&*pr(HwAse?F7jH0Sw=7GSi+5o99t#ufKz4FTrt*u^vA1<%iOKulKlTv#pu1L> zAqY?|GloS3lLu8xZwNo<*8~!NDE4GJ^+T7fOBQ6xHnxCnAB8(xSH6aNL!0jy)*Jd=E|{~ z^z2`ID0u^3P~@eb#|Z{SOp1nkE@{iNl^4gJ8>N%3l_x!pru75!C}XwIEal-+QoS{e zzR-FGT^l6S^aph(DS)XL*b1l?1&s##`hM-u2bx#ScVKu#8U%Ko0-{YO7F1sACRm!c zNxUUpW8mOOYwl{5?}j~^Q9781-G;jGb|GcZ^Ph1f%n7O1^E*ru^qakDF!%X=&15_g zeD3T}4I|N~!7!g??18GpxVIcCmv^_O+4ZaBh5PtiA2UDGj7}U?{nrxf-@wfbiiDXP zGF3j@G`UIEd;cvU{1ta4=pv^K<(ak2|LfiraeY@*O!IjQWy$q+Vm#vJi@+b`o_duj zzGZ0qiueZE$dzg*8fbnj0J_BARvFKEop*eKx&R<;()ef*?JW_^W`UYJU4vpBd7SLDw{q0^7A`=R8L9x_)uRNQG08y5{DWn z2s+u(p_VDYTbX4f$h+uYqLLX_wc=kI{#>;#EZGLz(s!d}SS~gZZ3aOJ=r=nJv^Hb`KaL9o@ zg#|FVuQBIJ;@>bF5ph8Twv#xYngCW`EY1!Vjdx`?I=i#SfZH_!iy?gl)&|#7QpS z_I%a09R+*^K7oFxDJe%YS?%(4$6K+5XD*Hx?q@j;tqzRwx$>;8Ej{;Zpd2F}S*+Rb zTabgU!D(9r598=!lq%^`S_)S#Az{p^0E1T$F(W0VHd%3u1{ZGY2AYx+;1-;RkM^z z9l#__#rq;*q<&Ew|J{m0y18ISwtd#uK(?FbTp6)dw=ASM$yc<^WBU%9Y&(qP1PP8a ze@iAZRB;H(Hf)Ge#Ar|9r(kqQ@eIa02TEQI6Z;0E-iM)cxZpozMpoFbfv=-e-}O#x z1>d^eowZe;E6rHq)%gLw+&gF0e0+Ts!R$7E|LkS_%1#*#YyZXD5X_)(dR&hdiXY?^UJieiBNf{Yi6~3$NW|e&f>i*bczO&jz0RiEsK-WLYs zHP$;5-?cW_W(($t4UhEt>BrHvXLn9<)24)K>d!r8JKt?>??3o7?qlslaCMeM=Ou;+ z)X0~cyG&Uw_I+Swe%?ZdNHB^A}Nf7yPt-r5gvBBkrGnS9w{=gVH=v z;$BF$k7G$e-T>mcjLS8CqG|(BV0^ zJsi)0OzPl2deF=u&!|qiVA?%d_w9;JSdvYRWjGOCvu0Y^t;gee>pQ~+r;2gzq|fK+ zE#nN-l!TYR-M1U8X{)UAO++UbvhL4u63qJ^nhZi>{>b(@J`cKuDxJAztcZ^6MSyJE zz8XdZf!j&RFtti9ZK6Pj>c0EM^PFDQp&}=3z-mFC-ncKD`oBnmlUz z)U+p)7uB4;PH9!=#29P)ScJ=E;!#)TjYk?5?*3CJqpt`n$E9i7ynCl_jnQnx^@sT= za;nX>-&+_JZ(Mx!rDobtJ1)0cNAFu}@&ue^skoT==Ntwy8YUSO@>2W) z6-v)59MQeoeIs}D_$vLql*^U*s~kFGUpZssn|Sm?zg#r)9emQOm}%G>o-3<4#+$oy zl)HLZvgt4_(`&5;C-!Pv)gwE_%X&~`TGjyK0R+iP&q~{l?tqabG zJ}(OvqtdSwT~^T~zC6i!{m2EypBrltrW9oSGJ!SwpF48mNBt-nZ^ty*1*6* z1@)87{x~13eN^oEMj#tv}DAmS^kP zE&TZy-Ml}$rTRf|;DLir>PU{6X_rakhD%G1+k;^ENp5}aUp;>rH$L2XT~ z??d$Z^9TGNcezy8O6_spWvu(n&hO(K&Oj+vcv{;){;zt`ky;m(eupi;SL7YQrrAyp$1=Ce(BYdzQb> zVLx0VJ8o4o2D(mJ-CRq`s}3zme&;5??9)x%jYnHQf#MtZ>!oymyq`fGSMbs!`qGyL zX#GHxx(Oe49Q{A;{xhDuEN>QVys@g?SGg^Cu7O_d`&{pl5 zv08h^jvcD@s!c+o_KF~ah{*47UT4Sk`1E>wZ~gE5@8!X99Le#XulMWq92t=1iY-cQ z?Va=H`=cjIWtwR}y3T%U@@{W%6l6v? zTwjC+mC2D{hQt(auAM(9(P)(gOlT#H z&$dRXu-b~(D0Q3DDo=e%)16=kR($HKa{+v z-4rcA=qLb0b{kz*lfj<)Yu@KpP;Kq)5!+ZFV_}e0v%KeFi`DKyuAQr?lPb08Xi8H? zxwEkl!n+crOoc>oayR#cYF6rf@MmBe6s!+!Id?bcRmSHH@3bbH6u%n)DCUI7j&T_) z6z=YbwxwyP$xxhUe~&hD~Qo3eBfP{1f!1_mb+EB$)zF&HLqW(dpb~^QSuz8 zv*_OTPAOrcPg1*qB=p`S$;Cp>1LOdu{O zl$ga{6-!^*oj0W`#A@ z;g;6csBKAS3|H*w>W6Y9K=2qOujC(p(@dy-?Mff%b@{m8$V0EGbrFdM{a(lAc3!q< zs_a&gpB9xgw=6vKjv5m2JjItorJbm>ZS|U-76c(FeU6VOc6}S{rD6v}*JIa{A)Y#3 zGyy$=rv&U6S3d=@*}q}LfDYIOu6xU!0GJBA$Ft&Lr^_6%$v5Vc#T5MaNk{F#G+&MI zyAHy!KB%JKdf<)|1uYwgj*5ou<6Sd1Vhzb z@#}cgJyQqo5L3HC&?$X{!-$#x?z&IklVsxksK-&aa!1M-{qmjPoESE*+Ac|VNjQzF zN%3rblC>BC?!wc)E%p}EA5iJR=yN+2_r9U>0$W(h|R4U_pzzPNIRMm zO}nA}zgXT5jl?s{SmAQ%A`w3Lg|jjP6{A*~etzl`)n;?uiMD}=VxG7f)y%!!ob-4r zqeO{0b&7UL_jrSywGeg@>VK`Y>)Ak_#+oFOLu;;gx0`|JXmFFdAmOn(`ZVZsSg=}A z@U(p^dS4pic`vn=*8b5P{D{8|7|U1M8W!8jCXBvwXqHa>-@E~kV9~hHCIU+L+ukFT zJXzFXe%4ta+DH2$%y~GQXY~g8=bC;m^F@kzfj?hLc=%*IFW^j)DRCw@AQ2Gn{J8Mw zVK``t+=yAJ#n(%~9KHwAZKNCyK9Z0Xuij#6-GMmD=KEOMZB$u^#VvYojUp)#tV7Og zLe9ZfFdlMyCXpIz&av?K_Hh1wU>3rsm8kYtg<^wdLkp~5?~R*fGL9ATp|X1xK#S9W2}(r z`z}2kI)jGKKQ9P5i94%&dX0;<`T~aX0n* z={sCn2`r~HWo92o>5UtP-r2Baw(aSj>plS&t{X0_pYw*DN{Q@mu+C*4*?#7u_%a!p zKqN2m3n#eVnOLzfWmy@jPjRt_x>9D^Dcci#FT02$o)5m)j@!h+Zfv&D*D<aK}XGtolUV0 z1u9XQF4#3~mpQ}v(cGXbD781^ZUq8yRCvwnI;?`vI<&&)L2=#r6 z0kb#R)cwL=SnyhP3GMr%b*|l4CdQ;*yEZI;>m`wtpptI3Sd4X9Y()@I$U-Eyb_R|i zJJa#laPRh08P7}I`>XvV#lE`Oro}8KHY&40Bf1%SB*(r&)pryayOIQgSWR!&R&Et5 zp$q$SC-&VLu%LRcp>f(`4R08vtcx_S9HmivZ)+gm435o_Zgn1^Ug3sG)&fcn#0cvG z>9O6tmkM6T2jeF3_F{vjNBrm2;}j+lcY4pDerg)3o{3v;Ivr`Vue{&&#G?&lJdkeC zG;_|L@Jqr-0dn^3*6wH2VyX3RG9cFKGNfnF4wzQ)9mvuja7EoQSRmo{p25dho4b>i zzRdRK2x3!u z8y%Soq{0uTCE#U7bUK69{uH4%?nx3GJX*Yd(w3}wj~7C_T@D}qvGkC_FYpx zce$DLycU*fDePE>*Ue&Npn#(=QB%?#Dkh7z0wS_}p3sv4AOr_S?F-BMf(p4^o~- zw{MTSifMbf*Qo@D@=T)5BoaO)O2VGN41{6){4rgTY(d*mZ#2-An2$XyD<@AB+?~x7 zly2+bE^SWl@IgJW`!+5&BIO6MUD)+8TmF*%vE?;$3(vDFy8OeX3|eQhPX=5TS#eFS z8r{c~m`WscMQO47l!=ay{-U@yumz0G&DFfa*9vy_i&-`oe)&Xf_yrxvUZrUkt8fbw zU-N0Z8uU+25lE0k0XFPvfIsDI<5Bht-KuV)7M(u$TemN=r*N=tjb%L^kRHb|fhe|z zwdD8L3QYXRNYqJXB^-LY?PpW}U5sJfSG8Mv=y0Gcx;H%2RZ< zRsGJkkc>K`Tav76opk5&Zo8)&X1aKamZrNeuaUd%>fIn7c5&NqUjUix9%@$i{OSJ=q>TgI`UfNMgZWe^zzaU-FjCWI^K!pbp0eD|TVEp1Q$~_lswMvf zI}Bsclv}s;+WB<0#P&N4!HmTYRrZWQr{G(zo`X~oxzYOZ0^TY(p4}re{xBk?>gwN} z6|$1z3pW?@^x>O(iEgU$Vo;~`EE%4@FZ}bAQ*NWFmQ6 z-n-6rz5DojAu;K;3#?pMQ4(ukQKlCAwMR3T@t`%l>R5;KEKd)aKAzhr02zIz{9 z!CXG!oy?(}rozIlHQzQcbm7%5dQtx_Z1 zTq-hNc9->Mf+S$=>~*_16u^fyy&uK~7QGNA6j`3p#Fqm29{783eoOr9&rcQ@tn!lg zq_QqPZ~G*1dznzNuvT{YX3fM&Vy@D>eBE4!TKBhJY)6A@Pi!F>C+s>O=O_r@z)6C} z9KYO&in!(4BJM>RLfmPRlizK-4o}!mamOI?x?nO{Z7?8vE4Y!s6n*W?!npJSYaJ*C zBN`uf>x{UpR?VZNptsP(P?^jzBaU9i|g_Bwv3 z^y)RzPSf^Gb1ZhvGRMK%i$x59pK3k<)=NSdm12q3L4YMZ+A5)V)l__xJerm^y9}3$ z^^8jLS$WQjLToR4zwoPFnChIdJii8c-*auHD`Ht-pp|*9`j|U7JqusfB$DETd2QV@ zfOBb{W$JK%*IJf-tV1u=Ix~@7dJ+wjpP+ADs`GD>UKEn8&13Z0Z*j2betUSn({%eo z5x)DTs}FKxgV4N0GM;Riz5I|U22r>h0PZtYNRb)0pyAmk+++T%z zhZ`7wz-0nlE*xVN?`w!6zrihEN=2=RtyR4op=}`f&=kEe& zFM+iCB=&VY3|=38^#1s@GzV4-0Ly)oslTRL0kL){y&1viF;{&rPNNQwj z%ZJFI);mw;0YxWWDhVx@;!u&*)Om!TH^n9Q&gSGZ^c+2JGUs{TJx7|Z(!hci@-E2z<3DarBVlX@N1^{f*oy+XS|TnQSu8JN!KhE4-ML5Q}hIdA`3yGy;I=*@a zBJbvVvizu{WYYuH)pzdo*bPkVSgG~f{e_#o(zFCan-qRP1)!LhrQgE`&}mYei#H!l zvtWyS6r~Yo8)!XZ;t|Dq#Aw+*W?F*au~g%Xyqcht-E<4&Lot_HoEdP`jWzLpT`Rq% z#6mmpB2I|9IS}S6sXId)JKQVTmFgAyq^KwF!PIwg_{dy>8E}3* zJsh*0xy&OOsTg`k5ja*|*X4!U!NT&A%nu`zPT&4gKde4^*!v3aiMc%?*DNZh2FxSe zoqUBWc%Gt{E+eS%O_JX=OFell;1nlf@!5-&f!S}I5LGf~%gL(~?X;1xT~u_JTCGkf zi+LgGm;f!5e>GJ(z9v%DkIrelvbc+IX=ZNDdzC?;+iAZ}P-D&+!;{u~Crv!B^jEb} zLF#y-_q2w~W2C=}KYDI<^oGX2xoU;<6P4`@CoI#MeE`i8k$7v3!+Oul@5m15m0#Ai z8+uRI|H-e0vq?JEecm0&G zqlDbNy^Iozzg(HTix zE$zxHNtvy~y(yQB>zzJwm33Lc@7u~QkR)p#cHCy(@~UyQ@^A{ZjVZuB?aA8<^d*ov zTJY$eFB4T`TXS!+If#k7pYAZu%)_K!dB7%J)&zDQq6&l{(@&3EA}cZ&v{4f#RW2Fg z&OIIv>sxD4Hv3MUJ<&sidGadLZ|+jL3g);#x=80hq+L}Fw^Rj+nqx>8=y>kOe5db|YyN%Ui)^D7u}FP#$%93~W` z9&(|4dK99d=?`{|x|_=yau*8y+T5JLVc#C0k58VPodvqLaCEtSPpEI}Z$6PZp2HOS z$6a0*SufVgmv42Qy;77UT6@;&O-k6i(5?n&=F!JPuNBIvGis6`flQ~-$)|uh*3TL_ zz<9}-b8-}{ai2fCS77Ui`U#)B@i0|$!g8$ID>fel+SxWWl#EW)sXp0U;uK4Cs8{$b zWdL9Vl$3J>9Qr;ylil`HGlU22CQ|FuYeWAENUZgI7u*xMxtTOuf{-Gu&-OEfyb62q z4yk+NK`JUtvIw0%H*abE=*;QvU-h+DoZ;XSnX(0}?Z4O-pvoDr#Q#t@CxDAvQXrP~ zK_RxSOs_({*=6xq$l!wjpv)JU*gtx5#B>W@9o1EpizCI9n4I?BADQ0U=AMPn9&ITzyg1^db{rE^ zPBl4gbX;&C&p zYasHXjoKd->VLm;@)|%rKAL_7bZ$>j`OlsQzoP;IBIzy>t1MGWYSq>d0^a#Q>kmK6 z$iF`vK>J*!zwqGE17gmK8KAxA!*Bm(JO@uX>ta%dEh8{WBv~@Z+--(zwQE(&+iq) zK@W#NDz^Wlq#AwW47>5e9JGbSu}4e+w1pwZWgeB^$e%rCe;YNvJBGk(i>6}j`s+=N z?S^tQ04=<>+#v_c_Q;Hltr~o1qLi!YyM^j)3z_9oEmAaMwVBB&> zXH2_A7{FJBr}JJGmm}wkIYvM6z-UY&xCAi&XIuohT+F_xdkNq*2#;9X{R6W}eRIP0 zg@dy7DXfb7>3}nIZug?S>8}>vgNy*hd{f_g`4m-#y#@*E4?f%5>6k1DYwfw*9pa%xW5Ln>T`yz+wF2>w@m?~THAN?UPZh~ zwIjwlzIB>OTNPx=X?YcQclRQmSv)k8F;7=VM%(&@`>DSXb`z*0O}DP?P6Z3yjIV~w z41e+|4aHI?EviVFEL)R6~bMzYs=!{JHwYB?pu!AH1D?1{GsnY)4G{SpZe?k zUcvPzr~@*CeWt?14$YVqO~c|?7yCo8u$w-5mjlvY(Wn$Qg)d|jyOuIEf+SVtAmZ7i zaWSp7=dElOSi^Gf@;iHN78?V-=edO83p?`C>Klq__eVL_4w3P^Y4;goVNUhkS1dX>T^D)rF^fKjGX$-v^B$Gaxu|3z3L4>I4A+E{k(#My!cr$>%hyaAq3mhij5oubS=S ztFpL6uHLQ4$m}3Wo;sUk5ci)T-~~b<*qu)Y;a|Hl8pFq;58n3YUm%QDUb5?xQ!?_f zzs@XEYPC475m|97?JLnf9wNOmlKxe?#+6_>R;$sxB<>I;pmOS5u;8{?Dmj%r1^<|d z+($iO{>hh7SfmyIEC2Oh&psWd{<8+tGClafWM}TghN>8#4WR$)=utq)+H~76-_A;7XT*;zT&=cRTP*-?+5#s((Z?z>6Yjbv$!$g+xZai zzf~-j7WijZdTSDp{*iW3GP}l2zPe5+Zmr#fw94wyh_w}~YFnR&L`@%A74Dm}=E9e_ ze79zn@eQ=JA!#ix_?nAV?IqV^@-Fxkg70|Dhc(BfNX{Iy8!EnAJc~Ke5*qhVV8=LS z-}`qBnt&2|+Za`o{87i~3G2UZzX=e6@j4uUog+9Oj+}JOBP6cg+=hwKx}{%%Yz>_K z<_Ze(9{vELL58X}%bwdi)wfk)>|Eghtdutcu&|d${FCM&ZPUzRHY(dM89p9n7{wZz z%oJkXuxPr>faFZ|5{yndYFFt-`$CTPMc& zWCjM3vXYfqj~l&28XYlpS1F#vd(9^b+9Y{Z`%&NVro^;IQOkNs|DhNJEW}-xDgiM` zt?xPM$XwMwzR~?qWDeeTDzD$3esP`>M54u3ti8R_RJ@;^UCggmHn47zWh{DQO( z3smT4%I-SvhadU2Z^~aPyzetKOVxZd`6mR{a(=o~*CW+-f>*i)zU@|RQ zZ~n2p?7SBpB;!tk;5h4mHX*&O5a;!Ty>_dK!PSvER{G7W*TXOC7A5TqA-O`oGLT|G zEe7KZjb=`VUx(vMyIh64IES`4E?gK*W~@gM%ATqD-1s=vXeZKVx!VGhf-lFrg64N7 z24;22+HQP0aB#n?76cwXsV4|Wl42Y&wcM}Dl>p;#%a_Q6_FU!$OrtiqEndqYMc8ab zj(~VReP0LZUs7ltSkwHn1UPn-;TPpUl`R|E^+r8JFP1plXq^YFAvf-LB-`FJDb4b^ zGH&V?Itd6^v;jt)D`?Z|75-~)unsB9XZnR}#fJ?;{*jdlIL7qAPDi=077iB&n}Q?? zG@^Pz$v2oVC^Q2(|B#7f2Huc7)_~7%=bxRP&wSvXNkR(hW@!PZKdu6p{vaFeQh zE$(P$P?66sSFRY#CJ3fH@70RH8LP5!qV&fJz4a3?n2ok59)D|Ntg~6UcCB!kQkzd9 zIt9=Fiuq=FQ$gm^O$xD~yt04Foeu}-#7}rSulv_~@b%i~zJN{R;Gt-%r8(0PvKNQ0 zB!s4*bK}{C>(VVxZg1WEuq&QQwX2W>j>zsksE0Lkv=Zk5P!V%I27G(0rdr_R_xRv^ z#8=Ro2Yave-*zLV{mHyN-}-l5ii5jm_9@5f+<+5V6m<>UQ|~`JG=fX(q4+E|Goj`o zOM?;fDSoO4q`Kz!(V}jnrp+|7{wx;%2nHzJJLV==RFy7Xcnw>7OEI~UWNcU?Fa(f2 z$Q}bI*1M<9Ef2+DvfL{UVYNVet>)AR-93NCGnpGwcTD5|915oz3 z&nqjAeeBqhUb)xI)qv1pi8am$i#S{_bnYWj%%JG}m0@>DC)AAO+RB6{0FIBh82Mm0 zqg#tM1kW)FmBdEK zWtVrX49P5&R+wK!qW?NyB=7(s=j>T95KWhX2U>>r32;84ksC&W+!^(zsRTMQzvdZ_ z_I|6a;3rTBpp0C`Yn$KnfD9vyFl!o#*)es&7UAzWJ2C#-epS$&HqOq?*8@HMR-KeB zt)PfQOnNlZ^`(GnHesx`GS$z$weZNh{_uMtHAmqnGsL& zx0rsKu9C-fel#SeTn!PA4GRcrw;L%h{>t0Zz5$g~(Z65FC8_@Le)sZN)tiBV5?{$_ zFVo?D@5@v4Kez0k*?|Mv$)G0y@)kN>eBOL$NzA6(rAoig{^))d%(Te6JK?i)oIzh- zUw^TpPmS-pluxkWg30n!*DTGgA;2m`DJXqQNJKG1H5hI^$L8&;ya**VMn*;R%h$`-JRaKl`q<7nu+qCp4`BwLdGAA3bu{^& zqRYHER^mB#gtXa=|6E4^M(MADIGW+ zZ4GhCH;z2z_Y@q>(*6FdFPK6LpdIaS%yXn`=Piex#Jr3ibDg`8H#MR8^zT6WM;_Pp zTMbj=yPfMOg|)l8Ea$FwjsdEf(p+T>r~D`o19Y=)mPV|0TC1nQ_kXqO578xdVFAD0 z^Ghx5Lrr0~4vk;38?7xoHPf?i5$#J_67MbQ$FQtg&an&&fCObj?S%Q6oFZ7!q8S=l zZ~EI#Ui6!c0B2OtpFwU-etk+9l3{L2VsNxB^|PTC>)7*tRSlxR9&|FCnyH2Ps4Qig zN{Eg6z%advIQVw;ou4VA|2iZGBnTf&C=pFj#d9)NK1=TNIm@lOT5|2fL+YQL_h_L> zB)9VZsb)1(1Ug$=Q6&d-J8|==Jb@yuc+24>5Zm5u(b{Q-pfMNg(4?hhXRDCjL?l2Z ziHg#aZY&gC9q65TmzBJ3Cc8kOJHh0=bcZ~CqQu8z^80Psi(dc6wr6dZEcXkKQ?^Tw zgc`#d3UoKz=YxBS^BT>eR=5)I2IhPeccy+>m&o0zm3*oVUaleUM*opetk?^F!PfX5i$V7AaQSvhI$c22Y>7;3`?Uf2=aqhCHI!SZ$@9PG3w|{=jUtfY z$Rp&_fkV{j0@XUl$#jHQ^n#6`@>~c|?7pv;*_)sLlHZO%AZRRtCr(Oxr}72Y5uOXa z>_|>YaWLyWuO)kpL_%xea$!3=fY`Prcv%gMp683|jZ~(RDvb}B5WwXVrXpOqVDe5e`h3;fT9IhiP;lw42S__3 zTi9m=pXc5lNd-qv_pb7`*jo~Om+I>BJ{4+XJROV2$sJO=k3UNXsSWKL`4|!#ie)I} z#`N!g?eM>UnnchDk{Ne#Yba-Pm<0RDL~EkmnDtog7LbJKka0DO4U_X!-d|t1cJ9Ij zOK-m=KHkoTLlok?aDAeKswDDVn1f+mUVqnA*PP)BCIyPA%G}K8^cSCCkp$=+yI>8C zkd-2%0*9IBvjf>#6&3n`GGGy(j(!EGp86y?IXN!wdRDSaqz0P}{aC>~qk+CY>Qtx< zf9F5C76AgfxJUBH7~5q5;e0+tY5NO$n+m@cQi z%*^+uHyy9%Q}`uKpdtH41-5>>?X8JcXom?ahf7qC8O!w+>odNEg2;( zY~{KKpFo+Zwqt(wL?l8F{dY-wCWFCwlbrdcFgX!Dj{w7msE-RXE!kMi@Q~*F^?yvb zI2!1xS&ZfIqgbbNEI`=y4VQo#!%4F&8`FHd+jx|EtZPVhFlJ!M1+nsJb7ZJK;`E=# zt?$9O4JM@PR|uJ+N=mj8`E1nin0N_ptpB_$=|InL5z$+%rzu0c;I-I1&&|Vge`#rH zrkcfC)y^(QLn_*wZL`)BMdwb48s=;`gGqSoT6WCY29Vpg|2kcIG1iE@25 zTcXh-ajt8*7*SrP?fd;R_vgULCF$?4rn#l~+C67CbwjviWlejdqN0|?g@yl@2gxa^)PCa+t~hvdd%PCR}TR*Uf=+O<=hoR?j%sSEu*!GH2%e)oG)Bp9<^m z61oYflV5E|KH5SC(zHIiEn*DaohEpj=>#pL2KS9_HU1BMXj(uv2qeivTC_&YnKGx4;$lM-k$&4RQ#l-Ft5-rQ-NCZ=8^eu;xu^Gv8F#?A6M)5wYgM6rp zc3u{^qufwMhcl9xu=iw&mNJ3BQaG@_+RnaS|%fAHTAT|0C6<~49oK%q&w5hj5UYU16l6dBoX zT2J0Rp>516Y*c#>(4FL#^-k~TQ$9UtKuVC@-h-O;>(fG=k}X|RkbXh6>vLDCHr{t` z4%L=|_7J|C>scF3wRDj%SRVKgGvF3{GUf@YqMtYEw%K4z@6s;b!MP2~1|HK#Rrl8y z%u{kVUwx&Ge>TTFZ0MNmV4rKXAE?B*I7f7Jval-LsN7o0+uWE>k2(aQUXi_I zESKjo$DfLu<^Ff}x(3XYc~YJu^wzdV#Y(M4cTO7aEZ!emBQ%ySoj^pZ-~&`dNlRxp zNc?&Cl86o_i^`B_J49&o+w7ZTmG)T`G>CD}q5k{+o$trL^I9)7PGI#fygmLcHxK*v zQPpPXb5wFSC$^Rnymi!6aB)`+hjzjVOy=L6m`z+(?#L=NP&IU@$t|!$T*-r<)c4XC zMp<9zlRuq-WW2b35Z(PD<8|mj6SUi|9v={tp!GDv5{)2& zw@aBqS*aTM1Z8>ml<0#Kfi~9GZ6d87!U5K!6hEgQfN#J{vVYkc%v7!XCq_SZEFe4X z**lF7k=8h5=UjkMx#@=CK#Z9Vr}pW&a1s(9QLa|e{_Q#Q?hQ=t#^rYGBThR*({$IrKMs!E>VSm_#(<#X zPt4SjRO=q$NOvd`^X=TMts%vV{R-tr@&hF`4~n*qnn^7mpACTu#q6Sv1eXN$gM#0C z{(gS=wZsLyIAc5JAj$CtCHL|X(!3sY;;$6wcW%HwoZP(X2Z4l`$WQZBZPy>Q8p!N+Cp^;ATg-dgD@*0f3IOTd=2rt7FJi2m zjcwABQ7EIa;_1mHKIL0^L&z3LqnB=oaZt*AioN6O*EOtj({%so+&P+-m|lBgq1U%Z z1udosw;FMWJm(Ri9!X(Nw8Uxzl}wNT_~s;n(R37 zSl|>d4i7#r{j3&(!` z{B#W1`5v8#Iq`27CZ2eu{6^I@WLDK^`P@2c40!|8UU(ca1bCmNxUeI62d!1xm;q7&uQl7h1B+FxC-EpcH$uV8c{Q$nu)-=p;@n3NQ z1#|jWK|wxu%!xsJbaZr)iHR%ESugz3lv{+Mm$eUm@keC;77+J3eu|F0Pt|Cz<6` z<$JYmW$dFq{%EHEzWDcYfvq!eV#EpBXUUaI$Nj%Aznw_a7*y)A^b30P=XnKm&%!0( z$*j}r{C`@v{_AfIPXM7ZpT}M~f27U+nyml-`_MJgq;nLl%G0pHruX-Lvk)kxf2FLn z$n0<#X2P!^^rPPr@${O*gg5Q{kH%7kBd28&@DMQ5c`y0 z@9c%eAG#BKlJ&Qneq7aHK^u6v^N`@4H4qJRBpyr0Z`;0v)A4tn7!`*?tX~n3w-!(n*^&2nQnTWRz4&w$xha#rChOFf+5l9|ZrH zItnjNs8_G^(1*PJ*tni_*d*}#pCnZ{p3Ttiaqi^p+=sl2YAbqJwTAKGt}sSi<5m4x z^;dX7pZJ_|%4Kl0Sd>#l|6EfOjpOD?raugmzYYPT3^wU(Be*6b#HU@oxxhC-B?>Q& z!Be)c5BwZ+4O(hYWu3z>H9B#S+_k0<~9qS!OQ1L0Ge?>>Y_Mb$iTQGIVh z85|JZpHkzxJqmxbz(UPk;QqI}cIq0mTiN&}dy)kewd75)OJ0v@(6VGox|qU`2L8P- z;7rGeyKL2CjWcb};^Pvy^3*zKzjg{mi2yp@d4Lj>1Z6XAWwcT|0hTbHAF=YIVgI60 z)8#A{J59ATX!FvdTmr`JC|zCyR>_S5fq%_$)L!%04Vfsb*oXz7DL49c)D zUFIAs7U_=#C)fFGEU^Azq$)Jf?^vyk#5J#?B)%=>=^Nu}YBDudmzOeb@EBcwG#NVz zZ~V&p;Mhy;Ae71W}JIehXy!_0GS2@~lx%*qamjTV`9* z)c8<-edX^{{r3j`)fCVR$F^GUitzmU%m4Vq@eOe3JA(QkX7)cW`1$-bHDLenmnt~< zo0;?i72D|oC&$Qy zmisw&_K|DmPbmQs)DJ%<+xP`rM*8FD=!fc?U%h$o)_d}g`+b8l(1^Qj_o@cE3-pF` zo~7P*HyC+Pw{=4O=N|Fbpj);`s+U(A{34S8Xq{0g-}~- zU8U%J;ev3~oOKQgp(Oz~xvJ#lrSoY*xwS>5850@0a0L7_6qMsXbLAYT2C9eetVmyE zT*8gT!$&&yKPg&Scx7z9eII^zJ&B%%yt2~&{Qq`z0~HXg+ikpJATHj~%blTPVl0dv zE{wKfhjK~r>+dwSUHa*A{%nTs>C}|v&MSJCz1IVlHjsjoDhmRKEo4|pp?!z{@1ud? zlMghGQNRw$LIs>8Ab{c>A`&-{HYw5NSifZl#Z=^vk^aKq#3LM5I2e!s(C*x8Po{><3=-ZyVFc2<4xIIfM3>4Ax7wx!4Wt@!!@?H}LybLs#ioyvG@ z3;&&jU+|v*@sZ1-ktwo7t^g1<$@=~e-Bq(2YfVs4v|yfodu|;$qq?|V%|`|Cr z{b8-Fo!aanyJ6|7nWodVb$OdVGfr#90iO$ut#BS#6-}>baf!T?o+m1p^WQYSgS$nrQ_M@}mcW|2DPxwKG7HG3x%$@paI# zqkz((1Gd>gcPOTpymZ-epjX}p%)a>3%Jj^28nnM5FL7u{$3&Oux}tUBZyon@LYN5v zNAY0ZR>{v4PzrVatVfXW;|7(461zKqCvfMM! zz-ab%Np0omQExS-pP>|$={o<7n2udp#2iw=M#7%t0p@@X)s>8Tw?#9=2AwVC0QA&;0ug zn!BlG&thL42c(+g99sU+$(}X9{mv;@cmFhVe$AnSPn8@%bJ1~?{A|A;4fX5S{QC(b z1YC)>dAt9odGp`53jvjO$f0)v|MOWt{_z3V@lZU(M-8eWoHVY! z+e90`8T8IOv<6=X0r!PQe5dH;1!i+9h*(plg~iIr3n zNvl5WZGo?Y)vXv>M>V2d|3|j*KV7qvdaz_BmR%c~O-<#9_n)10nNM+wT3dS-?DXM| z^{Z@QNP$_YekRDZ4#+k*Mc7c@U@Zr;Ex4}AnQ7kkPpqYWSC;S+I9?{VxtheMCAY5y zNGZp3OI2+E4lMB{tbUscf^nX?`@VaX#T(rSY$rfS)W9cABzm>jiSEAwbaz8p83V9I zMK`O~0tsAPTwe{JXW`9!C>p`rx;!a@K$2``gvcV$kM_PjI}^3JJ~T9Br%wi#z{0R| z882U5k-%)3_V)z%PMeP=H76tb{mbz^mHdt-_eI&9z85B?Xv@d z`nkh{gKddY__h!+n+J~`rJFq4_Yx(~8YG2siHhnZQ;}K324^d)jPbQrn1KF88=GyB zXoJS@@nVHhL2O=wALmvwo!u+;r6oOrl`1ML9|N`DDn`2&MeF<3faB}~s7bA5jzqoA zbaeAP;Qpx5d*ki6jF=*{r!R11)nv@5;jyWgmvKgMabIROX$LtRI8|O=F5#7bJ_i2S zE{O{#f&`RcTM`funC}*eNdkvfdq_ytx6b2-lHCDRVu(`3*5w+djQ^3E`gdN+9W2Q~ zyzsQ@LK^Qc znK(+Ocs&JnMO$1>_@RnWVY zh^=U`r{Ej4v5!(Po;WKCL`ms2AXvk$?oDfe=hn#1j|>#&`p1E8EXZ$-ilEq! zh_`DX#)Ybk1q^KRY7gE_qUzwyd{sC&MIY@lX!IffZc-dy^0vPpXjbS0-;wC#b_Q^SE^S-=gIo)9N6GT2put zjbuxuGm0qXq1 zO435cin!9F-_>HTtIYpAWVc(swCixUe%^;}f+5xh;iOj3?~2R6B*Bi9u_$uN0vgFT zze=j&knwT_P8Rf>l<`^rS>AF4lB&okWaJoCP}kz5D?$$}kuOdkJINX=WTU|@RQ#^5 ze|%8DL(8W(!>pC(UVA!!P0vo)RWQ*HI4vcB-HoVR~f zzERPTlT`GAri@})aiY9y*}Z$O4F?UXvsBHh@kjai%EpO}oacY4sQ>qFXnw#Mc=L+Z zA)wyRxTi&M+|-iNu}X*@fS1CYxSTMF*Mb>^BhH7i^IF^w>qorR53rinvDucR;%zov z15SA0hYkEuGI)t=vZi0Y82KCK2d3cbw*zX$<{`N8G4m=)g|THz7cArkST1A|ZX{Bx zWPEG6VN))_G_!n+;gYV#rTThW=ZqFRND zeSHB)`Kix=J#|NU+DVe35&e-j+KrvPHUnyK>b1VviQ+d0LpM%=bZex9)C zXr_Cpl*Ix)9~hYAl3I;g37JM?P^6k0MfpM=fd%)C?YT>eWy`1a8R|t^vi1lB1iNpa zw@s}bt=0bfLmc2SwhjLhP=jS~T#a#P4 zAgY(;Izm=V`*gh!Y087--6LHWt0c2>^jXMNF0SS_u$I=x(!$F^|332bU3EXQ|7nX+akvkevzT zg2?fTk3yrr_^=FA zGxu65dW{iI13mTSrbAXD{*pcChGi_a3hL&71z@WpN5Y|hPC`yj(=3@1=muE&4SL$x z+o+*gO0|oCC19}i;9Y=-v{hq;A1x8nrdwJc*=uITU5q+z2)PJGAi<>~$@Pjl_ma@$ zSr&(xb{H};$t$CuPfiCUWl~!@-e$df=ZOoHKI~X@a|%^R3b`VY!6NC!Vx&*by;waL zTZ2pV?D?y}Gu)T3C0)ZGj&K@JGf2s%gIE1&&jFIWkV6%I?h`l6UFG(_4!8im?~8{} z+G(K?cqB=OQNV=jp!Ds}=J5P^r?Bk=olYK<9lE0Z?!$+Vb^|@JfG~9@1zKkepPSZ_ zi$cuRE|+zzgZ%raXculLQ|px$6tXo-Sogya^dxm zvS>F1TN2UTfnjhtrA5*MEwVILJ1o(VzqAsA>eqx=b*^5!FXQ`XV$_R+b7PO6XCD2^ z_3Pm(Hd@g(DgJ-oKgpg6?quQ2O7xA~&v-HHyrWUSv%ycAY|^^o)aQ75gFyA;^T0fZ zaRCsMyuwNoq3Sgn?fE6A@tvA+!pPB;i^UJbdcFc!lOawZMvLlgTg*zzbY|b<1rzc8 zR!l}8b?=S?k+*Dj5=Ta{QRU~)f4ehPx$hVEDG$X-2R-(y@{v0JkOh)ANy4)XR~X`8 zu9yh&DzuFUb&Uwhvf z(A3iWjR;pMVnINvC`~$ofPfSQL3%SFgrWkXbSa?+uwkKB0V&cUKxhe41EQdGDWQa> z^p5nBg!kkspjV#z{NE4n`{~c81DvxvJ3G5GJM){_jO1cPK?WMLZ6)o37uv$#QV09i zIz^W{O6KQc@2vQ19=L}RgM4ih54(&HFsm5QuD**}0aTovkKHIA~$V zTBOWtj+-{Fzy!oe_0;K^`ZGnmhuoZk@PJ1>FAPxb4ULT!fKs}id(Q=uMdW<%-m`>{ z9yE3dw3PVC5zQ4>`Dc{0E_nE+#T!*vyCYLhwrHz;KjTn3@*XOMX*;NV-O(}Uj$Azr8f(s)Tc@|Iaw-FO!8jUn1VFn zCY38JJ=U!`*0d#x)wf8C>?=0KUb(igw8UQ0?lkx`U0CuG?S)=ZzJh4-ylu+uO2bFmkcPw2#X=RAh14}q@7>D$j?jS&NB zW&LD$2HZ`s?v9W>G;Zz;J*UQHc@(GxD6u3Grk0^MmgmB}Qb!hU-H| zndoc;YYZAOL-KoM{$+DQWgDFR$hFWysBz!B5SHgYu$usd(<^2)fwFf=70reASf|h@PySLhx?8-$@|rzEgOMG; zSmoxD1ffgJAvdpr=Lm*6-4OJRiB}C5qXkY=%6tN?tLa|ut7z59AfpF%!7%Msy|Aa?E zb7dDWC7LGCF;QHVQt-{v(QgktSTBo;Ue|1Fc3}a^h9jUNeY(MU37ghc(gl^dam_R0 zsN?NXS1nejQn)0@XBlwX80GT9kA?2Igh8n|)5Zcx$T2`I(k1xlwIle8RT~>dW34T3 z04GzhvE(T;SJ-270%(A$$oC|6pt81d7_QyYHJ1$NJ8R6v?w68@uAighMiD5%P9@0u zUR*Ivb*j5BP<2Lw};0#74iH=fap ze_ms@OVU{$wly}IwSy*OC4op8_|4tb1HWNrSq_Gw(6 z*eWfjtaG{_`3N}o)HI7XcP_)aGG8H=UW;CYS(_UdmzWA$yBq?-ag%N{iaL#ZwWL9jmghcu_(yp)wtcT0?iWA4=C5xU# zr9{@)BHj*`OkmfVWiIO}ExREg_@$?GZ!%ox2De!v#(4G0+SOlOnG=P)QgJ6pu-6S% z9!?`kE(K*Lr=ruI@0LnFwLrdbPknFaNGpn%<%u4E4Du$wes>htWa^UV=>n>h7d0D$ zS3KqGOkt+66XSLTEmrHjSfjhHk5C2%{8x=E!MYghwjT7Y%Ayic#Mp*0 z<6{@8Icbz_;A$$hX4~P#?6X#)Yd|??^8t?N1dQ3NfT#i?kXo%u8c=QZ;9+E^HJGE^ ziQZx^_e={zzj5A1Bbnp-Q9Kpw3RFjy?AWnT(Q-odh7`gk1n zRiXKmuq}AV2=JmrLX}n{{SI$6BD&S00RZa4{zKPeAMYL@ID6bUE1ScxYYr6Fm z*3O(OEGn4t2;PbxT3(tQViD$m$vJ^QkyE|Bft#ftB;t%sYpho~2IgKAfe(KJHjhFV zaFu#@fJfJ>pFmE6KM=UbfdJ%8A6-i@P0?IKeg*1kcyE#6u!=NKOiSkJqPKD+0W~Q3 zN|s!xPkZ4Cb2(2VAQAM2cwFh3br1QCM|@Yg5w z8fc*I=g&6rcC~JbPHXeN+Hu$vqQ5Mu&eLdR{uC*CX+JRbn@8jw7ofJJ;l2$3N_QlP zkyqZI60NuOq=8?&wG%aaE|X|RKKKfcJ!(0jvK!I?m{jb5>%*s{H!vytBol}f)3?@p zf8+6S*{B(KrJ=B}VV@JneVYi;me-)xygV!jLk&wRFsXam_1U8iZC}@5O0xkvbbF@J z3)`)R(lIY{p~6gnVBNP!d_X~Kv8KxfeR07CC4+oGc450zWP4@#mGxO&B(rmf;4rmo3-vU(hy&0_hRhq@vOOIGiq?jD}f6o^b^RT zwNKfkV2ckgVjMpjkE9{XOprN(VHyuZ+l?`&B(I#mX+_ofS*cYp`cc2P*jV5bWZ&iz zqARRZL~n~Jp3i5qwYSjQ>BY@?_(__I`CcyV_wVHqwi%7)EhDO_HO-ODif1c3q^VXVsi2YTOLbt+9jW$GDcYYtCFj*Q^0vX&0$01SC$?`L;@zG59LF zISze#8hkMtKv<)XeH5#`_^2+;vv@9fE{ELC#wN@)(S*}!$cVRmxpAe)8zfY!Ka{5f zGJ)Byz7f=Hj^(w^ebj(HhUn6;RexNu)aGR%=2{f-!22^p1fP7p#f>d(W5n_^UUPgs z<7kXj6~t{m-^KH90{&EnzG-qH$h$?o!kIQ{>hJ74oz;m{69639aR{1nQBhHUJ&Cm7cSOsc zA2NR2DCf_2f`OJ#J+QgG(|J->KPxvOT*oZ!CIzRyKAPEahzWFpo|%(O`C_4^W$C5P z5*v}Z3vlra&9W&@dg+JBMj;8)%>$|SKM3E*@!i@n=$gNiV4|+BUI-M72Wsi86_YpY zhXLK*$^kdxrlzL4-DwT7i4NL8wvs@DXJv`>!TQTLjVhFO!a#XZ=M&*ag-}((x+?_Z z-hr})ZrFswtw~16W*6S1z=W`!ar;6e|+#0s{;@b`s;tm zJeWH_x&Jpe&B6_O+mhBVU*Tz}_t0?N53rxUG3Oa^=|+eTRgm_+nC%;t8w8X_Vyr-D z%bm9#!Hm;0-Z>M_yV#u*i<*A#`Abi+C@gl%T1Fq#Kotj|0!qeJ&p!gE=jdL06ukOo zeoramx!WYpX(!9eW1SoV4gx(@XAodNoz5>lAoH;5EuU5j5;}}`WvW`1RL5gIs%KGX zhlwfWhwW2+oP>dq5qJAE<*#SXZlIO2@lnxI$p;u+d9)@$)AXL;9>(`;M(j^;d>3{ zQ(2_Yu6aJAKS=@BDANOA+USwv?^_8>dQ8A|#aE!rV>k@b!I(paKn#@(M&R zPM(>fqjSmxY5$6#-J{A60>G&;0s+jXpF=iUlF`v>Rb%KN`#1YVDv9XMT!vNzNLXgC z%rUVkpZt0#uV(R};ZpPHGCh5TdnIitDQ1h zf$HY~&gHj)lmk|a8GhO6_C=7jZ5}`wVB(8Mc+|R)P(75xtoYjH82kn`0K)2f7}&9Q z9Vx)MdbL<~I@yho4-b5vyL#!|B_bCx|1nB0P1Xw+KCMft2meC#q84jst>fwCQ-=^; zw{JP*lN@8ZAYvNJzdYz>4BZ-~evkuS4`XTHyEM6aoz%msJU0L}dG~X>9&QbQeVHMc zZ@ot()*KAnS>yy}Y48#w%NmC+_)!0K48+0K;OQHWE@yh5?;n?Du%v|+t32Edjp0j` zp1_e0fM&)?+xXqxopQO`N6*YWI)C@>iZQ5t>v#yhJ}|QQ&|wY*PYHGtj0=Ytr;yN@ zU9{*gJoEK!B?xONchS(-o_sBdx8O&oyE;EdH5@)A@l}l;Iv%qo625=Y?r@>pn>8oB zdl?r#&!<9+F21i7pyN6?7mOLmL@%k$luCaKfK0Vb&wtm^0dsB7Fs7y#C7rfPPX661c zH&Al4;)G5xo=+0%5iJSY2F)eHJE$|epvTrR2~f)~aSm7NPNb4X#{qRvhUZt-sUhtxADF5o(JYUH4OL8)_9{iG+7>kE|=br0hqd@MK+dI67 z?!*%k<%UlYO>gDX#y3VR0N5Q+0X*W|_xM$s8mL-z+u!>l)`<1Sb}i?xv2fz+teHq8 zdW8A=%a_t{&8}5t8QkPK;=-Mi*M(9O{E^=G4-f1j1F(;q zh|oBHh>^3qo@R5aSPNp``;Cur;TKh#QmvWjbshl%h3SL5&w$@r9YE3{O~7XL;87~2 zqV7q{70Bw=!{H@;uKFXC<@a}tHBxAdtR~XB#&oV;r9Xuu#qjOuesWgu63fP zUbtK9VXD~ojqoIS(j|1xm&2&K*89wTmje%)yURcl(oBSZ^dM_Ks_JS3IR)S+Kr@!f zpWW@n&zJT>Lt{t1X&x@1?!ehHCgA_9WhMie{bK7ldrfujP8?I-9|tqPR)H&gFm;PQ z@St3X>Tue^04Ck`3rsq6{GRbSlkNXTz+Rtw8`m#lMEF}Z;h@7(p#69Kmw){4 z_g@zU2r6In?8-sg+&^Bu0oY1PHm48TTYne83WCk(+I*z)p!zWPmHd*Dk{~&O*}F3b zP`qeIAVXSqh3Y>IX^$2MWuS3YHS_-g8DIh#t;Z|(P2S(>+$X^3)KM31x|kD3h5U*W zq=D$uPEPO^PzW&0eVO(hztG4tYl~0AH9E$|{6%)Cj=805Uv2*~Qy{!ju{^&$jh?d} z516rNOG;UFT&ClT0BZHL%}HL^-zW}x8Xh2sqbGE7;N+>xTa$i3nV*d5T-Y$2t2^Se zrRvZu-zE?<*L*o+5g^$q4|v9dAE6E(SpiCt5AfC0@KfM?w%kkWfdZok2-?1W_gyE? zpDS8#IVLUjh`6`cTP=6OrbTq1+yf{{e7;gdWMx)DVm?}*w0TCW_3#nO5C9bCGJ|#* zs&tJbMrGgD$g{*fglP-!Z~ecU06$ib^E<#~pyJ8^?jhCUg>-?8joC=0T+0T=ngS@v zj@cUAT6mD(RYBF|7ZP$?;@$^`k}ctf?_+@5-!IZyTsfu)zWM&}zYn6D3>ZYWIvMlQ zUw#0rVAy^>il30H1Bq_Zr?Ovj7=ybrD;`k{X2?p!SznRb4tV}Nq#W<%e?1Dg=Z#xn z&@8m>XAf1ZA+e#X@!#0eyi5_ZgC^sS(QN1CIVw%XrF{nNKelUiPv+a0JHK9;#(;nf zXoT2WqZq#r;M=Li*1bw%4YiZL%Ynbs&b3B*A^N)cnTOd{BuofIY4iU%%4U z5EKeH25A>m$azPfmZQR#+O1wWkDM#heWw;Ds<#z9d53)}aXPq#)@v!wYqiesmGi-o zXa~aaidSWn?1EpwiZdAnMMr&w1Xq1Z!FqEGy3xJNwwTAJv%o?%fzPx+C+{6rhhEq% zMB)1NX^ghi%q>Tqu%_1!;}gaZ;)7w-^@&MCo(xS8H0|!NnTTu7T@|*|k(Kc7W7V!P zps6@UPSvhIitI9RG<@^MY2e0`$OQwzjHLzs?Beq25^F2V(&_o{fJ;+D49*_`WdGj) zA{5A%C9nVqHdRg|v6~Gl+2*V7ZN-`sJZio;Ze4%88d=68XOxYy zf)*F=$XiSmCce?z%#gaL?0hp~cA#9JP%@!(8Ysks1_gx-sq0x-MeEISF~#;Wu?WHkF!!^5w}Nv z^?dBEmugbK+jL7Iq<+4qKDF3MEa)GTtbe@h(S`g{=~-fS&gM>1Rtpcvz2s_EuYGw$ThsX@TT3QwTc>K4@`rLv#sOXj2Yl z>^Afd&65e1g(c!QT67yfTv>#jVq}apuU#U>c^gIF$8~I=(>%H8b8H2T4fNO&TV&2` zhz>^2X15J?z2u=g^*(s|8Aam0?XmxqN0z_TEz0Fc8X^bLQ(f%t;E(I*@MK;>enGor z(o~f8t+g6>do)gdX?cuVAMlKZntXjWB-U``ER>JB<;uV%Pl-4(e5}w9yKvF)5Tbd> zOav8z^E^K3eG_vTW^G!4%Z*!&?ko9;fTD#t2NtgB;j?X{yLbj%RF?yJ_+-rPvaL+i z)!low(zbYln?J9;bsPkHJZF3{*OEwF%y6ElJ$;Ear#rqAM6)D&2Q(ejA?&6_v03&xP)Vl*K?6ss@YQ5!?u`(G&7 ze9Jw{m-!PJr{nkl^>xb9qI<`Pb-MA3=u(8t7R*JJ?{V!hm%zU4fykhjQRt5cW7y7xP3~Osidb~2~IS; zMCT?4+U5kZ7P`~V|2TgwlKRb88tUQuz?CyOJ74;E`dYqgZ^e{(_Voz#l_dar2G~^& z>1gZmPurNd=26(Quzd}^Q#d>_lxjjj6la>|nVkv*cY+wA&T}P7Y2Bp;Bh!MOlXtXo z%8X%C(iEhWHtOMGadaaGoVNh;D4OIJa9cWc4Dt0OefTABP%Z;JV`Ai6c0E6tx=T6u+6gN<$r;vR78?UwrV5H)z>5;^N9b zM${eqq28<5Z|4lUh;PL8Gh7?O$92e@Rj+^uAD^1ANc-wav&4L^Vc~t>p9j#OB;S)C`1?%8^#sE@ zzO7>CNdn7PpGV5#ahJTW&)4r52!Nsdj-}1Y`c&cJ#a$IoF)CxZ_0f~OLAex4ivG&* zDr0s&J_R3|)2G>i$jg>Q^|Va3(~~Dpm)B#^b_WKE-f>pjM;SSt*Y`bY9%tM8CN6Gf zE%Wcq(QybFg?6@ zYC4wvK?Xk$Z9x%o5xwZbvjkK%;16-yyA^ z(H2E=cLzljP;aYToi~ZWRbP?NGO)a9y%q4BGSd3&WdjO4goY*rzcLnC=)G(L1g4_q z6IcYp^UerNHw|s%eOW@IqFy&VJTQaE7X}=wT|h6r4xPJg6Pkn67}OrdM>UUQ6yxB1 zE=O7`sAh6A0-bzPQj*OV0h`;(|2QL0cxyuH5Ns|120L!2{vd}{PcZlJXOBZwKhBcF zW5kL?-2=ICUHJip$rir_`AE7i;$VfYfsL0z~f#ri2 z6(exE5o2d3DfE4ao~ND5G1f%dh&AxaYwGs_lf^72CcEwmq&_Lw9(M;U?al=+mikaO?z)I36_LljJOnL)G5=Y6OC>NVkS-B>TC{r zMC@%n5fL#j?9q9lwm#Vk#aqOK}Cw_*VKFc=t@rVC^NwEpG-fYYC< z`L>?0sSOl`V~YCB(r$bWC?I1mUobmhJSAkBgSI@-6G3u?;6}(|8pCR^^5 z3QZo)Oy4dl+?q6y9uPC65u4V61qX_FH)Hg{vYIhoQ33SQDim0%c2n=gFINcMHa&OGA`&!#yP%Lf##*+oNE{?ul_a>A>*ZvF#O`7PIL}htN zbZ@g|d}a%Yp5^-5C$$I;Q>;KDs!)YO7(7wvMMZ_C`U@?9Fzor#1(Z88r<&y4US|nW zhfy$Fu-+TCrg9ONaCGk0Ikxp+JM?5|;!pX_m@I<8beo<4bs5L)QS8VzM zKX15*hHP&05=|scA%I+b<)z3R)G{gh2n7`ONv`7Iqt)!Z$1rREEL!0W0vE(rWq|yVmRK1h@O4I>i}7r;M|?WI ztzg$$$XTQc;4B*;`tt~}JRk!^cK|J(*kZzsg7>9y`CGvtmNFi(A6x@N$J6i8r;$GF zimrsE=3gV=54$;8l`3mD(M68+78&fVTc|O@S{n!9myd^2IUPvS}vIE zbWpjk+EZ9yN1@4jL|m&jWLo<3@KAMY$mjJ1xa(%q9i_Rjy^<}z>@+8Oh_3<}hPH3C z#?NGCX5MITZ)dV}_^J-1%TSblI`xUz$#pI?QWnQ&Kj5j!Dk22=c~;0jbu^eVvMl!T z)jP0m6I^Bx%Pg8r&kDx4A_A=}E7FVCo!}f??=q5*%nPRsa%Cba;i>x>DPp0>+*!*^ z3A|DXM6uG6lH|g|!=-Z{Iqq}aL+?%aqkKpH<+AO$Y9aSXNvZ7=Wqv153wGA zEUDJ0T%fD~o4=dwMK-%is%h@VXAa5I9z90Up+t9r{QfUY|H)lndw`>>&F&PL zCQ777RE(~Bmx}y>s&&zN4a8$SiP5y~?1Mo7a0vWl8ybQ)LMzPLgQNNV7I)-0g?p}Q!`W@@0m#NUI-btH+Kl3l-N9-I3>coS1kss z&3aza@UKMYu+(~m?UBVZ2Tc6%GGV5np4m<1KmJ{m#PVUL<}`SOFH-nBtFZJdxY!Ipe*$@Ic>mjvAL1zRwpj=Y;`qovCA% z`3HpuV3`u81P2*rA|gt-vclDyjbH7}%&+|Y@*sB`;GT?UPSM}}7LZ4`w?OlPZ%&t) z^PV_$nw{;`2s^^wG-jhd21$Qo-&KCu27pwYbZlXEz401?UTAyL;-AaRbI|g=e95m( zo>$`miKGUrG1x-KaER3rZJ?vC%RhwLvZ@!=Q2p8a;?CTFvHfY#nInsquI1kLX$pfR zBrpCF=*+wwaU!t0-y!Y0*&^AB?xg-OMdte8gKv>v8>A>No@031R$^NY_RN05$Ry)EbA+qbOnw}=GevNl7gzO;Wm3W<=u~jc>J8~QPkpg zg8`8p86(p$rEg9BvzZWE*|yI4(=A4LsA+to0kU5mhNEPX7sR2 zIM*+jo-+%6bMZgv(RyB8(B1k`N!;$k*i5$>a-i=xRR3FNzuLJj-td3W%&KMTrw8xG zpaKi~APa+)mp#{P5H&l2eS?E6Ruwg4+h6h2?qn#G)k%uTGSbmbcvZod{r(uW z$f2+H%?$U-G%1)cs9JGvV~H}RINa5oh55Rc+k%j_pXey9)8^dyl(sQW>^QN~tEQUbzWmTgx^eiAs% z)wWc(xFy;gK(;GDJQT&e!Iwh*N$Nj7EIfGvf3Jg_`rJSM{)-#}UC6lr<8zT>+iU#y zfB)bd!J|-%WZ%M zT5jx4@xeWtv$0~E(`h)b{Z7a~n)aIpcs&i-pY&Z${`MX#Bftu=T%nWy-sMfY6L`H6 zk+6SffA7(wK1C0nzBsU_Jz|r}d>2c~;zR#j$-n;PlOnKPsPn2l`S&inNI6;XNWfN^06mEa}Z0)h0?&_eCx=y9C+tBXpeln~s(?-u-l-Omp zA0=twQ6H&zjc1qA_qyGEn^j2JulU|*x}P$nx?oRGr#XebFN*u6)vq7*oqm=^oaWzXswFdDjzQH%-nsNo*8KJwNdxT(eAIwX*WUCUB(!ZO zfYl+-kVUyWWe2wT|Gz1}x3xnxx7$vTTl`7&CH3k)P={nT%P!4+mSmJPcqC?Sa(%nC z50$vL81}z?{aVhjT*dm9*zPxnh&hf@x{P7wAZDJPT;nuRKE^$s z_?;qoM($&2X=!F{4g0_NhRUa-oJ(9>Ts2>ZZLhK22f09!_E?Z%`6)a)^FjLFq7sUz z*7|BMxzygSlarhKaejVYi~8d0U5VMB>gr6Ac0-V1k&3ncFM~@1DsSL5G&PknI$ro6 zKTGbbDq-FE#}5AK7Aq<0K`u|OK^lVhmtpFVJfrfV?)>)c?(E#$N8I+hG;vvkh*JEX z=pPnIk^Jv&Be;eaeB7n=zjqMhpgU9cdK((Bu52NzVtL2cwO?O4#|mGI%buw^P5K6pSvHkc|jl0iFOO1T?=Y=yWJB+ n!h_snK)?QPQ~y(5;SU|*v}7%{yVgep{3u`7P{_M>`_caa@5!?AejJ-ZOH>dZ*hL6Gs*_&coODJVUdMm2t2{Dd+65wo|=*p zH=j7?#_h;W&fUTApxESQ{{~v}b!`ibAy>$#v9$p{VU)oJS@csz5rG(0{Oiham^mVd z9im>nA>&K@sU}{X{L@Q(nf)Xx=GD_h+|WeANR|<7xif+Fop+0Bp9|(mYd(EsC&SEt z9yu$?=Pp3{Q|NtFK|H=ynG6dWFK4L3v4qswQ!L|~kqlJ^#|6=`VsrM+jlKAFR45BZQv#7!66MuPcR zH7xOK41_fp-C9Wu^#1Sl2a4SFGV()K zoPWR%Yq+b0X0Vhsq;v~zBw|Jlwynz*jXk2sbQwkX?mbeFt0b(E57uz`++}a3eV@y! zPl-D!Vbh(&^eNbpzQ zlXpXZnCOCob!NxR{DN*k7mGFY?N4M33QnHttx~Zt#ONwCYZHbnCg;&U+E8cm8R3i7 zkL{r#Tz!+gw?@1O4g6j0UGY_pZhyvm z>s`)KF3GROOfda0slUn=f?uw61%Y2Bo!gmSKmEar z`mbjm?u!(p;YyaX*{^XAWrX67uHTlv)#zgB@_t73kl*0>5_;dgUqfETOMVkmTf}?r6UMEY&{)rTnpb}#63%cK(G|b{;(0$yU%Sm- zo>KXIdCQ%O7tUyF$a-@LDI!aF@dO++Lpr_n6}&x~JIlP!=yP8(DyKKjia0b5_VR;~ zq>oy3q#=T0ZkHzdKFc6G-Y)+2UH9z~6|RgUqqW(+KZ?tSoq22!C9D~najzOi!HUq4 zx0cv4IXvqUv4xW265?2l==MHKOZP(C6=H=_w4~?_DX7f^7Y{E!XzQ5?X!Zz~;ilv$ zTNo=?A{j#r(Vg<1XyYNTG})@@Gh!LXfKL2$3}-P0_EkcuFg|<`6C-(dn9Y;Bc6m66 z<_Bsxf?uVyFb6t4zu>xnvc8IZA=<~mlfx1t)OaJf%G`9PI=uDunO8VfK0_N;-d$`a zCcU>2+f3iz<5)$CG2Q8=C6Md-_}~$>vb?}uCg!Jh%qIx~HmtQ6bJ2P%s06n4N1pUM z3T`Z<2^QzXyn(H6^E2ic65Ed;0Tx`iVcwy=%2cn_eGM>%Bmu0I!+ zSygoDDC;MD=GLDp^L)0^FhI+h;-q|5T%twvS+#6>N_PrxinLrvA5Xu5Q`0-n>75gN zmvTDI$wrt+xMW@d#tid>g*&B9T~77yrtWfk$6dOd5uUM~W$j|o2z}tENucqkQ5EuW z&PHsHKXNp2!gV+nqH=JXlq$YRj~E|v;HF6v$!o~*$(*TDoT{C$a<+9&aXgsb9ot3B zO!>@cjOCV?7eLfnRq-Zkre5u>?{ZIy=Y!?9Ch@=B9lCpUH%4hHu1Vl0{P2ajrFpws znOn}G_mXCS7aRnC2&W7n4nUrHKupmN=(5YKQ_Vf(hbfvJ@kGg5ul2A5-#c1Zrr{65 zsc{$X%oF3@`EV!vj$*_fu_pC7_0EF}8e7^b5ec^`XEnidk^2vzB5wS_8i*3Xo#s>T zQ;~pi_j5KSiYuoMQ>tD^T&$`q%yTr`5 z%-YQv%v#jSADA6r`_LXpDBXSD98VrsPUAgk(Ua?F>0oJnGxoHXX{cbf;OmbKhm&!R zPlmBFl9ySZVyvsze0p20g?it{a?npoZNieOC=g{`JM%`nvz;~I?;>%K4VSGU-{tk7 z!FQYFhqYtH(;F2PSrxOe85m-Ck!QGS;($#)=5CKsm)MrZYa}>tEqDt3DY8N-tQRA` zL+U^pEae+`9$QD#%g_i}wC2<0i$fSddEHxlGm-a?co`@d;xto6Su6!DbB{VpPG!}3)AY;e8-n|FV$a$d{iBa&8PVK zc6Dr(@~h}vgbQzL<`Tot`vP1=JbJ7`B3|;_pPno{@h}35(a@8(b6#1zRebxTkcnKO zmc>wUIleYJlid4J<^wuP^SfvvJGG&q^tzh*S>>8m>y@619-f$1T6a3WD0g)&)feiY zHT?3n^O^)|xE#GEDvM(JFZc!&{k08P5OJsjHq~i+xvf zD96twasJUrQMlvV`tJHAM@zAUY|arm2}!sBJa6!4^+x;Z#j(Ljz=g$C%9TB}1vQso zfB;;;(DvN!!Y0N3jKJs(@f*XruX9;-D_aVi`$N=2>O)n7x&x|%&g4#n;J2&(|C zD6fT`m{M6TLhegfT$ymmPu?Z{L;ivcBUU5x60{jPGOgZmbJ;lHmMz@jCE<7hKKtdP zp12;an3WOD?3K38*IyTL;zI~7i%S$>3TB?*f~~IMm|u!-6zO7mc`Z8rm~uc*pJiAZ z`_HAZF0xVu)1Btva~X zZX)w!V`L)>p);d0<5NXsifCF6LLZ-5irBa|S^O~6Hgwc#ZaPLkU;fUO6(lW-6zm>)NgjdMS3vRS>I1&8EH*JN~ zx5;P9(zA8SZw~DV-f9|IGYqQEZrcqx8xlT;#UNO!eV5;Nc?3D}x--$77c5AuuHSnQsSq2Tc%s{ljurj(g5Z z1Bn8$lwTV1@B}qM8o=NKu?dnwar~aF8`bUj*j|ZpI)Po7ZZ`&o`-g`!$ECBNC_7)u z3krbz;1nPy0gzCW?5EhYqZ^xuK4hf;_BBQ7(Ouh3LOGtRkod#!5K&Q#*+x3Ij{J5L zPLQ@9=;tDagwOtK+WCt9^AsJHE=XtUDs;zxXLTh#X!JsUSvD_BZ<_il=$a}^K3BMAGyexm_= z-@ZNq@7p&2{KiU*0O0|DkppkPe9Zs;HIZCC)_))4N&(kEPj%&$m4R7~ZM|MG`nkHefhGK;ng8(%3E=qlG#@kLKYrrnEX{1BuEi+t?rF;?0$9@%W*I_8 zMn)-58#@Udh3Eg(9QaF`*}==}wFDoZudgq!uOP3xr#&CPxVSjq69GN}0UqENJYat} zuUCFNZeW&w-sHdUqhJfR_H=yh<>>ClczfShR_@+j(#*`a9sSSipU-LQ=lH)pxq<&{ zSik`JZm;n1^FHDGpL+vMrEbqkXgT`Xx)>`sx&m_s^dZA9EG{DTj|Tt0OaI&Dzce-a z-=+d$Vo(0H>Azh1|2EYJ+j`2oy8@kh$^7qv{a53Ez4%`ZrTA{g{x5U!&x!uWSzxAR z2&MS`XVqi~CkMGkfQ5YMsGz9_d;?~7`@*6JJ|6$`8#u;N(dd)J1D0G4q^$5%&ktjN z2``;u8qxc^?w#u?Gkm^gyy!6_Ga<88ZwC$;rR801xo9hSIjy_*h~5{@c3RZr8p?(htS0&s|33sW^%d^im#9hSW;gr+bRBEEGd4J+?O9) zFA+q_rL)RWRQMu`5BCFD>0>DrKw(luWT7L1)Un-pnZO9di#de75z6 zLlQkd%yw8X@!x6!HutAeocu2=U27XN?9Ffsw*;FAO4BP=K{BMU@YBh7DK|o7gcqK< za0lU#+VmVgb1q74d*9~fKspotVL`zDd2+^Sb{d>MBvPJ{i%VBPP~ef^Kl|JH$$$-?A*Y&~Y*e@H>Qbrt2^)pbE2oksRZfPKbPg8=-^GWA z8ibFCc^XZ`7j4WpcYLYqxM=q2yn{_9R*r)&$1t6im!$L`cM_J!NcQCFVH#uc&!0Jy zv77{@1LF52!??v0Q&sR=X3a$hh1!eBKTTU z!Qin1aNq1qt7l`&l)3Oy7)ARgrPbD~Fo3)Afcf|QDjc`{3*7A_1ZGF6w_By`k3v*j zTup_5LVh2%fS_PDnOCiiUC|by7>ZB|m1$^`v(<^uNag{!D$8Nw7}H<$!6=3i^22_q zMK36^J2jffO{wyo+yiW2<}=9Z=?5fN_oWYM)GvXZ;ryb9Y?~k11ICeLP!Q@*6+Y#&?m~CGYEy~ObA97-6(o! zVU8&ljPU>G7yt?*!~a7h=X|!+^!5?E4GrC!PhW_zpRs&QN#Sthh*YC=So##WJqKB& zA4W*E#xh~{nCF*Jyp}mhkDh4K!4a?0@fRN@4U@7++Swz*k9&~xt?2l`$?Cu zw)Oo=D#)wbl3C*YU%=%0{a;kUGs4zuAoQzqx5 zo(6zeL~zoFps+SV8(TY-fdUA9Rx@7SQm;4bkz+h@hFtyw{A_(#tyh_;yab|5y9l1s z>{t=h;8Ah)#o938oJ9|h9Yn{ed>;N6EAdvlQ~FnBq<5YMx9)NVMG5(*S5o#Q`U2P_ z2P+46U3^HzTjTfU0yNX^V2u29Ap4w}&S)s|nI~m@cS+1VVM0v1j@@QgHUl+kmQ5hOTgd5AVwxvI3|V_%!Ul6 zO7nV9@&tB4_XQ1q`z5xF4v4+NIbXWQ-B6O}QQm(8Jox0VNhO^d7fZdR%3ONzcX`a8 zcIwJujmL%uQ*`v?OeUv>`6Z$Qk$O?cmG3 zhZqha0z>~fkYZpn>)p<_xmO+=h^~O@gIhB|ky;-=;CPD3udVGlsZ3mih$4Q(#MWYz zZS3^Cq^;Hmu4Z0mA&?zuAFay*GS9BQ5BZzu@DKypS@)(%lOlAJm3-$G+|Y#M9c_e< zzIXTW5XYy`YJAQ^sIyq14MT2JODav+IjE`cj_19UcnXquz&i8vKaLT=&|cgQZOQX? zXiur4tN+|%1RW&3%jnUQMpa^*57j4l1UQ8rqg)d6$te1QLNJS93RG;r0p zbzdfjF0^`e=mRI4y}W3=2w){j3zU3wTY-c9y()PTy(#aL0Chq$qc*_2MvMxG89xQa zmH!6Mm2L+DUIL7xMhz#*vpjKv?7afeO@g2Pwr((XwUd?-Zf_=wdE#dT%K(Q*inu*?EjQ#yz&>d>NapXT zOg!KyyBin`nA7>h82?|)ZD(UBvBW~L&pZi*swBoXU<5OfuWSea*jzgMtWz8<Sq0#nU-^`DbQ0ClpFEv!bmyz7siBut)6`6x ztFs>r#lU(bEAS>I6v{sfccwt=g8OK%jJPb#62g~ zMU}HeToqQDzShH>5d-y(lj}LY%lsIQN3NG=d+g!3#K*Y@z9#W-{}a28LF2#hLHxI> zx32K}AA@KRxWl4-YY^2cz#Q6MUtQR-=LH={E&6Ze&`Sng?vxfgBdYBz_GYSV2UB_I z2Q&IQI%iWq6v+>lU#vXkUp&s@k+j*??09ZA$|3=ROenMWf7bp~1Wfrw#AGS$^LTom zyx_~SUYUUNeGZoAvA@!(9G48&7N=;(Idt=?HG{a&tq`gHS@fN8P3#Rer_;8l_Q2TQ z-gY>#YrVeQlP5V_aPLrtTEK0#MshYce|^Pcz=p)y=Rpj<$1^aTURM4M#l4q$3w7uP zM@cnq^JM@O7JyNGDD(b``m_ z_pV-@MWfqNQ6TbAr^0|o5b|sF>CRGXVjqZ68!ddWY*dv z;q*0U@oDKQDXcA4w*4xqDML%GkF2*ylyCMlJ$SV`;oUQm28BNV+04}fk}&u=w0VtCk4Ug#!9`H7 z-LlewDE8dP0Ty|Xb7QTgDx;dh?7+ijyQOCER;J4QQ`bHf|N9T5{Jty(qYjRj1CRQF zV07FD(RLjxR;3!xGy1cUW@&@IJbSel5&S~-cQ?gExjt9MlUHxr(B})UBz+!}7Fn7F zqt6V-*}vR|qmUc4?_=N5b~1dE)kIZZep!z~T9^6ye*Z2X?Xd;iy29YxnX)7_m~m%k z=eVCe54(|`SCISEfb8Jfwo=jkkWg^pW&@N?qWrh1*Z?at%y!$A38@BFO|G=U0 z`dHN6rtj;0wD6NvHK$E!^pI>EohhiP`gwk$4s20b-G-?VtvNcUAUPzj_CdJIdL!~z9-K+F1fvn1N$MxS|ARz znR=n2FD#8sWwUw_M^ISKyd=;aald6bVI|mGJutrep|1V_Y2d82&#{ub>MnA{ZwQ?C zo>O0iGtPft$GtKG;`dwA^Yx|bVMY4y_?vldmbB_2;f~LC3TmLs`bmu>QrWAqwpZW6 z3fy-mHD#BiU}XEhBS`2tkJ?dgUn-PN1AJE?ji)=4O6La)>>p@FNy?%2*&Y!=SHFAh zmiDS!;|98)mTkDRdK(;tVc`uZF+h?#a_)UKpb6r&Y;TkLvl@PUxd)A`!n>rIK}9wk zEHq{@dd-s1cVWTYSC+4)x-CP{tP&dX`Jb@?YZ65yy$z71dGb>3Me8vDPO6A%^I;iM zI*CV@bfFRdp1*z+y^SEIbGO*4%k+5w>VwiE70zC$>peRjsDNgDEJj|_ibxsD1o5@@ zEwSeX^U5F6+tpgb1ANjDCGb~-k^%0zvy*@-rsE{mv6#CevVIu2k)#>U^*m$6y2%~! zqwQSacLqVVF#|+O{;(N|f$(}152&0F@6)ukQuQpm`z`=FkI3ExDXXgsD_Zci{d!hr z+0pJWz10&#HTVXH=uPm;{Fal<_RHOhVjzB!GcfR74xS!$+_bwawdj+RldtbVJ5o(x zwc+rkR$nTfC#om+Uc`P#FkFCrTpLLFZMJI7xs&LY`1%lsUbS{2{>Asy4puOdH!50_ zjF>~ouxz(EE~!BLSC?*L`wn0Hg|_X0N>9RCw*Op8n{Ee6CDH!RXwCP$B@GozZ+Ndv z+*QL6fsyPU|0twzihx~pZsE{#SmN}%p0erbC+GRNtLB^h#V1?#%F3f(>Y}|K+{JK! zWGa1&0lV4Mw8uVfZRj3$qzo&e{ zM;j+!Ra`UQ0cVavL+ojZS_X5x%%#J+#VSZTa5W5XXjEsLikhyJNlWim6<5h!WB#`! z?JE)B;7eTqkn7A5juh^9W}CB{eS1*4yECa7mqtQ2Ke&Ii*%#Ux@gh^VU>3d57YXQ?QWkzRv|%5;~5`x zelheqaRX(9oe!RbpNvROwE2VU@+~`pkLT=v5KQ{+Oep3;L?j=YCJH1rzdMoLI#t=& zpkxQ3EqSW71v$Xqs>CbAkzbObvT0NPb*y`1U$ZYpj9k!bkA4>p7ES$TZ{Bpq*@nc& zCs%&UMGksm9VN|5oDBs~hqxz0H2n(w4v-x*&eRNl1gU)bB1; z)*9=ykkUE;_?Z&@Uv@Y*qh9c_gWy3(8KkkI2tBY~JmWI{$Ln8Mg03&NJjWHOHg=i} z&An3yN;e%p;hSZEys#~jLt3Yr!S)$Kj)|2Pa0yMy0hS-J(VQUHQMgr4bglg;y`=Ge z#AO{hd#+z$*+})85O(x!Vx-*l=*W{osM{0AaO ztHoKRBAsHD=JVkF8see=m{awIET7qWUHKW2u0!S9~s1|XMwZv$cS`nt`D>hh1E70TnX zcQ(j01e6siD$csvUO1SVbS%%1_<3SZzfjmK=+}m_=Q?uwx-llsr(D=K?T>-0*}K_Gr7+r)bhy*-gA7ds{>B`pT?EZj_eN^E~+UVS0) zX^~Ezwc+b;JLB)0>b34ykMs6+h9c9dlSyyp_kI1vs1y`H^X>j!{yzgMS(M`X0Q$E+ zYaLH~Id-x+oJ21jfDI2Ws(t~I(1FJGrSn^_&pShfQ)0c_#9)Oaa#ZYGN9_jS_D45= z*5Wt&dw|x_!54q&YJPb44(jRd>w_-CP!auS2y<%Q$54!TyZ`?E`*`wA zv&P0xKjTI>xY^X1KwXo^+H(Q#ffEgUp>Z|MkTo7^;mf;7^%$F=?q7K8A%>P45vf*g?AxedSm{!tYZv^8!xG|V=uP}dB_%Q1I+r{uO87*l z1N|&f7TpP33|v235$$_R=?u50>i0^(%Lgbc*DY=LU%UUVbAPU`7=k+Ym+)F?huCfo z{rs(qajjAL1#2uo-ff~NYO30N;VP)-`v+RZ!L`!TQq*3e|C>ilOi!=>tdZVk&BoBD z;kXlpibNE82zFBv2ATaD_;Q=3@ace)~rloR6lLRKi;H9*~q;j%s}a|ds; zKt6J4GYoU=@~ze@3(M9JNYxGl(k`vJqv7(RoPuIFEs~g4q{*H9{5My1(=#A7 z;!{oIrKBVEp4_YYx(g5^fP`5zLQu6K(Q+%+K*F~9@#g9zzPbAR4||SR;zRHdzn#G3 z1;JY!qWiOo^zyLS55w1Fi!kT33-XPcHw$mueP~48TnU`B02-s4d9L_qq_Db}< z5t4G@N;0qyS5?j^1*etJP1vKCW09NGr59(6r@YSD9xDisr4=2qk?{f;GMx2W1n~)w7fHLj#0VD2S7mel zYJbAHC~8v3WxrKfKXH6r%0S`qtnX|6?EG2LqB*kJK>hj;opR0z%z3^!>_v~Zrb;q6 zWV~e1i|#0OY`LstMHuz!!|8{R{sjF&)*4-(=UaUY&g-2;zn8OKlu>A;);2C}WJ340 zTdwCtvl<7-@~}F1(XO<+7mDDv_ zt)#?CyXSoEe+o0EJ3>O5H&RWD>P?${%$3~xbW1g0SsOG?3}+7vEg>*Jq{mW=x7{3& zx`SP*;;3m-r|>XOiSlt3&^XUd=BbDu`y4JBPwjV8Xb!=egSB??5CbV(V4ga`Q{}u! zhF~!S78cF+lrvy5UKDbC0Q=?-LZ2ZHO6-hg5s1SZAaS}!Y}g{&ss=>?c%Pt&AF zwIC!1)zonO-1<249928Wn`EEs|GjNQemb(K=n*&`esw%JOy$^W33>2py)U56IUqgWil6&V-v!e1%VomsLNM)SDvdq&sv29)UnvbFb68&%qPRAs#MhTkw*;r; z^4LyD2%J-{-Pj(Q2K36Gh5}P*K;GoZNWawzHspX>`56r4ELbu{6hqF;v!MEOMOn=tbYj=2>%`tt}H z1HC3PfB?kPCG>Cir#|{(9EBJH?)u;mbUG}$%qWj*AGv+Ha*YC5q-DrS)hGq6&{#kE zw7s8uZvom7B#DxYKN~rEohx;=E@n9MYQKryW_J)8P)RWo)rOrHq4G#;C zNMHRuN%38^*>hv)3Sp7QYfVqLXHse#vng;~fL9ENqt*UCHob8nHkVoM{mE3N(f6TX zcVZep`n{T(we=0dIzh?hK{t3+p6(dH9X5B^*Y!$`vI5=g;1t<2UoInva~1KH;wg7M zfFc$}VZ4)T)KRMdlS!W@Sfqh04|$&^c&0Mm7k8w(R6JRg4?g8izgt;1A~459yyZNJ z8DePRUtICIaEVkt0Ws>zQK~l-d~`$cb83Dm*vN(@3Q+fX6yskmLVM8o<0v`Y-jA*K<3pq(sO&_ z{x#CbvowJ0NHu_=W;q*ecIS(-T93Yk6fC3!o~y7 zGm~^*mfD#r)6KnnVn6b5{9_g}QYF_%=PehN0muYvfQEUhMDrdR7;s5fwalwRO5Zc0 z)Cey7q4b2keb*OfHNEtLqB>PB<WV` z!Amu`L><@j2L$+ypB&{(+^6P+94hs#xeTkhFT-BS&i2Mqv*?znc`R^BeL|S~=ETxV z&+E;>Z?!}pt+OWNayD(HLFV+yjI&k6jg#V1MRm)-1#=w}!b5oR51_2RHyD~OVTfyi z8zj!i&I@gSE*QEYl%twCgF*A;Ft&j#dn$-y3=z{Va|Zha6*R>$B5v{CvrElLB3!ei zxj(HkNHb)(pe01yva4%+zQq%Cpc{Tf6N_-_oG0W0RfTNNpvgL1K4dObY(_sq<)u(#YfPoJPSkWf*V?v-B)*d+7bym?Y#EwtGYof zz=l@(Xx-a+SQyUlD2ORHW+Hysawz(?ibe>-AusK#&3b)j?yz9+ z`J6o)`x?AqQ&?#7hxx@^pft~$QYMF^H*Yg_F98{8m@j@$gaLAz;J~I7(w~)Tx|*cn z3KW6(oNX+sD*haGV=smd^rH^w`1J&kwuWX%SUc1|%A7Z?nN?g2uN#5<`Gvk5B zoh_M)ryG^Y>)GaxDcj=|k2rakhb9T9OrlzTerA8fSyrFn`|>!+)8?Q&+cmq!)Avrw zEN*X>zmfrO5*8nBbyEkcxPD8pIKrAiQCNE&V>?68exRQn)m|1sq*xK|1RHK^078{M zeZY1>o7?@ndsNRsCaRmxkG16oB&tP?5LBG(FG|BCc*db&O+Z%Crzz_%gYy!rl162Q zv*cFJATDy6EU%_{E!E?H`Jxf=q&ULZHAN47JXNGj;eXh?HPk}m0%O2DT%DIa$TH}d z*2*=&YS2#=#;!`y6@K{{!?G&95{+*^8Ql=Dc&n>{33_UTuPy;W{tA^u8Kb6U3~`w( zpLFj)HxP*K;bq{8E@c@^K#t(ZSZE6|z0@o=7t9JOLQLvx>riD>H4XEIRMqc8F}+@y zTcR!r?uE`+?`cMF?`h^4)gBba@Fte#1`M3u0NVSLAKIZsF zwmg+CC3R|Q+!#!YiKxmF1_$f(h^Mw+pP_BI1Og+?!->mr%RyC80%BBood}$d+vtnj z=?@CXQG@G(!D*Dh0-I(oH%)Tmu;j}&_Z1n6dIXk~2_mHHErE}Kru@ku*zfd{z`+Mm*G5lbE`UfA zZH|cS@flyn5G-w)?5t2PK|2f%J49Op%Ip$xN$J?~Mz6Y7cHfC~Fk(2MeZf^%m1s-2 zT~)t0_n#k1{%*%ao{34+7r)Sr=01`>SJvgP_$+GmG{BfYseE>~?`F?%4zCPfEPLk? z(_k}%&V)1~#`a1&ZhWG3u6M7jycNYO^i|`TT`Wf~2lNho=<>;w@a0gw(~A*yQT0!X zH*JKd>{k#zT*LOj-rr5+o&5lbDb9(^o!9OrouixJQ^ZgtDZ^oVx(8oab6PgL@{Pg3 zxrq%M1z(#2xuhKx=7_|;o_6~diDd;&Hr2`%HwWb4L$&w0l-P?}68hKbN`~dkl!v4K z_&-;tls)|vN1#i+^nt*?k&1R#LceZHlZsJZ%`?}}Q!IJReKI;WF0h;*89m2*!zVn70?6GSBDE*1b>~+{E;iw6dDVOb@rjo-)p=@=mmdoV{@GlbXtwx3b z9-(cQij&>IXV5wW=?3)`T^cLc-geN@7w0cer-85wxKP$AT>22$v9;NqD)X7RQ`Mp2 zux&I!%ZF_z8u4E`Wd7vq z=bucrp-L^qmbjMo0!>h>*I(izexJc^)e`WFs_)hMdk29p>~|q!1~v%3hJexO8-l44 zs4aTm^TxAWfB!6|inwm?Ms5dUumYZcc9uDor#`+4JE)L(T$nO>_5*X_^ebW2%PLZ+ z0}2q)rDdD}|C~erCq*@VJgao?>j7RH2l8qK&kuClvo%ErOP`%8_#a+$zI!Y@CHW(2 zzsqh^Ba?enBZwE--#k3N+mAkKTN)Y<;p;%hVF+xYei<?@3p3puTIZXmh6hDz{*L9bAzcJq*9$a4 z_%fiXEH%$(2u)c*Z6)=S)ME9nByzBdX|X4%j*LeVj!Jg z{FPDsI}3`;!J0Xl))yy|Ci!|eNSW=ic1Vg=^4(v*-`v*C`Yk4t7a|I+<1DW_K%eeJA#y-kNW?$$6@ zym64c+Orb>vwLDE)qXLj@uek=T65)3+J4^0lNJtdD|wCu_R^QT%lt^y%@H~~^N;&aXFx3C{uV4mP!1@iPezUDWLIDX>@(+I-*4M zh(ou;56WzE;P*Y2+OFNe+#9+o6>#cc_}Ub81U2{HND**b6r-S-Vz=E-dls@6>C_%k z4a2O9_$FLg83xc_V&&aEqtUZi!I9U&29LG|Qw_dP%bf!nP7$E#1WQlpeSqQo3nK+~ zarAjx_XYAQc}yFGnDotOft~ieryhB<5id&&L=j*1`Vv^wi%-b*C)ya!AdXq>mO+r6 znv{iufOmI8XUgYkMy5-cEQvEwPBg!&fE>qooxTA{^1xZkxWn(Fb#$A=McA7T5y^3S z+0v1ACR2bUas?zBLD{ocY{$RTd~brJ^9!camqPgEjvxV~UhXYsh&uJ&v!{1lY4G#J z__spjgybrr-bW>*;tnZ33-yJq%ZBxHcnbTqSM6+z4AEl{^Pt~7)q!w07*oP3q92=EE7iF*fkOE`wXnd_($R_LoZ*APOKk>F> zVF=Kw_IcJZU%fZ3nkqIOhXreJH5mjaEO>sHE+6mdj>_esM6sJ+3p>l`eD~QTkkx-eSn)+2;I`qfQN%P5f!p}ewU$`;0J7s=YTv}pm3y3aqdVI*taC3Ap{x<0E zT0C|9&}mD3*D6Ld>S)g00jZUT@>mRizg*BJ4&F@9!}&$^upTw8 zf>;SgRb@=Q{3X&@TD~vwj(;Bk%_~!@N=X*(eh^ne%HZ%A-LT-61k6vCe2ZbuG_}bN z?D+>80YE@8#CdHA0h8w8{fmtQIa5#DDCDdIh=V1yO}vxQb0*_r57jHqoSv9g#P5B> zIv2JWvtEcK-w$qEA@vCc^ey!>H%Yo(P`v@(4Ir2t94ca+LEAG=Yzm#j1Pd(}g=Q-c zmV8%I3gqi#$Cg$QE&FE(OHrmkIwWH1_+qOr&uYS3=uh>?ypYX-#aD|X^yPe?`^jM* zG%&WYZkgRxF)+{!;;>enW>K582`T&G;kt~NwCr($lkTBsMXJ1@OunwmsJUk;AuWNY(?du@NLmqKNSeto$FJzTk_sXa7A z9$i=bI=>rv`xP(0 zR6RtOo<2!eZS=4RIV?J`+KM}?yfeOMXWaBU!MWwjbAYC$OCfGp>NH4k%0% z2rLpGE*^!_j(hZKd-Jf0UTEx|h>5vLoy2?_ILMAI#2WhgU;V7_RcWrz%}bNZX~9N%(GhV$)hr+@h*NvZ*yqpD2;QMVDY7 zIudNQUZph%)}EwX&k!K4J_F@Ek~n2C)sDq##Ps)V_om8{D$QGGuxrk~YXjRGLEcL4 zB5S?zqA6Z1aGH96spZj1%BGO1O%8O@#7%9|g&N4B3k!;W0|f~*uYD&=)CHf4!44-& z2@NW=62);|~;e2wf3~Ggwd@3wdOE>KeJl+05 z*t6^PssV^JgL-9jA};9_%tP^k9xImBz&*^+Q`qz(d z!;v|tmcuog)oH?|7WI5kJv6lTurwbbI=06?CJ;z+SYU(>MMTncjhn!nY=fld6;wqSm{i=RB1^e1{pGO0*Y%`ZYEaqsi7Clm=KPlYnqaNXc`jIBhdv#Q{T? zXUe!(g|e>sy6X=bx#CW*hF{rW5h5<%CwL?=wbwLd)%_N{ugMo7t-zEMCT*XWGUu;^FvwyjcwezkG^ ziXA%~Z4uIJ$T@@f^Nz|cw2OSD0Vz( zZ2dKc|3saqU0sQcCM(au7YZ|Vs;mnp;6DJ$x`(Eog=8{G z95$^Di33HAbL%qa`*Uk24>cur9#OoR!F=Ct0+c2b$U3`yH=L|2x+ZUpD1)H^*}-!o z#W4E5ez8AcTdG;qUYiGDE* z02&I-gjxu$4fN-|1fl7o$y#vzoFL=|?l~H~^Lt6NohriL4IuJI&0F-%XEUbXg672| zCx4YfOu9yHYej5VJHvbgR^;Irj_F!?T}Ch`{R9XIB@qVLr1wogut|U=RwPg*^ad*5 zvIz(3<8JqJb%}xEsBCsRLP1a!9^z%o@;kRefrT@F?^cljajWtRHbR7#_82*%nxA0{ILA_9)0M{hsrEmL|)*b zcpZafh<>Hf_`YG9HpYC~$0PrM_%Y7@fYEXGvS-t$CUc$8!#c;wlAn8nA93@9L9V9x zATLkP+LhApKq)F4P}?lrnj!3*y4QYqJwNfz1ZU1bxS{t{cq&rIOLqPZ!2{I15-l_A(JrOw%WQ~b9e-xF3x#>9B^<2zJ^)8F4%IB~-OqK!F^-oM>0k8a z8$8ksM>t$E%>H{E6CUOAu|rrpHbo3<7VD3Sb}nrW&c9NK>aeen-=E2+T zyDpKrk+h{N`L++`J#3O6}hD zb!Bv`OW(_Pl0otg{qrw2f=447y(1GgDk_k6JptH=FvnmHCK6smX*sr3A8Hq2l=jfK z`l#zE5S;rN zl_bko{@?;|(yg#d4Jsk_M7}Jst= z5xSDA>Hww+HDJtewr2Nid{5%>^6kl3#f=pLx(5ueP#rgOkO#Wu_mj78e$H$kQ9Lw5 zqtFX+O%G88M5?@BhQyEKm-{Iain|f-CiJA2@;u8`W}oHltFTXBqFB4Ev1ADot`1fi z6tx??W5aF2YYH7(kF7>ShTRM?u)_P?@a>f^-sc2)StfckIMdZ;1)P8Df5)`3Py-bqD?ceniff0^ z^%*1X&Pp4T*fwC0@Md|V^xh?#z%VZTw!K|c)tcZyZfx?t&_RBcpG-SlZ>+gUkTku0 zrc9k^t5Ho#)cI$K^~()v!4;#ZZ-Vh#BL_EqgHBDTxwk>jC;0fNr!-B1dq}i2V&GBQ zbw#rk*;cCAUGb-tBmbJYiAZX@MLfxSuMd6l?Pn5*tgMM*T) z-d7c2Gqz7HN8a|PfBKSIQKVP-5I>%GIc~Vnc=X(Hxov}U@r~#0t3{w;;~C$yGLqAx zh+(ey>s*H}5R4m<_X%nG`cPgDuC@Z7Q|Ptiy>p%f$i1 zFuqniR39PYy8Z%&q$_%ga3;VJ3@#`7qQU!4mz{Oi(TUq;=tx8y(b$FXpp`%d+RxV; zB)iw^6(vIiKU>W4jnCH{cwlxa9?pT)b-a{rcI?$P&CT)E#~h|zs+{AjfSzf2oD$P`V>zIzV2!T}MDSI=y>R?P?>rXuw1BZ5KMUNlBl zJifom*#>s!{DCG>x1~gu*xaFurQ20D-MPBj10|NGi?pta8>T7%u`uL2hp^f>_4i|& z+f@12Osfd6R!-s7v#(>jZF0rp{Ues5l&-w$ol1AnHDZ^koEbqjdJi5+-(k~3?sp@G zxE=D>E0g`A(PNW`>ZO|q=zSM^i;IFn>gtHkA%^#doK}b4$DIw<&_%^(-_P8vEVFCN zvppyua|=yJZ{sBmJIeKx!%3zQ8WzU%l#(OFdbrYO1Fys@4ASo$o>{S zH*~#4svT0@zxPfaXmMO@ekzQ}G0o_HU{l30m45u4-DKM}9)|}ouDOjWif|Ma=fTVA zwkLiW{t8hXf$qJOjBkZGye0?vGPh}47|d}+-GAvjJ(PHbZ62x(Y~4iN1JWeQ7Ed}g zx`ng+xcDvu|@Dm0oS@@i*tKY*7e@+ytuhebJn)-_I6Bo~E zOX;j5ZW{Pouo;;xP>8pDIdZw)=DT7#g8GNXv|RM-TFkp;Iy)zovFkm^vVA4{$uZ`RbWh@jYzF~Ca-6571IJs)~pH+^$xoN7G7 zl%+C_mwkCU>Q?8*SI%4)W>!Qzv)|^DZG2?w)9Ir^)_zWa2N$YiBH@iqt-G76NUY_t z89n9pD!;7+3M;GgMg7T|m{jN1LlAl><*DiEnfJc4PumJp{a&!=<;I-mq}v-3rkN<) zL`7efRwJFlt`=5UHpF(B*P?=w*3~)Y6=t~x3pkmXvkv>t-QEPV9t1XW1Hz*&uczh0 zQ{Q2N#s^sD#&G(%huGdvs|_Dd+lW~!x;R?H6{Sv$ihpuM-15mHneT2P z`*6%eB7E1Ov~6@Ot5^L|{7xv&&Ie`5U~GrTj8`>BB8%UV9;Ff4TlR3nGj028oZ@W}gv^gCrD{+P8~n@ZDQ>kCDtvMFw@JQ9R;( zlX;xf?6q!huXuK?#yauqHt=z;_t)~E&?p1bT8gBa4U)sw8 zkNMYuhFsk$1#!2*QY*VAw)6)>MkOKD_|8@on|E+O=F;w-Dxl~YrkYvVsHF=aIP-8u z{~AEkol!Z{B6Cqjfwu8YP|AG%Qq;Go)dL|mKD_wP#_`-ktL`+rouZ$TeJ z-%2ZSVO&kcxUn;Jb+%avKTFC!w9DMhnxMbJK60VbvaeXyXl(j@*O8wHvGI)oZhM5_<=N;pR@RDlu2ccdZ z0a;0Oe=NUE1o)UyVezCqKVq(G^vSj^g->5UJT-ay@NljlUG>&C5nVuykz4dgJcPky zmeFJ>CEk}W`x!WzG_sIRh%$h}v9OQV1ieHFUgo=@=ZK4L2ybS)G1JVH=Bmi%*^4== z#MfTBzTqh|>#W}xJgOm&viosF=)+FOAspmfee2ZU z35uP?MZ12)_H%~71`UK}y|Ztr^2PrrdF*(*--w=32=)s}xODSJWNkplTV_K3KG{T>kUzNgSdDOBCU}akfqL4u-I1hBgy-HCmu^uYFsb{(4O2=;< zH+rYW7im+ya$_xDA}K!$`Mu}D7>)IoHMD@;zQI#YxuPBrBsre0AuxNOC%NSvY-OOE=-GwqK_KUlg1jp%k5^Z*h z&W~{P^*;8PoZ;=7gyE*OlEO04`8x-Iy>sEmJc}1aRaWp%*EH|}4)!7A-^SoCJaLwW zLgP#8WsZms7InR|5aWnqx3x`;GxVuzW{%W1p`v(dU~o7ouYB(cHSfEFx*9H>av3Lq z{xo7CM;;}tQ=Y*~+N#X0adR~N({F}< zhvd|%KCxLB=(g6%AN%4pzNln}oFPI>m*-{%ax;U}GBtUMkenqdU3p%3%b*+#S%GBH zT#Pq+ZiMHvka;H)d0&w}{%|DK$8z7561yxUx@XMMfQRIg7&awTCamy0W#M=mwag$O zpt*iXH8u}X+}681r|Ue-+^b{%JnKq!+i1D%%cHb{YU{%DysvPJoA9imfQ_B0(<(k& z7D$Ec;_`%W{gVCzi=ONm!4@c}wqO(Bl|kjdUL04ODCP z0P03^%Bu%8O_hOd>i6D^7j$%p$eM9ePGso{8239yYuDNv3{IEs^aI7|8Z!vea}#Ac zKJ1{qk-EpFh|@fiiNq~EOAJf*A9{QAJ9>)EQK|CAUA0ZgSY22edg!7!J-1qii>~w} zS(-bfu=76IBXBUSyQ()^)2LS5^04jF4a9)|CN9zvsrXtIVo}Qi+<}mv{scqBzI6W~Oe4&1&&Sy0H_k4mLMcegE9JHTfm)9_3xz+%v8Riows;#j{*4vOD*p$h4~x zEcIrq`$P7;i-Hh2YV}>O<~jNgTNi0Ght$;j$xM1+@f834&iagzgyFV;FH)jApa$}GcMra;zO?g)&~&tHj|oX8%-<9^ zEexa`trImb1VBm9$Af0>Q`zH?L%hqCa>^);sF9$q{apFauT z3Jn^@tMT7|?2WX=0u%{Zt@}f^VuSHbN?aX21W=d&+_SAcc>d_l_w1;1N!Q#kok`tg zj@9|G$o+1HeBTA$z3lKw$SITgnb@A65}~HuDadA z-J?98?R%5TYVVeqFW136<|@Kq<5?|cK`uqHEPN80ut-ITT5E`sTSSoT1#?tdHSHD~ zQ+KqJdavj2=Fgd**IU{epsLBc*O&ixuRTh)jr1RkSFPjnP2bzP2bk9oTr{mV5W`x%V^$X2wIulT?T7YeKDL6cyPE_%xN?2yHV^Bw=*N z{=l2ZkaVQgy%x0^;MrcRT2dIfK|IB4-ueEb_8$$HAq*FXak|tT5BsYvJdER3hH83@ zI&44|DEc{5Tg%Nt5&Vi$W?CCee@AbcqDsz6pbcZ{6G;2KluenDGE zoJDJ;R)p%E<>jyRQjeOc2Uiom$yZNbkrh5T+k4`8_4j9IG%JR97c7~Y*!Hyz*75uU zS~+p!U_hgv-}+Uax_#@Q`+2FI7VV4LA*yy9?3vUjD7=u5v8WHVQIW~0v5+Mf@2(eF z$SUkG;407pIFvAsH{Mg>T8v!GyQiP7SL|B@tiY~91a^zfsXShu`)71B3IWSx{IET`%2_}?GJea8T#1WwA>J`| zyg*+=TFv!WVs9rPuK*8_k98qcj-4ACsQ>thj__R#!bA2ZR!o_7*ucsB1j z!a?tY+{n(3+H+(|_wiGhq-0uJ+&}Qbg}vJnquH88XY<0e$qu0{baJ$K?Gx#)-cQ0} zMXSr#{Y!w$qv0j)CKj#^HN2Ltr%Nz-`2s2^Q|70UH~sNgW_o`NE8wtk&xUMzlz z2V5*wBTp|S^$X;ZRG;}O$#ABVGUVn1QspBlbMWKh;^tSvl>9{ulv<8VA0pQh(MxRU zwABBc!-Su-P=9!&6k2+r{^YE#?RRPZe$xXhCMz%+lzxM$NBE^`y|bbFcYEXY$?dhfA+dEqwWtnIz~OAHpgX zkX9G9YE;>sCQHo6G#^>hyDxjIvQ;n3`>--G$pG*jo`tg$I%DMbkA61Q=T8uyD>@1{ zd;X|*2&Grg{R+|VDPo5WV?FSN*IKw&VUJL_e6Sj1{rk)UVBROMzY#hP$o&@xhieY~ zrI&!4kV=Q2h2;h%AOm66HqvUa)F0_xx`g7m>NaRqCJS!c1iJl`RI?>F&vEeJ(psuV zN^8Z@#l%yD)*Rh+sc0Ff=J@J*dIe|t3HeJ&$Zo_5$sa(&S=ZnTpv|JVu7B7*2`npS zwePz#RHZvRJB=rr!dJfqi8aA!M8KMPhx6Z_)nJ~&c=!4`+F*W81~Jfd=@}2$UUJ1* zaQ@+plD>FD{qTL9p)86-<;RHESdwto{u^CS1@30B0}WuPXDrZE|Ky_oW`$umf^FVq z{UD3Nk_E*8SrA$$7+^eD>V;yPQ9VN=BN3;Vgapna)Ak6QL-;b#(P_BCLd1C=+1+#{ zrQcjdfH8MW=;@fqyqw6zdaAq^^iJ~upY+JQ0zWlNr2hu{49)>|8}`D8$iElDJG(_e zRy3k|5Jcf66ebYbhzI2^#0bbmE$H-P4yIisK!5e>LyRpt6Xb_0?n# zymgiX-3J?6b;e(9JY{Ymk^9bMA2|rc{Z7P6GX5>Qz<<^>nG{>F=K9lsuq0Og8a|>F z*BLIe+^{x(aIXL+nZLUL+14ds}++T#m>nK-dQxCgXaSC*nv(Cj(DHKM4*$KcrM1*zOmX4Q1 ztR02<9VRP1?haV)#qAo&kY z|35xLbRN3_`TyJmtS^4lNgdgN!@0M7S6FviWMRPT1m4-(Nm_;vb^4P^b&z=xYD!O@ zK1o;v*GF&FcX282K)W>k)s5?ktAm8N=7XFHa3E-nEi5sSj_XefW_vslh>z@;9ev89|WE!#wmS@2C(dHMbEV-{AjC) zrVs`r>^Rex9@$_0otsF)a%T=l?iL3&utr2g^?iDMRSRuzvKzwuBEjQ!XUOrGP`l%N zyQh08h9ko-lC({loj~_4ALh+!+%CzI-K9}y7EE7uNhUMC>)$d`DOtPkR^?t|Qq^E8 zl}vZ_s1T4R;Ts?O9Tx1zDp(4|UB|?p6%|`Tl?$Sm!~Bf(k37CUc3&&tjP1UeJ@$6~ z&9iyZ$eXV_D7dHlf{(rHGkg8aYo!>~XC-^i@xYIDI^rMD0sZ-r z6Kq&k#bcGqa}OL8vNLdLDJW=zG3lz(>A?1#ma!if9Bhr)^GO(5~UTo;Q*IVZJ@59a2Qka~`d9?tu|5`h>gfG|k`E zoBrd6#^kY!(>$EM@IXfbOBuXXBCtk!p3Hl_-aI72^^@bhtvf|^wz~bOXiK9Tr01{w zAPuf2_v#VbXbOvnktI~ACzR265@f$07V>@ilzpjrG<6~W!jrYB{CkeLZIBq5)W4Nn z^&|J_5o4R7W|m=I&H#qR`FfS#Fe-+xc=tZ_JGGz&0xc=bNUljAoQ^A+1N!9icvs@b zCJk8k;(`-&F`Bz$boVy-7i;uxt;ZXk^%5TkGRMGbONpR=e2fC!`@u=9+eq0hrtKv{ zr;?E|H*E*`ir*qMmW?9E=0-eK&UsvPNZa)a3Nz5@_Wi&o}|nFjqmUCH5?*ev#Wa!;3Yt@YuM!-dqa z7s})kWBuPQbkIJ6dLyl#iaO(|!a!<4=9;H+_?0u>^;;*@NargnXDiDo9dhQhkhhTf z#Jic6nkW;ir1FPJUI8-XVHaeUqymZ&$;?bk!URjhLZQ*d7FW2p@JG`hut+ zJMZdh9f9~z4uO7F-8_M9*SVv-yD_CscDZE{D_Ht|piZazry&*gbA~tHP~R`DT&idp zbXQR+WU7=v`^(CPghgE>^naYpQJ3NgL@qrd?X$OE*mM@Wu`k1&Bxm~4GBB!F-4Z25 zxasPa;`OpJuc_J5C&AvHX=~lQ(a|SSIg#_~_iQ&e-&m2U8mn&}$VpQ1q*qwB#Ef(8 zj{p3O6K^4YfFHNEt@1b7pe6T$s&cFwGOv7Y(hvjeV zw>KQ~_iW*tMW!5uY?`w%E>a9bxciS|G5st3_rv-k;*YLK?Q{Uf= zE9-OTDC=1Z5I>JQBGKw9+&+=8Hd0EMNgWN%0{5UoScc+{Z=HL;aDjC;s2by@P1=)Nl9>P-?a^t-RYI8ckJ-%BU`4h z?#Vjhq`zDBZuG7I&e-ukb0mQccBT7i0I1hti`q6lTa*Q zxeZ&ESp)8~k=8Bu@A1-q?zyjOZxYdkVuSD5jz_9L#@)vQqe?qc)sjIf&VUazn+~}_oa^$em`xt>0A}U`ibJ4m$(5KDKWXB$nPv;J?`UJqX)}h z%jX^^etU4g0!XLC;VDlr*c1K6T_u$tJ|aQ2b>zMW1;h6i6xiGsFh1I2Qh~n{xx9aZ zxHf%?`t{X0mbX(^Pv7Ju@HV7mKVeu1p98!=|Sn13OrMV?`0(=)-;@k$WPxyDuR9E zrWXy9S;2D~giV9C$xqk#n?Fe#;2U5|oV#xhg(9ye#@{f(f3N)>mTaqzLOTGCVa`8Y z!ml3vFJ9GoBn~jBH__X(LKa{zdBg8_@4)*z8SFy+Z`3ncj0jqDgTVhSjQa1(b2AAX zDXz=y8Afr$z@f*QzhlBb9?Lrgc8_lHNP!15hYLg>uG9a;)Bff9Jh6pkxGd@=HG~5B zjiYTd|9Aoa{K_E+3aZ>LY2?GhJVf1wbN9bL?N3JZpFc?r;2uuk2NuQZl;7hZC54CZD(^e>yI&v1Muq|i(&Swe&4_>D4qqe`I*fVUb~qag>X3UiVcB& z_f-_a^S>aJ|BQ1)Jo5FINyFdX71P*Pfifa%6*-HbZG8zcQGXiBKl{y_i~$09yrXuf zxPl>axh!zjA%6BoH*mI%FWXCg$JzetUBEpE65%uYR>DtT{HM9UQ^Nf5 z4J+s2f6__w+Vx&X2-=mNq5f@)dUG7Mg$F}{Ke+3Gv^%)J{RK%^AqJxIbDd8JML5g{ z(u({}NcrPseU$)%(m84rtP8>?XJ1ZU|4nlO!yJKoa8osi=7NW*HO5AIzxf@YEd+e3 zj|Hri003<58$$d$+8sZh!cY~S;$EP(?M4j3!M4#}@3;Ld4nzPkrx{7%8NAI3IR3Xs zxG90Ry1L3FB&2O;XV=m@)0Hk&=OFMCi#)>)UPwsD!&$Yf2MJVdMlN~^OhF4Sxwm7K zWn@Tc-7s=WN__gj070fpX9+#Y?B};vHX{)ZD?9d1|J%JYWa9CxyU%`RTTA_7`fKIp zeS{Z&GBmxcYI%;*vSYvZnVQ2o*oMP1$?LARtJ5BhL)%4jmf>fdP&0Fl=XTH9aUKg0 zFFx{0?e*Dki?XnQTrO0OT2=U~u=Xbriyg=R;$9dm4)e^re|=9V;IjH^d~!0zgN21f zPEIahyD(FB#_}REI6&)x;LoIj;xBNuC}@x~J}_c7nx7wkEM)21-Dn$)uO z>^S4t|4LN`m-MQ~UOAzdHbo*d6xm_KmF4@HHwJyb>H(&Ri%X)RVMvbIt>putIHMV6 z*Mo;27u_K&*wKsq$G?k7mA&RUB@)VR@i7xgEGmP@aY9| z5C@=*^>QmUZ#!rlFz1TKSQO84<#4%(t8`fsxSw$nXGp*cr0rv47xP3q9SC>nAd9@6 zO(Qq%x;9qM$JREBqF)M*k}I>H;-|+uFjq|HZ#K3GGI4O#D#xsE z>y9gZ3_kJ1z?)>W=3G{qC|7EedW4>{Qdrn3^<{TnhrfzOj_8d6xWaDlyX_i%yn3cu z@c8)n*zu1EzpfTJE{Mk#0>4rR!Aq>MLI*i0(*vTV%r8%N+Mq7E!+4?kkr-+xYFXP!j^KZHVPR@GB%+oGEp3pc z0Pu2{8d2`)pBB}djP?HNxNLu&XI+IgKsiYTwE!JtM(y7>O@K4qcZxN!M%d|odW(la zJ`)p*T-|P(jD;(0;$R`1U)RB;7`YScuCLlD%P-vuW#-M{yZFn~{wtah_dkJ_Q*q0B-e%jz=W)?PN#0PIJ9eF&s7&{u)w0lF za!w_^{*JlW*XZ-}jJguwdm{opWlFgcE-LN}vncM4(xGTyN&nStJjN?tEkb&6s%M6& z!Mulr>6iRpJ_>ufZht4s*wi$Z2(3jZNP}IGQ$Bq&hhRmh+4Dp&`-#2H$qQn#k+FKA zv#oA!!@iL4j&bIjw%*hH4s+HO)~9DS{cIQ6qyMT+^i@s#Ky?lFb4YBg<-2y8hiShA znBt8m(VnbmQU^oB6g2=x3SZP6B7?Kj4bO0H4-z%Y>eY?Sth$XCapam;mJ2FWDs{AK zH!eb%dJi|f@K{qZtE-${wB41l4wr5IJ5Y-HuK_5jAFigRrrmtsWz~K*j^_uePwE*b zLw=6!j>wDw5P32*MMYILRj0xZXW_K}bI=Nr;PnWSMF@Uu*ld;_h-N<}d^c4_LgJY| z$*?rEoK{zjR}ba1HgdYVYMzJ>>-w)Z0QT{L^~KbVa|dAUWtEhUbtgWxIdzr$=li|I zd`I0|Nl7UJ5dKwXpL~eD1~O9WWzwIWeGv|ykKcMrTYL!Zc~CJ%q6vYrHE!sVjmadT zcvZorzkp}jUbqiuYhz0b551{&iADF-8aYnlpSA}M9xlaq;J}c2goe?85Kw9%sC2ts z2013Otz7IB&h#mI!ygHkLtP&>Iy)`G`rpTbybVdOI?YEJo0!P@5K**fTz2qQ{l)yn zPZFIGu)DsV1uGm96Qh+a!URH_dzYPIKHxIH@ggk?Vqx*^8Qgs+2XATwEd2bI{uP=t z(BT0i>_t}PgfNhJfZ-s2Kl!gTzkHVADDKYE;oYqz{sX<61%@9kow@v75_Z~1F4H3R zl}g7W9G)F#80Nw%mwmX=?*HF&hon<@$LNI5gF{n!d4oh&LE)k=-F>-VLWw6gyoZK# z`hoO~2~)(iTCF{K}rqF9c(-CIv8pJw3?$&=;1xQ z_ZPSp2QNLa%X^~mmpA#N8vZ5=fn%0;@#3%Jevyy^PFIj%;|G|!3ISn+CYZW10cdc_ zL9P*IFc3MDi_D41=+Oo2=}c$pQ&6kAAs2puLWJtpbrCigIEjlp(+{lI_eN`Vo#y)( zA$AG{terdzDYs~VH3vKqu1<%diC(*z@IZ!<-zx`;3A1@Eg)M)C!#YXg{%Q}B%#&Jr z)a;~w(E1-F_c`AM-$wtutl+z@p3L75%?3&v+Xs$1zbflKJ_~u+$(rT)D%TAQ>>!as zET1Bv{m9VQcn<{ckBL)@x|bK5b(~E?8M%BbKQ3>*1OxD?k&X2CYH0GIQ8n!`claY}xY$!ZtfqUZ-Yp>DB(V{?eja)Hlk^$(< zLOp0ksbS%3+@4rYFo0bd5c9o{fMSnQ*S#jduV_ zw?3{*+}x_b&3L!Au&}U2Qq`4y*7GFGDtAR+gWs{AO~=dY0CFo#nW6m8dqNI7eD(G8 zN^2~Cb6V91LX3{&yW30T3f&U}OV7l9PSLJf`x*Y*SvtWZkx;&9bM zfed)v^>qg}kiI%2{NN@}i*X5zaZv;R3MjEOXr0{1TcPwy*d1`RyR#M|G2E;fp*CH7PAvdwUn6}5|MyKXJg1`{=$7o->3ovg%%uv#F_%r$!GkDv|{Wb@w}tL`^Yyy$IFNX&{3s^zrpe%m;(iPfzGR1 z=LbLzJsP2!gI#?51??SDYRlA9h_*`D?qfvD>lHTR7`IuVPH zxq#5c%3;VtL@4#B4LMlloaYYMk}JR=yvtGv$T3BtkpY$%eR&JS08MBS7v?F?yhk|i zY5Tmxhm({O1v&M_+`KcM#H)x(wz=J}WD4gzZQpw;hc<8$u@1wftU%HebY%F+iF0RH zU-)sqnOANQ0T?e{7dQnAr<(b~X5%+rIGYAU#NzF70;)V$vlQz)+E5FRE}huGm5;c1 zB4>ZzJtPP8H&)*qIxYh)Jb2R+M5ZQNQ)@deW^c^*tFG@hZI7hnqt2EjEcwVZ+Wn%% z@l_I*(f!#ujh|Z`;!LoN(h}WUm-+AYF}%F-JOpq=6N55`n!#iv!5he8)wQxHNsC1@ zg!%b3O7Hcb1y0|hY@LeEY9N)rQ9YqkOtcQux#tyQ%s;u>|G@>o)99S=;5KO_jv4LP zRHEm|(L$t1_gIm~OmSWsy-i+sO38)dk@Hx>?P*2w1r8OQ=^D$arUb}S4ko4S_Rw_o zH%sjt8_oJ|W%4g^fCG4Ty@e)Nr*Xh#8S1K#JOgC(wX@aGT?SD5~yK{p{XJ>Q4GPB2b zx33Mc{((yWBKW2Y%O|yld)KJu072I(3KD`&gJt=Mb@0qT#;NH=$~-y@<;6V->VRKd zFHtE=yDT^3NUm}rg_L%kM@==rvz$nGfhL;_QwuZjfiCn|5Q1inYl)f6fa^{!h{ZrN zIv~aKaQvespN9^&f6Y(vk}3#(Icna(VPd9#<%@nTxL9fdyH^mp*-lblg0E3tJ36g>!&xoC@W!0v97CCfg$)uA!RK5zg z;oPfR?Uu~EHA=Vh2B^Ij-Ro~>bYyzgew&(@XzE-!-WbTN+9H?}=>AsUbZU^3lJX>_ zSD=sOlWx%)_WyElz-;{q07dVbw2SU4V%bts0TXN>l1tY@?Nz%_I`|64dJTji56ZuF zW5JuxX5=Cu+$d4;fSDRruF>E4!c0PMYHZxsd`@7c4p`y~ExIq*2f!<9hLCY-qvp-( zM04vS)yic2oehknt*7x3Xta({pZO&T>x1S8?XJ-$il1FNDH}E#2yqn4r5vvM;(K}= zytg$w+$A%XTm=q~b}N@8?!hvfNGz;BPQZT1Nl{TT97|`RRc!X9RJh0VD<>j8KAs~; zc=gE{5m&Y1fY&1@kux@)_&~CydBxxzUeU~w=YgB~Xl;#H6~!Rmm!sk^JJ?Od)x;&H zxHji%Q9^y5gR7D?o6*b@7d=oRtP#F6qr4HUDt$bvcC+q)m`x+Kw$~%ENsxh{Ea!z0 zfiq+st11Pq3Yb{Z9}MeJ?N@r#YDTJMX20UUs_LWlsF&upXt7ahzgW&<|6#g% zm-{(7DC2f~)s704g$R|5yWG9CsjVxuZZ1*%JUJfPGrX&ZrmUUBm>6%tSuyLVTfP&8 z+WQn8FiPMVTo`UC1C^Ong;efqnhU%B^=_@(?A;cOsm-Ys8_blZDFO&9m&L&{<>D07 z)tLP=Ae|w1_1MJ5sbu`54Ke+7*An$CWGlz~EI^m)@;6K|aHyGJr4RITgss%Qasej$ zIa9s);?}00$I17A&uTqQB$95eU14Wp6B}c)gMU4?$hE}RY2zCc2)0X&KA9$0O;8-o z2RX}nya8T@EM+ruvCxnZVSbL4HK^Bx^N+fBIel*s+rKrgv^5HecV02Mpe{Q78g??> zP@S_5PBJMmzV{k~m5y1{^(3zCvo#sVnNB)*&f4zPOi5t$mb*ByJJV1@>a$z ze%`i6(&6~OZ{aG|0|-o$_fJlw__*dogoK>cdc76Eo|{iO;U@B6IjND>eDS*2hoQu@ z!;g7;Q$Bd*AR(lu7W1gq=4{rY%F45)^6FU~!;)E32i?hhksylF+TZD|3mD-6md!As z#qx8R4SaDp)8V0sj_RKK&f>j;ucsV4U6&u>EU2PC?!$VYA|Bm-Ij@O{7Z?(#PmHLf z<#H5SpP3IWH0uo9F{+=c`yrz_|#dbuF42UG>u-iJ-O<}7B>Z;j==a{_#xG0*|AB+XWg(jR=6 zE|NLa;<-CGiq(7#2Awr|J-r0Y{m8n#4;<)BdXD6}AU>;sahLP5^75e|nIj8Yn5#ML zjl?O82oxMegY<`2r(XueB-x!eQbA+Vu6+kl#9epS_E9&^z9pZVxld8Q1kMbbaDX<9 zM0FVb9Q*wc#xhPVIg;iAl?*vB`1{&T8qHO-v2ySWeI0x4NZ>VfMO$NSD~xT^=ur>+BS2)sa_`^&eXCpM^2g z?;I20UvSPUKJ`GO)@XjTT86R~Qy5Q!g12IZL!~p4_WUXM`xbP7ieU zvKR5!D-G)LJ1+Db9=5@PNT}^aLxV&ylhX;<#&JD-}TI!7xdMDy~y~;h@p9-RX z-s<8Eg^&ZBn``d)*+ib0V2={o8aNwz$2D_`m{?evnz`!Y@>14<&qk z*WNu0GD0Yn}_<4U2#p%`A5uJKdxI20r)yU+xsO*-F^br>4!9DOetmn4mo6b zp6&G^={xE74<~6T&{$nS5OjU;70C@Q@{1!}!7r+_PlT6Uq*twTY)Q+~X=&f@AoRlX z{avQ_0qqGPt!rXDa~HbJnV(ncbEvn^GNvojhU)WQe9_&d7cy^TnknF1xyYR1vWYO| ze^1oF5+Qd&L+e)OY)SBrZtjbw679wn$tvUF7JlP{H2MWp8|_B4T6V|h1ToZXdCOkn zTf4n6uDc*puba`kas@(!yt(S=Lbr{J{i~P<0UM>D3MQ~>ZU;>eRkC_%b9*%ECe*j?l1T=D%Y zcla|akZ7dX<`dIYlTH)r|Pqp#l=nN+-#S2b;V_t9d z?ascGS&|KD`XpgC$dEycDR8?cG$zJ^ulL0U$Yr+_`=$b8rU7m@jMR{!DlLGY|1SN) zHz-km7-$#N5U!hL<=C51_AKODiO{wV#zNg%q$LrqBh@aeKzufc>DnTP@_E=~Yb?R~ z&2Ulw^sU&9le!=v+v+%rDTHv+p8mFt9B5*Xw|njvVJnoPc}m~i+7Iv4j5&oIX`POB zK#4g4N?X3lX`wp71agJdJWous`_ho3#y)|6_2PSppPdy*u0n=@c9{QJ!B~6<##;l2 zNSB5xRI#{KR;9RnWjjcZuoN*1F7dY^>K(FepiLRvwLtc~?{&3lF3BIU%&WPZ*LgNj z>-#Nk)q)WSg)m!n2fC0w7+yFw+e)gS4Z3aBAcJyO!&IvMP9Vh$>K%nw!bS+Y!d`Rq zCEFxa?(MATIJd2I@5M<+H_t<8g3^n@E(g`OpyVBE@rFvI;%10k_~nMZiFEVAX$TD* zd}tJ3O)VTmsF(~(nh=z6L~h#*%@bXxj|?MHAFn1bE#GwZiTAVwXJ*Q+^L93uzizQq zkDb+XYn6hth#RNDsXp-vj;ZCr^P7(asH^`9rg0<$wWmN@eXZ<7=VW1>VAc8bBITxe&!ds&s`w!^J>ezlbjPp74dZNg z);_40w3xz!Q#GS`3SvcN>w+`WuX>BBsqFHH-b#Js?0(~zq4t7iaG7XX%t>h_C z-gANYLtf3tl>aCfcLAwak2TO>+!WoN=Y|4*i!;TJmpAYf=A(dXYc*%I*gQ02KbxKB zJf^p9UwvI~`5usWgn^i-MDdk!y0vK21lug!g(VSFTK*Wwd06!s&EB>5Jozyu{y$SR z@eX+NoLV+*zjVJZVq@_Zvl-S;`ale9NKvBzGXVXcf&Ofeb*S2yZSJn6t#pVdbM`&-poZGJ{s3FOo$Vg8h za@aaMEShi#O%y$nRI}jHM1dCFnWMA~N0mmZXLjpUj_#C($>kVFn43&y1QkaP#od!t zk_{(LynUX~-+yzn&7Xsq<&$!vr~zfX{RFp48Rm{#2}PhID!th!sI@4_#%3(0uWW@N zdMQ&YJ4Y^*GmTy_2Nkt?Q%E&lYid_)IW?^Lb$aObz(;{^<5TSoQ4`k)k{(UJOt|0r z>>%7xKatH!|KE)|cT5qb`}S@ADiw!UK*+(_PFl>Vz53-4SzA-PtAbU}DRM8-ZzpCG zJLtTe@Flrw)>S&vqufitOm0FaOS}Px>j#bPqMvPM0vH&*<-6}R2ELlY;~vU+I;X3Z(S0p)JTR0YR~J5NTOYpa*CBE zrc%&TXMS#_mBZoWv~}kg&d=xBK6Ep7>L|a&xdQRzf^uo^Hw*N3urytPvMmf$kSp|j z4csrj0}7k>IKILs=m*lNLC72{&y^7L!M~hXd;(3j2a-5T40G<(Tv2?K29*|4RI^&4A^D)ek;`3eqD&ET!A}#l#+z=r9XD9gH{KF)Ms+e#P8+z zbiWq}I5$7NAscFM!`C&kAGJH{m>bX|-;yZ<86aL8X>ptM*}d$Bl8;v@LBZ4B3d%&2 zZ;#HIGt~G#jKOD#<+Z%);j5mZlA5GgU)Vb3<9THTcQvs`zoT>Q3x;o&65QBY#q85q9U`(_^K;f%y;Qi(T=*m;iTDBquv z)|}2tc=@X2Hj%hc!;K|>(A4|{T|JYPuOAFCe#zF~wms@y>U5p@O|IN|gP2MlN{go$ z5h)`XPw0Ad!w3j}CXQa46aHeVp2YaanBKpQ;pRGSPn{`L3bLk^+o*qzzQq|bVXo58 z^Fi?gL*Qo|hm31-EJmR7o-|bZ=0j_M%r51y8^$UbFUfgngaZPvlUYQ?9x>b4$}J=V zTU+b5%5)+AR{su>dI+<8L{xr1Rt8Su?*1ps^K-yLOr_Yx%FNvOEtja1nwollUhCfA zV|GN1VW(NY@De5|_oYFQ<@h|~aRRJ)B;ZW1cGL97LQ`K>Zrg!PyCUuLy>5MMk&{q% zk@4d>H~z-5c74O8Z%dC&4;!szw9 zW)bTlL3A%@<9^OIU)y9zV&ZYJtxj+9l$q0S*W)_BIPMUUV8oQVzl;$v_RmUEC=d*4^vAr;`3Dh!n@AkN!zeZo136dTCEiQE~NJl3+>Gb&S6t40y zTr9m`jcn4EPBGZw!)(%GrBPtQRH<^ZihuR<>+}*of%WYY_mq5o8r>0p2EP5+ftNYU zkH8l-hNae|(1l}$$J^K@QO0^{{PGDogw}CK=&UrgM4Q@q2_68ERwKv)y$-$H|Md!@ z#`D0#Wi}&S!A_KeLlO8{)y-aL9#YUMumxtHyA16@OTraU@PFxX6J)7Is+@AoKJoHT zsfqVy<9uo3-;>Pboufv3)bcsuCkc&SLRyqRZ1XNw)g&+;Ag`I%tvo=6_v?)rolTXX z$QV1Kt^K9%4lcUC;mSmFLsgPSsdEx|?t*=jN~Hd^d!b`%@pvRf1cB+0rf&rK z;8q`}xgNzzhncUvQc%ag^qL6W_Gr%YA_%BxLB)gVG~YceU36d8hHPft-UOG=eqf>V zlSlp!0sao>@AK3A0~-Cn=`7|9-tQQJ*cfy13=-w|4hG1~foOX6fza$nd*zuBso8~wp z%A(uvMVBGxVh7H#!YRjiYjPQ4UWABA(@B@*w*(8S7D#5aXrGYu+v`xl?sok0&Sw>9 zXlTBE{;WnW4zY1$2GPPyF1>l40ki3Jri2gCmAfsc+7(|~i|PR7UOtq?!WHcgXwkfU zvo7()bbF&VPrRHq3vFNHm<0<*ugVZKwu-9qd5nEqgBGd@m+6HE!4!cc(Dd*36LnS& zlPigF6ZukUv(ILkc2J+q4gv(ei6BLnGpjkAI=D2-)0N;kJ{ji_?c|_~%+*v^!!c|3 zc)6UBmWtl6U1UoKI;9WZP|=y4>K-IqH#m(tw+ga#PeebYav`^Yw?ha&ry?1wkw*hEg<1?nkfcABJ zzNo!rHIP=QNs)heyeM`@Pg2Z9Vi3!pG8JbZSYriyk4M9+lq-Pn=aZ83{9nx(JaL7> z#TWXst*p@UZxYQ%>S5c}B6$_0SxGNz@?ZGhJcI`NJV*AnUJzS`p0EU?>GP3p=&vE| zrW%^&++hmf73@)!GHYGz6qwnv3veM$cJCZ<8&=YWQ)V30f5RcKh}R@d^#skv913R* z)Jn?UY8OvkZYeU>yK^LO0K8MQ&csrrpu8_wzY`hK}|w7W>De7+^YI% zISIp%LF^$~jwt^05Nh%@mThXW8x&;iBJmtW2ezqa_D!A(I0HRl(WXtL&Bvp{_QSby z-NV){s@SUbWYYg*?Yjf1-v9p(5fNHa8Z;H5jAXA$$*4F-j+M}{$=<7^Wi*Uz6>>QC zo<$)$oP%SfGLKbO#^LvT-_LE_`rOYy-`_vCbE9+4`!$~P@q9dlEs}ym9s5hI1$j_b z8rvwhZlB8|m*tok8=t%UXt``$m+RfA=>|EV&%3yuZEy6{<+))hHtElK z*_o>XEdhpz(mXf~XGt|~!**ctLE5;DQGlG8k-hbWsAcfZdv%7(eg(pbI;(=-A*Xbg z*tZcx+UuucQ4WJ8>6f1HNW;K>`H zF>*t-#ljIs;hOgd^t-(tP%VNioFXC4eXdG?dobEhx2Fk}OEzV6YwKAshPut+-Q$fH z6koFx2ZfxK&S0_lrrpdQgqocs=6nutJ{y@Hu1q*6ZNtUGju*R8@}w;}s6LHDa4QQ9 zWp0*pv0M}1+uC=y9W^`u_OZ$6w}7VIg8N=;YNeBNqdYxguFSn%tG%sl(_Md00!83i zU2W{I&!AL@c^(05frQ?|vlksUQ%tvb>dds*Ct~W8YO~e%+M~Uja+c2nF#JgV25Qkf zbY!|$&lo$N_P(U=-0S#EeP|n;Z`3T*Z;c^Y7@{$j*R#C#zd~#2 z4Hn&Pcq*(U13Gv)x_n>E&*-OW*AU~!plw8WyQmL~$-9&|0e!(oC6mQ`2AyPWaTk!m z9$HW@U-!0)mSx=HgI52mvM<%U=7}-htBZgMP<$_@xrB{Y?RSt_8hJh>?KA%zicvz> z-Y^zi%ogZaU|c$J(5=Gsf-N=LyJzmXO?P!4pR`go`hzWq+NmVtCQlepNB_j zHa2&aHet9JKA<=M%R+39)7J&}*W_5OKh1$QEotpB5>6TGoznVq^ueF$$|5~(KA|OM zf2MEfL<-a@=z{cf1KM{#CIWZqHSfqm0ZAxcB*dv$Pf$Eqlu%2p7X(8=5xz5krRK!M zP4+LRdl=%08j5G{a|nh(i#4(?mL&VtEEGqe!_$aTBisqGc-1O@P&9B;xfNfv$LAy} zU3NY_hR{lS8b{=piym=tU6f3}BnPqI)fKz56~k8mX|^nPBVW^IVX1jB{UvoWU? z%LAMVkLQH@j~m+P84z3rN8Q?F9b2uT!!YyJ&ZJ2;{gI+1CejG0_y|!BiR#Qf)~FFS zS*Wuy?oZ-M)IF>Bj_iCmM0+=AQI$5knZ5iReahUxJ*EBL$?ol7Z@ls1&s*S19Po72m3pR8xa4nysl!CwKTv1nkNys>z-`~ z+nygzapF{#w*BCvoy5L67kFFdo89clCGC96r>@W5EuHoOw%q=-9M%suJJ8-WraMRy zYS8<50i29OZ4CL=y}Y0mx}6|mNm%RdUxmaytBE~01F1ijsn0&~epV&7FYV+@|$qhocXB^s(nz)PK zm-d)PT^XF=40*v8|jK+n$0PF-=IDjS}8&M^CYYdXlq?4Qy^_VQZZv&{7oF{-lZ1CbW# zHv}F5TUo@W^!2fxd8f7LXDk%lQQT2l?**-hzQu(Tv;Fa!~-+|dM8w_jj@NTC?`tR6$UpdH; z7agcTt^dp@eLL5@R&(>43X{3$5n2Rs_w zJjo9=&GsoN&89JDNNNrZOP+&U=+^RBY5v`qnP7cTVq6LSC@yLSNqF3$RFU9P9p5efj6B1dR~oNWba#}x2K-Cv(Y9GwKVbB$Oj*KE`2PNpbx(E%u89Pb~b?8+A` z|E2({1p>+HarqsTWZL!&1B2Oc4`?(`43cim4ebNM(dr;+4Z}X{@B}*UNhF{QQsybT z2KkoS_Ip{H!rqum>f~EK1T@ooRt`2!k#hpYBl~$SX{tr{3q?4D|e=YkU#nJYA zRfBsIf+zdr{h;Vaoj(2rBZ5#(TPP4UZx3m2Z+~PrddWEklJOJ%wd8y&K3J8&;?=hb z0hNX?*Vr=Fxbz_U%EX$!T1(a9{0rI<>Ty*+}#95)8(z9GKWBN8#!622twy z^RpV|?(^ej%?v`D%^82#>trBVRo(2p6$%G^wxIW%gtf`lH7li$KkzA%r-pTPe+}D& z9hy`12@^5uTuSztU7H$_(x^gQllY-fU3BteOw_t|TpZ4!O+emX<+(aW?;>*e{V$;rw0Z-;v3ZRJs`MVP+V?9zNO)cZb| zSr+H|x;h~mEX#F^Jc9|X^EQCvc@E7Q$<_o#1`Vn>S$b9W>mLCeY(9>?N;@F50-a+OwP(;&^56c2DJ|d{Z4~xp z23Y9UB-LH+3$}B;GTd9=!i25Fied}&pq4dSMfsjpRHP-*Pv+XjUcc;TmT)T`I!F7S zK7Bfri#4@}F7IoHeZ2GMZT;VTefEs!QqKm@w%n_)X*EVK-Bf?y4#2H8(>K=*kouC+ zyyX+#KuPy9A0XR!`bE<~qY*1Mvi2(cvcU7$4l5(GeKaFiIQf@2gJ}_c-NgV#!Y!5m z2KBvD3ZY`{F8iPGUf)_~0M^ys+OYMs0itGG?NMi=prG(seeWS$#7V12(-Q|-yd~GA z3{2`94!^%wwPaR^F~~)2=RfXiyK}n|N ze!po3GT4blIUc_a@>9JfTA+J}i&ORvADJRvu>!cg<7Y357y|fyb#1~c_E^j`M^~1^ zz0orPsnzEQC)dr)na+g^)-Boe3)O41QO*Gz=*cZc&3BE?9~lJ!-D7x_^baXO+?A00{Ij2G5%Fo9mYhmC*%qhNr zEz5rtiP2Eoy^3}stYC$l(@#>iZh8EI8fx^ysf2lA!pPMR!!G^KNO z<=dBMq1nvlT6&IX`PBO`mNPPK@4Yw}{&iS(tqVyL_kysRbQ~~TA#F@>9i8=lPZ!VPqsP6#6cgd$`&})xl&U0_ncq3kK3eA9@6TNf%->^p>XxF{f@+ zYCa(O#OT`>*$uvcdXs*JXv>UgoCDW{GxVBDWBQJ@Wwlm327p+5v{pd|Q@!pxK)|!W#3BcZzH<*JZ}->mpeDpZ`*)2sm&(9^)RcGc zdG8tkfj6#f%xC=ynf$v8f@Q{y>#1YvjDQ;MJ!~8E__0ybbK-Kv@}y*3g}dLR%I3*) zsA9&f12=d95pj{Wwm74F9(Z3;~99A25|=@Tam4BrGQO5WHvi6}=)8ycftwHjj(IM82CroMM4!C-~_LX7_N z*nTFDGl6Y`RL#cxPY&iq)k*(YfD{UG@dAkBZKDqz+)H<@wf=MB#~98V)e_?YI~3^8-$B$P+G zZ&l~kjni}JewcX_?c0D z(;K(Fgu`i#GuU;~!5OGD@j?olV;{6LpAs*=#9&DG-gD9s@70nKgeauCB5h5wl_rx? zNyEAGCcvnkB$1ciX8zGlaMT4l_l^)15KbUv#GuFX>Q&?9(mC}CjxgxWSFXfTg(Ztt zTUrR17~-;86efx^*1WWEno{0T_aR)@?rutm<;kUqV880lj$+$Dy(3go96P5}!T7BE z=?aG2{TZ0YB&Nb8s`G$9N8}XSu;{X|GzfghMVWmovgt3krij)`Bl4&E!%Va-YJtLS zP{R=3N{>c2S7^-&KrSEXYO3VjVcHfqv1GO$$xI~){lZ|{@~HMT`kUX}%Gfjuy;KvZ zUCc|rtl&V>x0w*7P04p7^&lQ;yhzuv8IWH^SsZXD{|k=!ug#4=2!(us^UoXeeoSJ0 z;fYV^1+DT3<~G~R+nRYG*{fGho!1fe1jiC}HTmh6Z&ggj<{vKTfb&&-t7D;GRfs)G z!u#OmTXJ(nmX9P%W-zoWmm7F|@!u`$)iY~wvjWrz&6i^J);%JJBf3baM53(4E>Ggs zob`%xoKk$Jbh;r-zaVn@<+8;Q%(`lfqXEkRm_JQSx~|#D3c%%;VqVV;OO?}Rx?PnH zz{HbeW=GyDa*CQ8J2ulz=L*e2q;lvzI^G6>??+&F`B(Kwgk@;$v6l{>mtTJQ8qMbt z`}C<9ub_^1c&j-nmc}SG*loqnFYUFa59vm0OLlBU{Hj@m)^bv}`@H&c;zCrPv)dZ< z*DpvoPg>GKkg(8|WfU-Sla6yeTdqQ0#+L%!v}LiDsRG+soz&|YIt5L-7SN>coxH&k zMu{-pQ4H372k?+DRmpTafQ$y9p zuvCn0hx@sT0z%TlI4CWc$QEAXXPZTP-wuSLKLJ~|`k=+#3h+bo1Bgb0#vo?9zY<``jhudt}MNHMYk4Ygig<;w* zhGR0@TQb+zi8PE5w0%|dlF?$K<6~VSN0#E&R%&k9JC@-b)mZAynXh~Is`JTCb>%2s zzI<6FQ4jY`yTbwj?0Nu#^LjDh;adTrAUv`1Jo9SyZLFx=%g}HOD9iF=b8RQBlN@(B zw%uzkb6*Gp>iy5%NtrVvtgyqJ-`eZml0E429LGf>QU{zw5s*xZt)-J4b@Nz+cFmW$ zv0T!)4A%;j820M)L9`=uK}cIidIQ`VeY*SR#Kq9eZ$*cH#X2Ad#mN$8Pir%nO?2UrCeINn?<3DDj)zMLBh5P8lVU-8xmioGt}L zn)&m&OEXZ{vcyxnnf1296!t?9_ql+Kq%9AuA9k~8<1Fs*$-AALicTHMzw4F#3Pj+o zc;D*qL3>N42#U3Yt_ZI~s6A~}Jl7cFYYJt;D(4<<7NOfTt@vv0;HS?F*eDi3kEM!4 zDz)>m>VJ2oDBlQ#sQ7W!+2o(aI9*y0G2FyrYu0w$3NVn3xpM&+H0gN8$>y;<(#a;d zp-?UTqrmK*k0~l^iV{;lY29;V>D^IeWUWk~ojMocW@&{T?bMmWQH-19C@|cl;%ICU zQ@*rS#mRa~oPfSTR9UuPnl&@)%uJXaBi7psS0Gzz;cr$(?8i=tC=35F#1FjvzIp3`*A&27zRePpW1}G2jw={ngsiN-Jw>BzUOm;P zIYzRBt|bHHJPVk*=V`p6GHE+vjfN~9IEooiq6J=iRQNydUlLaIb~3HioZ{bu^E|g- zmyii!cGn3Hn3MXf+fj93X*ziI*n*{72K7s@w+OL?;J7sN88Exki&yXE>7|tdVS4Dp zukV{PR!NF>YR2zg)eI?*+L_7ZUpqm|c#2-lWX}^b_1Pz%g$9jZJ;$y34d^zD{0L%y zy>`IvXoHl5tWFp0{a%}h|IFABD-D&Yu8%qUvz1LjJUV-v@7UNzT?oD{eq?~@nUHhMu5Tqk+s!A2KLj-kL7xc(tk3rK0ilG( zfR7z+5Kjbvfbp>$A2UAoc}XVZ%Q|x_LQF)A`;#X zs{_5O$J0&K>a_puvR#AAruX1m^iRPCZd2d!amz(enwy|Le*AdCZ1~n~If7H8XvgPN zhh65}!tGQJkTZa>I(y%J)~RcppGk5B`Jh7jitZ$ws4;awWiT{Ds4_p%J={Z73Fp&l zx-~4ai9j<7Gg>jex-23csak>tT+z%RRWAt5en$6^9#__8GaT146eH&-9Sc2gtn{bk z%Q&RhRj>AO_+p^_-ON=LEVER5D_nXR*XwM}p;7x_eIg8S+qv@@?8EiG>X7i(^N_aP z6y#;GrWSo_Uwycs7~92YDc8#!T?CbB${W!p9%(v;*LdzL5eL3d*n z*QIg3>HSOzWQxZI>%F0#l+5C!yx^7x{se!4(wtW^r*N%zQO^aoR#6lK%p!SLzTpEkgUx1X?sI0>I}JH&B3Z9BfmakoJRmZ*KR8V21&4a)P| zju&Ar6Nh$QpDPH)gi-+Je-2XUUbR8K)0R5{e4~#ou%5^dwm*Bb4Er7(g38 z;(PB(gHt-6C3dQyL*KnoO78i9JFbnvK;LzceY7*{x%~}Y6<|~OV)%o)q|j?|w#4S% zi=>XbU-+IaGoHqL==9wqG_!c&px{F8>|Rmr%Wco5Sk4&JpZYg0mD7MiICP`E==yiV z$30IEIsA2n`;e_CaoWjiz34Vig;~p4z%*O6U0nBcpvNGUV!o+M3&slrSK!`VpF`Xk z=N=UT5MJPKst&rob8td`A*ngX*U9T1S8xNwW5U7HO7yoGQk!FO% zry{4*8*{v&7yGElemK&R6W_kcIKGjy9t`Mt_}d<*@Aj@&V(f(dNXtHrJz9M67W6}# z51j2}Tkm2yW}gp!YBwY#fTf#5i+PUhC&yuWV_VPQERd2dYHG^cQ0mxK#7B^>1Kg;xH$74)(9h*5NY+W#xl{ zg6fc<9fSxyvp8&uh~J)uz5-vd(t|?ykiPz7Ze=zOnHLxdzpW=aJ4P^bnS35BBg7uU z%q+Jo5xloU3pEb~nkSG>TrfAsr%37IHILf#9v^VxE0h5+A+)HI%JlvdCLYttSAjYO z&sLAJk!Sb6qRIJAZ9X~cWAa?rKZscviI=}wim`NDZ?JBIoZyvAIpAx+RbPVHoX`@2 zmv#op(S;Isdml1DY~MdO+1pKbgg})t$h($?>(np!B3eyPV0Ij@d~Y)mhnXU|x9GG@ zk09_YJkkgREtyiQA^V*)rg0+sGBV5iqh;9?WK5szm7AJ_1RFi;)p~E1UX;3;i?^p# zd~w0J&i80}Uq^7VNs+lT3kkzcSu*M<36fF^aqY3vLVa|W;vq>&NN(vj8MD@5=Nq`$!znnnag-xlTpXv)8~)IZC-tBd;0tJ`5w6cy;Iyw(EC#wh;KRc;}?8s z>C?C~)<;6Mb5b;VR0``(+H`Wn*pWrgj2$-JD7DuKS@|X zBE7G&5oi#efK<&T8ZxJ82OoR9BYJx%mvOr$x**G}6WIv0H5djLeO*4dT z@Jd#uAoO2$9FkosbOx%Tl|H?pKsm~5whK_^EERpwXbS`rkK$eHV-Q#Dhr6~7Ek5CfDTc5VT1YDwfgOxZjsO}T^f#UzOkl@gie zE0$WBoI}oCk3-NeoYO=n;M&rL!5>rN)n27$%3m8g>jG(Xv31pLmczI3ZB~qzd+fe* z0g!V~P&4s6EJn0%_JQ>kdF{k9I6AUlz z;hTFeM+k~5@c9Ccwb4yF_;x%PGqY-iHP$3~dln9hK@zl*+*yP;j7|NA<~p%=OQ0ou zxFOZ^k|Ya`lG`U-zLY#*NysL2Acgu-P*>N45&eR4T{0wt!vhS$CW6^*B1Bv7T1^`Y}sTf7yQaU9*gJep37zS~rDlYVmPsUEXpHok0o<=~GsK!|xsUSMU$#w% z$`STq4M4HyuRJd1%1shRcGiRQ6_L_T>6p$FXj4w)tevwQ5L%E*A1=LZm`BdMeMedc zDVPJYIw`wwy1o%LyWXd0@j22;Pq=2Mn*;b%?#AFt%x=u2fEK|xBojN#hUFF$%A zCl?yRepNGq0y2uW@?9=YsUZWx%~GE#6Yw5V0QD-+&h~9EE?}D|;iXBn%TVxQqH$NH zQT5;N+-1VSadvJ<$qjRL=_Z?uZNjMu#R1}Db(tcJsT+)Ao&<=m))!KDfL{jqf?Nx9Uk!pot=EN2mQrRMH-pShr999jf@$k<<7F-idjDE+ez%T-3eNE;+KUObZd{0|#w*;?r=WgiTG$+>pxsJ*{bN`5~8{{lxnG|@>rPuZ9pVOaV zC!?=w2lbsgO^G9QI3`m^iZxuw7EERq8*>S?V*`!d3m|VeMjMt;|D6BAVCNyS&74MP z3HyF@;#5l#cdoU_4uJ7CEMP~R658}p5)S&MZFKRJ@ck&g3bqRt0IN)&c(^s=WV-$} z;l7o}{417z=zx`*p<8)s&U3fO`IbgX?kL!4cWX{|x-xPXYOL=>=d0eVe~E#)LqZ|@ z&#~(q`B@&2V`V;KnrfR&n}Z)ql}oLB$zlfcLeo}eW+|z*yUcXxgQ3|oNCKH`RR!N> zm!PeqoqbaNx#)e`p6|tZO;b0SpA?y+!qj{~>ZU#FwrC@)uI~8W6e(H%xH8I_(EDg{ zsfS5&dDRNUILF4(%>=T`{$=%!lkaAA*lQdo-W}gr(qiupKve~Ulcre18Nh0sG>xjh zqP@>kj~RwLEFV;zkzP+T@>1m39fSm!Ryn-^f2E`nBN&aD`Bq12mzveRq`w>#rYo-1 zw2nqSz7VZsk<-Y%U^)@YpmU?1weMQ&PXqTes)Sd*hXG1Ze4bU3C-8^&gPD*MblV=F zQPNnAkt?A=MAlOuP+ITB$;Ayy+))tW;ATcdd&{@_SQi^LKmCKk;ph9vZQaa`>OH+a zvh7zwFW*8sO;>ji)Xaw=NQ%1UT0JHL0 ze>43JLJ)7wi~04P{;=uU2&=AB(5|vy`RjaV84Z)9z5B{%`el_^PxoA1l0-~AVbOe`qd5;x$HvYf$soEU7E{* zmi(I>K9W3lDzbBP)1qBXuyfgp&3FIT&S@Y!r+GGV=GXQ1HKyBkr>VaF!gUVI`*Ii< zEorJVwD=lx7}fh(kOuWX)`zIvHrGWU?)Ktq6c$;1RPjCM6)_?uryMc-HNZuePws--B`u%f$S*cn_ z8rqg3naXIc-#_av*gdtLAbw#USRwoQ|IOBIx((hYu(Cn^m$&|_tx&5BKhPGpR4oUS z8ntrhXOR2Xcm3yoJ{Q9#=yDl0u_3GdOQhuc2G*Cyx+d)DR#+i%_n`lER2fAO_{dqq zA@1Kd!8j3qkhVMjaK9OCi|XnY)Gr_L+b7b{+3CS1qz4}#{+-rI?jtRe-0<+Q4#0M| z^q*(Sj~26u?Y;m6B$qSAoF4w`?*8&bre9(2{_AR7f(KPfG?e#&KN(zX|F_s!2oo%B z%0*+Y-yigI5U;c%NE4<5pTMgfr@GYOWW^%uRKi5f}a`=t1`=6_K z&L2Kg^GNm|6xeo%RkRMWNRMOx@4NeB>A9zAiA3V|RmLd?eSQ6JY1oWBPkdC+&ed~s zCq8!d0|X!qkFT3eQ~FkPyW1tBs)N~kPjePUN2%srbF*`>pC9dlZvWC#-Loi($4h@Q zL|ugw%{u?BrKA>~=RnEvf0(jgb_d*2F7uHP3cZ`go+eet;WF-A+6w(wr-(I-{c)DO ze0+M}#CLgY^Ak9BY@_iesA+y9zWr1FX&P*W`xYtOV^|hTfb0E<;r)9LLWF7G<99Mp z=@e7Jz~+4s&)WX`_5HcQ zN4H*lS%Am$nk?793DTUnV%YDH3y_(TY5SH`86`<)|2OPD*1%(xi{|u{fs4a4?DO*< z|L2u)AaZeb@=9*2MrLQeK!@&O1ruFb=*Ky_9e`Bqdp*!&ER zT99?smVaNT%ZEcOh;h;pnrL6l@zQ6{_T%tI0ZZFBIB=y*$U2?=uj>Spxi{URu~Wq% zI!1xYMbRgyB@!+L*T4R+vBy82s8)!E-UCe|!4b78m!#bC4mku-dy6`O=;XSaaW*{C z3z?eVH;20uIcU-{vjT_=My)`@?@RjA2yiFTGRgAM#oULb@{fOPhF^`Yr@4XlZ8AQ9 ziaGBY^p6M+&XrsyV&mLBM)Ztf-yiBl{5hcV{T#|E)5EnR6c2T4v_) zlt~Dz_9c5N0|nIA^G-0K_l_z14>hVHWKW!HPKGx>Ksg8m3k?6xGw>tU*|ftKmV_Zm zaCGDxbh;mrCjb@lm@G50OAPoUpX(h&#a!}Y{avm>E*^OdHh zK61S9s~s8VQN>4s5e|q@fIW~HlktNSZdeHmUme2nkc*^Yz4=_C0IrQ}@9GAiOgFXK+oAC92 z+$UPlhbUf607|c$Xf3Udip$#tp-b#~)*Z^8&sTQ;E@|c~hZyJC>6RiSta<+G`0xCF zKi}I|lSvbU8FF}402rt9H#YmI-4h(D25j1vEZX0#pehD@&*MEyX)-q;43YM5*!%N+ z{_)B*l9qYz3g|FS&3+nA2TFTuob z7qA=l>a$6XALoN1=7G&0yNOSZYK+5Vc6#1d=%|@PNi9P(qnrZ@W?4W&Nd`IwOK9?A z&}frGhYpcITbt5bQUJuEIpvL8v1j3Af$Y)T^1%{dRL=IZ{2eYWH;F{ey;+Te!f+|; zpVt@tF|+;maXq>vLewJ66N+g00HgK}MzW&k4DskMu0Vp6&Q|6&XJ=^Q|5S93jYf+T zkPmo;NXp9g$J7)%Qdaafa>?{S{cNN{?d|C#+Lo`2fPqK@zD&%;iy`+k?iL0Epz=&K z*Hi;^X(E>*gOVuoc^&#WP*&)CG=Y0Yz2NNsCD05}l69 zt!!qK`4-RY%eLeAE9jy|Ke!dYL5^qE$>hKj zkE^q(c8{+&m12-oSIcBGnN_oQauFy^9e5({qGl1ISp(0x(A1SuU^o=p;RaJw^Duo> zxG9si{q5Vgj`Js6zZ!Fdq0ysU)Db1eFdm8LS?gL725@slFtvh^`f|*x&F&uS7U)9d z^4e>`-E_WlE9@N=7&UGTI8AVC>;rv=4J=%{{x}(O2f*N1(;2fqw1WpZ%3~7n``-MW zipWheN-dA)_1Pi^4_#mYr{soGP@P4fbC7bT0Lv zNXChEErENywx5F`<}sa33N3W;qFVr1^K(J}dd2t*JQ#Nnljl8TSRiau{qLst@89=5 zd@R$lOGrz+^T0VY3Za&R8<5lmP{}gAl3`%2>w?p)&(k6Wyq`K{ZjJ=UG7ct1E~iez zzWNt&fJ?_Am?7rbSeX4iKh@kVZ$uw2yxEH+zFr(fST&KLQ$=B)%l$F1;mZwIll9}v zmSiNhGun{#yNUd9SYC0QJA=Xw3_~NO&=c>LgFgYYDJ1kwQUgTDp%_X+mmBcr1bv@QeoTb0IY z&w|f7)|Y6iMAy0(lBk$>(>a!pSmgLV^zGpP>%0b@DBiv9#{zwiNwz>0A?6New=qJ9 zmZaqK>EB8Y+6O~`U5e%tF4nagJ+Mc_^x_+QBh%}0AO=RPUpFv&_a1n{L!=oIw;$>R zW2@&lnw>3_nx5{Ifb-7*S;mv-BQT(pIA|?NGUFa^s zx7noRFY^{^Hvi4S{YdD`<%EEbe#!pQrH6aGSH6VB#Z66#IViA4B&$5VM$jq9KM*V> z&u#)x*|i>+Ycz*QCL3|D{kU&$fca(|#)O=6fULuq@5qs9t@Fib_&cH1_DvRkkfkr-Wof6Li3Ko=&OXh5?3l`vYO4aEwRn*qoOdIs zvU!YyW~BJ}^Mww$;uHbKr)>Z~cCI=Ne2tIG%N3lWTHit2x^pKk+Hk3d6Uw+$5F5yY z3g?U29r9gW-@bgB06OekV1FfzwE~0$2jyi4f@{&Vg4pI$E7ouq>5=tjAEaijB54F5&m)1eXBvcqPMVbH@_&j1C39$`oH_LAMOfSq+%$H z#JW$4cWZ8aaw)_T@Y5Ma`M@vf4$VMS!vO$<6P~RQ*aT`m4xFY0;g~|2#vV}eiV2nuio;Fzh8tw#K{EHd(Ci_>U%4S*v*_L#z z0fr;Shl_2Nno)@YrbNj&qag9>$-+-T(c)ribiSG!(xiq^sgbfBk#SBzd4-?xniKi2 zm)|!_L!N8TMm?5dCQ4mSXy%coJdBI$|KOQJ^ZjhKXd=fd^kEZW1~N6BPw%?^?O2(y zp999YpwZx?`1CaM253GPK+gjUW|oq}o8qN4V#sAKg_Pn3Eb&JS`@v`C{YVnCLm69J6(L@#S+nj zs0pi-4`kqvn8>aduutk+(Uhee4g_yU?w>fC9DNNCS#t&fYAO-OUjsAG7H<*)9bW3G zO-wqT;5WSVU^Wu3M>z{*(~k;oj`!t1^&q*7MlrS{T<{jry$vC25IDTPx&=BfL&F7; zY*(j32@-?nQdfrfEWG;OlAa9>6lBh=EFO(TvN2C!6P+B&Z)tvcF5u{qBbk66E!ou# zIrITSrPTN17k?hoG3(Z9*5Y`@3zK z8iOWzKv>iXnCo$d=e-S6YmeaV)?aO5Deb4U#B%U>Uk?V?ZCslSk(`>briexu27v~iT|+8eYthTSwZEq5-s&nBv3 zrH8!o2AQ0YMJFhk*IGR+nfSq00Dej z>A7pG3l)>v#C61NmjSRyKoDI()E53E;F{28ACl`)Is&&@g%|a*mm0YO8v+4!oI(pS zX~1lC(g_9^cn~wdFNGp3&jZaD22U$OWm?Mm z;=){j?8@uam0{VE$&_oWklb=o5Bq6$L2n`S;Ii30+Ced0vt2w=!)j&UJ{(9J9IVLy zN)gCW5d}L>bx)e-?{)F|5wnlsXw&s0HU0F~B zBY~-2NHc*R)D2mSF>RQ6TE8V@bOy=jCaWcF_BMZaEpi&$!LUA2l67weRiOF*p#hqW zmD~3O-nuA2A%!W;cz-k=C@An!F->)Zr%ZBU)n~TMq8yBNv^#HHd=eH$Do`ee)0fdY zrV{n+-W{48Xg)UpdZFY9u^!u-((|20)uuVazG8E8@oSA48)Vt?>uf4WdRoPNb@$kI81YxH zRx-IQsE)bV?!YOfCFnyQcipO6NV*{hW4K?uu}j@l;Av^W8oMqtXl z6nxWEez$d!PZsa(nzqt=D_{%k&}u|=e^da=uA%vax+(km03pzFc^+&z;9*Kn2GN6eAB5^4lfV2UJO%r;8v}1OvU)F&r(Z;0R z3=~O?T;S{jcZ;{8?bd+pbddKVA6-$u*K!wdh+=Ww(>t^0(?ge<&U9#w|{qVTrg~)%wA3BC7Nb%vtX? zGR*c$8PUc5d z9HIH7($Np8Un_TpaeDo9dEyu~ty!!r*wJb^9}sD0@r0@z*`IEFS7_o3M{(mf@J^x`NZr7ItXs(XlBTlwr=zfOu|!urJ&E zT-)%&RnJbKTJ27I`LcGt-`jg(>a^l~Rq>DOl@3{9Q{HAP&S6DVvDpJ*+`o(;F>;3> zBG+?lJ{*<=Z^F2)GOBp8P*em(kUqkQz=euq5LhPtK;=Ry=v0+}H6CB1R;+2IDwvMA zF>UB~`4lK{XQ#v(M0R;VJG2I&PG0Co>452s4k|UpSG?lAq#DYRt2V zMa>Z>4t&Hj$*)a1SJ)?v-Qjz4LO6Gd<;w+hKLk`2oxlUPWls8Kd{NUS!;$IjtFcdk zD5d252e879;7;by)P-V7y1o3!v`IpS#tpsO3;gU;IC`r0d`{fcdG?gi?sX1UdcdbU z=XK!>zFOcikivC~d|}bC?;XUHSraM>ZKs<^O9cfw@)_+IPZCXjyJnad3=65yIEnUp z90yvoJN@bLj%CdyKwEdZH05+h6@v3g=bum)GaZMQn>&bhKQgD5ZAeh&f2pa=9)dD= zqq?1cB%$9e4BbWU@O3R8F|UN4LIZDSS!cI^PJRQS9ejExpI9a5UAlPmgcebi2!pwU zT4M9XsqqxUfIZjoth-Z>j?aVn0NEbu3VIjN#NTTG8fsdz+$2<EdW&xV|~KP;7g-E3<>JZ%|PctE5X#kG)InxBj)&f}?LH=nX6gD^zAzJs8jz zII`Q!6_4EEL(5*6crCG`Y1%o5FBe!eO0ItUG{NTm?PltBeGB=<`zf^L z&!67=A+gW`c-y-}2!o82?OHvwdulvUz5JjWcfZwEN zKU!1k(8M`a;sW{-d3jNV{cTl7&AILqKYH)AXtciU5K~VSzBy5h9lVEZ(Q#h_+G991`x_Sbw*KL6>FX?saE(*u15JHNz z5_N=4GI-xhsMEKB)nU;ZD9+AqwR+B7TpbTJ)ycetxE54K*ys|m2&k5Oww)#|pRbYm zc;`T=>N6RO@v`Hefr@S!i+-Wle1=${XtRlN;^tDuaXBb|MbBB6Obn$TozMzRcbwF3 z+mRw<<$_dF#$P;EvkSG%Q=!TNr%10To;$gcieUXmB{bXeP8wF;!m_{Z^*gn?mAv4x za+z3w2wi~7WUUC0r~vx&LJPeqJ+wV(#}OBNlKD8W=PYz|oc`vn{OK7*-N+Woe#I0$ zqNgLjnV#p#muF^_2OW3z6&Uw53$-{tTfk!>FkKZRf|cpvVch>>41yb$`o;**1dPq1s)E~Ni4k!4{@KT<)Ru$hnQU#afD zi|0 zk2Bz1cBBXLO7HM%#p9J1YR<|0EZ~W=5Bc$`wF6|MolmO_VK!uqr9rQILcya!`$D15!amd|;#^{ppsHMw>9DPL?<4pQ1c`aInx$T-N>URn~2Oh{_-Vqz_l6RFABr*(T!O?uCl2!0{^<{*fH` zgLvBJm1XT2wSv3Lw ztveJGdM`{|FeE`=#Pxn}Abm=)K-F?s!?Jj8q`RSEg6dPDL)Q|o>9H|$2;@S*5W(vo zkgpk}H{$hNt%ELGEXccBnN^mQmeg#X>g5)VR$I=<`_?rmijJ=-cGU^vcbvI5zh^?9 zXNIecO=PvNksm*jR`(^vvRL~xafUd%+RkziaE&Qabjv?fC9@TvehlPGF&no+eSLl9 zA4;A-3u&$UAp7w`Llg=fQwJbNu;v&bT0HKxdDb1k5D)VWx~W@oDx1Nd2}=ivp?6|N zPCU%F8&uwP;@Yi>{&UO9I24v>UdCfFstMDVKo6J0|8X`^% zp|_|xquihqlMjArv3GI8#@hmJK7LKYW4{M=mrd#WZTsi3ralGWO$4|n_%95JzehPB z>=@|ks;Xjr1H`a{H(c(yKwpFmy4yT-#}IGOcM_fYJ)Pa5N89U=yLKz67lOlUJkhoa zx#$B;HV}O*Z|C&WI_C%-TSwmOO5?V*4bvf63abgkenpJq||Ez?p;9qgiyFU;&t7J*+<1gjX2EKzBK5#R_;iR6s?MkbM(zCoX&PR zY1SeEL}_`@jcm4hZcb&`Z7X*(KiJtMFaSTE3N1)kA!^j=AKk7nTcoj z1@7S-3!0GrIFPNS`;Ec4r!LVD9Xd}&NP{?ZZG9J7rIUqGdIqBXkkoe}N%DdT5W%Lq z5yU=)D6(cjwU|_fw5q7oDer~tXFSS3Kf0icLNmAR@$muyk=c%{e_v`!h{Zpeb&ph{YpL6c( zT-S91#kTU<_fGPoj?r59vY_*k%Em!pvZ7K&TmM8)F$$DG*aGrDwQ?o`KI=%M=3KYdN2fvNnSqF~YHDjIwQ!S24Sw8PN5wb2$K!~ZIyIc7IlEao;XY$ddt89C2Muv z4B1PGRzkOiXJKJ4-E%;uLP5oq&J11Ov;+3>PdodM>7i;>TBitMpQY(rS_3W(>?(rq z=&{A5Bc=QzT7{Cn5iiF~HT5VDPSZ$`#agCPwSlmBmu`ikpgoxEKR+CeCM4H^9n$i( zwvT{tFl8Azlg4?k%RPbvtAByNWzalkVio2EKcZn~v|&>Dg$7z9^z1Z$MGuB0QAX6Buvj9I-P@*?T=Rf&j(t@tR z2KXXWGi-$Q#0MmpGsWC6zCOuU&eQ7FjI*K2niMGkBQTsoKON?a3se$eSH2=ii3k{r z2IPB5)nr~b5Hb*Afmx4+VIVz1$)!j>0^~W8I1+9(1;4UHE{ujHiJBgxKUB!rlEp0+k4QyG@#HO-Np->G%K4p3Fxo)Z(M z43V%!5o|Ka=he^|uPNa)#Sz_4J_ddNcHlnfky<9O zpEdwTMEcXCl)LQY0vP#geA*A9C&5P_0Z+8C&}7Vl;<{kdPzh)+9#Ga#611azC=tto zH<(dOf-u=8^h(=dw~aG*BE{2WZ%GkJsHxnO@~E*+!Vs8%b#K9-O#&8KAghCw2%!f^ z8cSs#Fhg$OBJ}xdS1LB!w6(^z?qWQDIghqmvr$2B8`a8$dVfFYc-w@iOL*vyb8~Sm zkNWyPLv3odxwvsy!Vwk4S?Wk?W=T&OdA$ycF!LYVufDZ&{AC1rMNE zBIXMe1j`%lJ$7v!5bgSLG_;4YO$EJuU&Aa7cTqnMWERGwm$AA9tx9eP&=U;yjf+Za zS7+mpLk}9|(sS}HlVmYd0HfK|rw#m@^yR}BT~^E;s-VBr14rhrH@*t-+m@hd+mpB5 zc+?HV>yza?80 zJm|X!RD(Nfdqp<^DSHT61G~kMF(dXZx24y+9?F+fUHzLI zcMpbNR@uV9U$P3^o83yR=Mq*{0tt4al4~y4B%CQcM4 zcxaD(p2|k^#E^`_05B|BsNviqDU^4glTiVV%&F~C0)Jpbfe=Dcyk7_P>5ETdO+zxx zDrQ?Yri|lkRGl0-%10jf#JjjOw>M@g@gpc1-l!PXOY2N$c&wR0UXOhi^ui0(!6*rv zOn4BV7&8qO>HyDEu&iJ?goi{R;Cw+(*NOg-*`AtY|T(?C?ravz@{NB4sl0$UDx=s(T(D#c#VCG z9`dc=uyyBy&e-SINKL(b^KM{c!v|w+Ik2UG3`XeN8#9>&z|~j#hF|=1RwLl?7#SKb zyS%^g>U4os4on#cB!(C1Eng$`rIL)gp|qVsN?d66wsoB3Bc}LZ$TkOANcr{79hbey zY%l)NWft;V)lE;WT@pzrh*Q)M`w81`4LQ(I+h zdy(J+iIRoh&I@pDrFwqlB%Vqr%Zm6@RFf3~d;apB8dlg?9hJrBFg?ZMUvB_bYm)=eD z{T}xL2opI#hB8tROU`!Kh>N}Ghn*CFjO5Fi( zAzIk=QiZ_zR|hI~nZ#|jYyQm6>CcV`UdWzI^vE+Wt|>3<=!cBEM4fHT@i`4Iv3=!= z7|;0TH&jR)jsoP@*t`&GYVq22q;lG5aglFbESXH{-JbD_NeX2Ma7=|`V2FS{$vxf5 zb>4DJKAVz2;_mq?jl|YO?Pl8FZ&cSz9q-Wn!1uIGBJj9FV~4K(9>jlDmYFxiV~>gy zzgNp$(sozAUAg!@$UO zZW^kbI59C5)(d!RcWHjQ`5iGi0avngSTERaG>#)o!D_Z>a~x@NwrA?|F7Zk6eoMkr z9g0H+Nn&Hj{L5UVR>Z=T4y*`F1-HYT6X5$WIeYH&L!zy$TdpI5*CaN^arn|Q3$=vz z#O$-bOm0lEjtZ_VTCt4*57NS0vk=EeIqq?OD7{xfg`-6n0orhs+nRJ_W1I-Vl=?#k z?uq!eoCWnccS}(%cTszruKP45%qIYswx{Py%w)M)|LoyS&n*P+_Jd&>cffEg6KqBE z)2+BUITtV5NVxb^&=YB`egG#xLu?IS)>%oDa^s!`R!qH2TimAwp{P8q(WRok&3g30 ztLPS?5@mnw)X1GvJ}FD|-%Pa&Z68EWFWY6rk{i2ma{(c5S}}V51xH((!{yh%+ARgZ zCMbMxO;K!ca%UCN;J~M8hc9?fkZ{~^u*xG62=tKC1AqF6jy!C{VzqS4)eL&9&#T?S+|a{cfoi?AxzCY zLIX@lx-$%uXg1%+rO~0#ZZN*Wu-rp5dwdLiDzvp0~cAU7%}R>=ff)yDO)?E zIlgiPjrl)F5!X){juj4MBTHS*iMo;jX!w=#RiAC8;LaCVqNH@V4g07Iaz}{*N^U~I zouD+9EERzSqbV@yL#QY%>b;F*R*}ptypq8W>FsGqvM-XiRqB{sXMys<42SfV;SlL` z5&S`B&+U)4ON|0%Q<{doiHS+M-9&iD^HP_M8&Z9?78C8re9647cMXLS60_1JA(EPq z>VtdireZ~tP2DaeVcxV8q%oqqFM;e%ruX4j!$uU+OJG$jaVd2U?owfRc;^iRYOhw3-U zJ$oq&Q%ZfB=s-O#wm>W0I4id#r&`biB8{5s)<=J@gMSss>YOq6Rn|_lve9v7A33_S zWj;p^zS?|hPY;4?p}Ir>Ak~Ax+mRgSwP6rhn$Sxa z04}Gu1*uE}8SFi&=2@jy+aq5}QYZ%56B8;IjJ%7n_e(5$gqY6V@z^+#$idC|m;{|8 z0cWz#$#4#g=@Dgh4x(Ee6&BO$)^vldHJLbN5q;gGt?Ocx5sFF$b%&yVIrOdl(pTv& z1QoFAeJ)xK<9_SuN8G0}Dz((avKcd9Ctq0yyrYMuT>9BxvFf{X9xaJ1ktL6Xml~?m zcaV@)D|kv@aj>EqfaJMiKNjoT3F(Vvo|m`DEthcEqos$0&w$hbw zRiSvGo;)tpG#X)f{YeX$KaKj%E%Sea`6JJ=!#18FCWht!L0YZ@UBVogjgRxWd4E=G zo{5Meza%b&q|lV7iBeWBzx;fw?^fSbJQGPH$8>m$MHd&>*sw{Zz@uHrHzN8rbeg5EEM>4MPzmeb0z8k3JbS}yH3`DDSsNGyV zJOZdN3ozBJdihOW6gpP+wOo1mG`YrKKY>k8?X}q{u;tJa*Bp#Z?+n&;3)W;R^2VIS z?#uQHg5+vZE^b*!hz}Q1-mP(LyN>~?Bp-zSA3H(u077kJqmqrl9*X5c)4A%0 z<}pn4$`o39Nnno)4A^zXF%Dp{HA`k0hL`RnTPXJqnL}KRS&X7n)f* zIL3ssEwfJJgHFSRml2ddf7kDw1_UnKCl!-S5fgWA=!?0(QOeW25M6Y^=3+F-b~J^m z5S}5^`Uo+$mqpu_DPn9^Qv|adcPNkR(1(N3&yb2Lsu-sIfu~&0Ku5Q((bu<9E8|Jg zVVGd-__f2RAiV$aUrLA=b|Cf1H;iF5vPugKK{&FXHpZ&@FaW*dU6=y}#}xX`#xunL z1U3G6gEm@SOUoQN9c}D_b1~S)+0gP^c1Tm0;ff1g?LUJ{7ZItdSVNgeGAQOy` zu!@wL_xo|zdr&^zNGt8&U&_r(z`r}5T61~FHbjnbt89OM{kyPyjvgPCd?gUa-eDd1zZkho!?>-2zuiPut-IQVL!MABe6PwIcN#`vHOcl(es0qMIJF?-n(~f z|Y<_zdo8LA5e7U>C8{eu7FXlU27}`gE3_;fU-KVF`6U%5qGm{7cw!;9vTa6 z8qo~9cAx;lx+Q&DZL?{#8}v99V1u3`x;QXy0PXl?n4=3?uQ$pGC5{0VLccEgBJw6A zWA+_xKn-iB7U=%gmmM;8n~qv+(vhH!%+HWpYV_<3AhV5m{pBJJNKS*>$&vLlE>u2`gR_baJQ?VS8WGx--ufR%hVi*6A0LIvSqtHzX%ev_^&ZM z|KCOZ{5Nq%BomYKmlc7>U7qaS+oD>Vfu513yr7)Qdn>HW`%@CAu9Hf8$a7kS( zh-*h$Z47YT-8gHYwP5T##uUfF!7(8E1VU*YEDhZ%K|=clvSN?W|NP+pbBEbMfD(E9 zy1n zKa<_hZU65l+H)r&N+Uaj{pCOZ_riQv8H}!YG=vK@q|+ddj+H>~&_g&B0F4S`6(XQZ zNXruW=js-&{vM*^wkT)(x!6B%6d%Hkkuw^~Gw-;En74orqJ> ztA%_7R^+*Bzn1b}^Hr4)%D=L-Xi-Br_{apZl>F~&gGCCsQBL(=*QO3gG$Pjk8@t2& zZ@`>F7!B#+LMJUv6fJ*!A z@T)&!fXGjv_py>~dQ&Lznx&d z-^EeDJVuH8Mu&DAT96@(9N=)8JNLpyB7rMSeYNL6{Qro8G4ne>Mt&AFtL_IuZ3qlf z*@ljGKv4$YeKq=h^%$k$iU%**1hr7lmy=$5mHhr_|3`{n-gD-l zHl)&ogaqy*+N92p>L9JYq$i>9`?c*tI-^U^ssN2e@MUB;DGDcjGw|BPY8XAaG0F}} z5*8q-DyC}a<@sw_<}-+`93G6R(;seXwKey7zdW^kLc8+bA7<)&zo=WP;_j4l7~Z4} zt8LIfoSEI`tn%P><2EiKdzgE~53P?>_waX|&)biHK&v2w{`aRuP6F$L86`VK$x?Msr$IDJUrW(FjTC`TpFU-@d$&|8=hfhU zv;O1npZ%W={g~q$MJ(z_!uc-nh3)R+QqGo=qtIM(*h6o=+xi3<^U&8=tKT0eeHFMW z0ufI07Qi>g*m)p?S&CSw>+d>e1D6MHty9jnuN}0ypCOUkwH~zPpt{US(FeS`wfeI@ zW=`}+74v26f1gqPbFU+TlYQSUvI0=UOsqh8ZUM*CMDgsfZH-)-xqHp|LCt3QW{vju zo3-mIYyf8RQ&L%=@Dkd9-s53AD?$$*P92*QjbP}vo9MrCTOsiU!;TANsdHIqlXtpD zF<#zY4FswJS-wvVp|?ig{Qg=0iQ?rv&y)9MJLjV}omT~@H!UQkw3d*+PawL4#%m9^ z{`uA)ul5~*m^IGi2i0W<_-a4Rr;Q1p0uI^)v&p~M%ggtXma(s_4x|JMin^$rpTs`PguTTmrM?Jgv)dED0v*Dp@&As>tJ-?jN) z<|UUP3N;HHLgWYt`OkLI^*F+l0IVhN6wJ=HqJ!bT9H+)4)&xh>MdW`EL&)Zb@B)8$ z22t%ewIkIk=Sz!#=C$o$t}pj!{lD%QgpZQ84*&&QH76-p%}HE?=K_$`^x&W%KF6*` zYUQ9c0o=O(Ca|dy8PFr{nu&37iWu;GFh@|d7z|MhTt)V4aflf`jP(9J&HS_3pJ$7o zmTUw{a3V(36ga0Dps+pVCYszy4!$@yGFg6I_TL}iyUx+Maw$M~<~`B~lAyeST62ON zWe<$eP5_xxA%L#{UEq|_l}69q;@Dyb;Dxihc7xKv47e)ZJB3l4SQY|C=oj1epNskR zN)XgEN$Gl*YA%2>pp3sgVQ;WbQQ=||K(S`XX)>z;js;%((*)8b{IsROjWIMD0F z@u{I^KyWwPy5;{jd23?r&qnJmm-(>kQVn#Qk2LH!BV)T?%@x&iK zt6SQ=lo|rqxIs{=bB9FwVu{2z~>74U!cZSjFtI^%pvwj`cetvRlNLD@fvmTjeJQ%#j1gs8N z685w@`Ahvf7~af))Ld)QH!a(s_K?e+vD9ZXP!?OjX?j<%fa`BN?|5u;{S;G;`UVU2w5EGj4)K-4nQR_xdy;3FGVJAkF^L{ ziLI268?g_yGS9#{on>N>i?a_263(BMXhrom2W%! zX};fZzQg1^=fJtgO>zsYz`NiCc|g7qw zeivG)9lEu4iCc9jTBPG}Ek|AK)3`L%Z>JlDhs9XqqEb_oeD9g{dX~26MEu3`XO=cl)&S){*VZ9YfYO?{($JMl19n>{xvnG zUBw-yrToQ(iKhLum2EhQ>CR!zBzY%%vC{}TY9m%!_Q!U6-i0I%u~JP_G#PlGgQPaN zRj3^XmY7eqXM7J!z_aets8yW5()u=sq@*CiA6KzW@d0=LMwKI(Gr&{)VpW#+PZc17 z{a)NP7j4vH_+Q$0ejy}3(#n6_&?;(AV%U(Z=S$hcrUb?&z`XFT2`0RY!~|;Q?t1&a95=Z&LBUz|MSKUFZdx|Gl4{4)x|xOF z%hLTC4KrL*K_>`>@9iE|sPoI91WDHNt}&PTtv~Eno&{XhOQkJBfg}&ZfTZ= zyR#1Po~GQh_z|ObrVerb&TWZuQFfEB74``g#NPYcfNTPe5ZXKnHHUNn5m*6Q3}HiQ zZ5;u?fpjDQJgMF+$Tcl6>uWG9+UGcl`%~Yg&sV`wYC1?sKI4_VQ1ZxV^2PJ``ud8) zwBnp~X%mzLLY}OO*e#ZqC3i9x55)X;viKQscMTA>{LISQP)EOhV^6bZdJW}yRFONs;aO#&Jv`(560dG$?<4t+)bC&(zinA zw_j9g;j&1`ltV9YXXoxNynO@VBY}71kEKoVjh%=5m z+UH6fuz8w$2>n%mAUsglRsJj9^ek?95^Gj^ySUR79dDhgU39t2Fx)H5{6==vd6vId z`T*Rt$ah+0xh_D3or0Mb_nCZrqa|1QjOvfL3m$cm>uWhrBp z>t4ycK6`#y(&x^Fj?D99B6=$tMdQ8Wx%aCd3E4{3Elhie6m`t|uDrjP%E&fUTIia! zx!CHnLfG&#ZyqV^Vs{4iN zaa|YXD-T?vLhp|8G56Blb#2?LwNoC4GIyho{k2=xu*RyV&=h=4%=T%JEbXSlth5V< z+KA7BKiqi#vjV&dqtp7_O4W0_ShJrK^>^@launbYc8Rp zfhwvS1_I~CjNpSL%{2oi@<*papG7Do~nHZ>2UM!x-??|#*nyZF+? zc@r-4wgZkb6wsTYSGjlP)7h?VjaIJjTV|XcuSLdWc*(m=HC4-t<>uMVJP%z6lu7#m7ckuv+fpx*96c@cPL4ILmnShj!#9dpe~1gK9jkFHgN3E3i>9;4g_SUF_x63_ zE&B%#qOioNy4s;EQ#vGA7#N&(*-y%t_v_eByo-J+CRHL5I7}G2gH!OjjsF*k#UMWFkpyM3P?Z>rFcVoP4vY>~98@J6|)isF$JkLJ%$xmL!qvZhmS_)RXY zvq>-IY+kda7JT(Z?hu0&wb&@7Uju4Rd6&lBTvh?%OD1OGoQyncL2AL4b(=zKObAaO zfle|>em#+u?^x!Ij^ zuCHFGG}?db_NcA)arTZ`%~!8GB^Bzj>w-0jo5O8EUZSH9w{kb?K^WpM5^LH*xTcLl z(^xC*avr>fRazEqcKggzu>S)sZfM8LuCU2;lQn?#z^&bi?iT%6l*n!gHh~56?-p^5 zK>%O~41aCtwP7QJp`pC}y8K!%D61mwoK~C=X+A`ZOZKE5Xl6r&Nt&eJ9 zaVj%xZgHk4chS(GVv$WZsKbKR-2jCW3(BzUC~izExnnfhQkr(^YbXLnVzB#oq4n?0xXWbmw(*PeJ9Dc zHA*m26Aq*U%rcv>OT5yh`u)*AZAY?g9pGQ*JgG*(PgY{Gc&KQNK~8FfiRy~JIL!a^Vo1v<&);YN9qG}p)VoY_;>?pY_ znS&xdKSry2Dm8sxCV)YV=tw$^rk-05$&bwKet*|&mvil*Eb{GCDNZ(58mpgVem~BL zE78FjrsdjYf%*^#B7=as32+zcO@1#%kJ8bM(3ROX5`&O_F6nWa zeZR@3X{UJjKkG#yx z&a{%jJ>i10zBPEvGneth-sX+=7K25ObZXdqN3-S89T%y)Ph*a2-u{~3^NB~$ia58p z!;$2C;EBj!$eZxI)|%kfTvJp|j#-G28{xUfiq_x0nyjzk&DE})rA0JBv(i3bm&Bt$ zc=&J7=RY=}xHUZUc?1eBGVKf#zetzXgPPg4abh1%RZ!S>p^7x}>Q8MIn@6c-o5yWV zyl${4`^-V&6UyPtVB+p*eHu2rv8c#@Tg@0s+Nj|qbX)SoJ@1t)1HTT!a;u7ZM@-!T zox`|?T)jNG_I^sSiYE%crMeZfnEyvBHp!%PZd^4msq= z55C);n{#5NFBe~|ulueLjso_A9k0^|8+3 zNEQzSD5x2g)fVdxyujc4xy>H_@Ualmge2iErU+2<@XLhg|G3TnasSIRnK=)#cM$UC@je`94lx#i$ zPA$v!TNYHA30ZLD;6|@W(S6%wk~>|xzE&}M&>|Iu#lW~k)5-Spea``xqC%oWQT>iJ>numG#QCSi)YlA5si)Nw}8+SN-g~f!;&d zcmX9ykjzW;Kb6z(ubvAbj{ukV0gtry>x zR@@OB!R;Ow7f*U_f($lQF8uOj8;|tt!KXeS{&tBQKuSlpgIEgWmaUe-z|vc7ry_qx z2>&^Uv7SP<-G!Yno}<%6W-3?AeKOGE!EMhThq7~KU4@}yJPd3#c=KGpwCH8A%NrtbCMbJ>4TN<8Hq>uWQqV#nJO5)xs%LTD7@+jc1SI@KFKsx}k|m$T0* zs-ATfecxt%Ke6%m7|nDC2ddCCY;hUxWfX4aY4 zlNBpYe6bt4o*17v;#WN@zqX!G-AqMXC?9e-K_oT}nNXme?kyDEez4Gm6I0sS5?10+ z4S2Pa`rWqa)x@ymEEln!|Z-2eU zVYc?Q|EuzH*V&^=!WyI?HcHw@D}4)dob6m5ENCbCZ=2z&?0sGRqg|)cWm>JE3_Fpu>j3rGgfBha#WkMPFMgg6-_im!TV=j11SG&Z>bjVpX-zY=uob#fxynW9QV4~>r`bK&Ox_NxiCtbYn6O& zStq}lLk&K4b z8aOGt=8=+2=Vh9XY?Hti(b%_qf*D~g>8k44FCFgYw6w?yTA$=I;*`ZLE$!_vE=bLp z5n0CGj*EzBk1qu4#0tz+4M&M$wdKX5^CB)ZwX|Ys=U;PawB%l{)r{&VoqfWO^Jj7h z->C0uXmcH|F&Ju5`m~|`ml@iU&5br)7bl~l9_=Y?eghdh-BlGWC6axLt)jM_vg@YT@P6~=eX95F zy?3F&ZN9AtH~93hzk(l#Hntirw@w+~ET&;Kh5!l^ljD@MhSWOb3b)kIVq4iN zrxilkl9TZjE;$EO*4D$Y4bNwK78$%&g|t3&s4XqFCZBIWbK-b922v)7fv2rC`)KN2 z^H1NaoApm#9Pa9HA9)gos_nd>KUd(?c@f7{5fc6=%a@WQG6pqOHFHq~GKa=mQ#Lnfe{PSf*qSe>q8Mn~ro&Fzae(a#DYOr-4 zQhGFx%D{_5T^YCBbX7_pc}D(!De>=rV?BawBg_jL@pLU4@fkP$4Bm1!JPZk>HJkb3 z>vFHUiR*&X!sU*F$y>Qf^x*uZu=UNRR)1JSfx{fA#rg zpG`xJgMiv7jq=3ZDU!$y{c=LIB=P7ur|{+`9KqnBxtRXrBSNlYpb5p?f&&I z54>l4E|(;YI_YrZyW3vMDSvH6#~x#LrTIHkA48tX9s2V75%*m6_^*oO&fq7EZ}UxE z5o{#LbOJ-}CUgqwSfZK!;dB4Hx+nk9K|-3hm6$d ztIK-eW`~r;N=h5FZ}J-Sp&K^ZdK1rq0CPxSA+|xk>`~7nld*4>FQ1R$2G9kW)rvT@ zK{%gzdd5%^t%t1RGNs;rE4OYP+pi{XCFV79II1A94aJ4xYM+YbhA!W@vHQYI0yf^3 zeX>mO8J7z2HCG?wt^T=KWhWEj>WI-Zf+(qbSmn_1d|%IPQRQadA}$vUR%c|BZ=dL` z(JXgKH8}M59o{8wLtBoV3sP?Ty(U`%4h$#a-}1pF*`W6Ih5O&c#~Y6kbw>}*-E03X zZT#y?&oh83P9J^)3#FU+sUce9m~l~$%ixWs0t=MOMf3DNl0%NH>n58GG1K7X&?BbK zs*Jet3nn#}v(6qMA1l~nUqdRHPii)z7Bkx=^hPB!{(AMxeroYRrxne0x9USS>LI%L zo6fqO7b;Jow<<0;S#_oxu2-|6LMWwm-spwj;<r=ot#2+Kjn{2ztkp$Awg<%ZS{SvinP9%GN{+XWM>bip*9MdtqKq zAUEfV!l_{~8KA*&)4Lqi9tEr@?^N+Hl;fz05lz}@a63^pV%dsWV*0?+XNPXP z%O8YSDmW9Yha(1atorsBjP}xg$&d+_4SJHU&9da=)zja8KEta*6dn?(I_PP^8Lz>u+wnUj{I!nkqjYt^Sf5Riklr;xd{aap<$m;%ap930H+ZA{w!=rDQ_P|T^gA-ObS(he@7yKvop&m@T_*B@-=_PQ()kp7d6Af4py5lv+9L7 zD|63Y;y!1FKMQ6;E?>N0JBH4!&FB2xANtjZ_$SLBM2K2ZFZ^xE2>83Wn$I{I;k=F^ zqm*;j1y_wkwdnj9tX^j??frVQ!QKzP=fg+7aT`*@%JB76(}bZXo=L)sPN8R1x#d$d zgzj3*8lX;(Vf{KWH&wN>*{;a(!w{{my$xZgl&`2a@?aN<6Kzfxt(HychcDPB7O2Wwp`>^AwWW%$%DuA>pvR5szTv`gb($A$&UrK3Y))*Il)4o& zSpHNuMjm}>Q(%3lIl(Zid)tU-0NoTJo9_iR(}k4AoaIuKoPF?d(J)eT<- z!hxVb+SUOZD0cCx(ZSC_uJUFWSgXO{q8Ntxig21+QZ?H;dZQXG5HjhNRt;FRc3V8-5)Q$$8lul4}dkLN;N# zOZ7dOZTx07?czvka2wmEeh(##VxN~(aV&lihq-&+hJ_DL%r)=eJi$VcZAxhf1U-B; zuflTX7B%0odw}=NZ+vvtm4DwG-N{`zrz~hY_KxTr zhS}LQlZtuKyi$vlFuvr|fugQ2&T8dLB$kk{=3VFy=bz?bdh&!y(z;#sgp;)jva>En z&}DpMct@IbpToMY%o-SG1u!#KM>^P2Wy@6IvC%tYmV?P`tJDPdeLqF-2aHtv;m)kT z>;QSh->JMuMgT7Fb4|;FilsYXPcHusq29jw=uN3fibJUb@tg;7tZ)SmgUTuL2A(F! zdM6`=m`N@QQ!5Y2zoH{AKom-TYH<==FGBy$3w2cOz0Cjwws7&nBSW}Dg@44K^_WkpjN~5k=Q+pSWIfyB$^N zXp(-&x?(tK)THZ{`N3&4oJ5~*JaXJ}TTkJg45g$?bejwBOKZ!-Fo<1R@VbKC$vlll z$EMJ4(8gEAZ1BB$Zs_JG5kWM|Mr{^c>sNNqO*gA!mghv)V6BG1i-fOvrg09G!N!=YmFhSVSkV{Bu9v|-)TApn)yAEM z>Ef3i@pcj*FsplzU9$jYCHf6fA}SP~mz+ROKQ!RSW51HYHbu7d{FtOZ%w|2kw+BdL zbgp>QCPv$Uz`zg?Dbzx(ZUC&i)9-q+O_Xei(5CA2eW|MBBn2Z}M!rlwEaCzC`uDq) zCKo_R6pCp82PZ!IcXpvF)@Wc%$x0bVwjncL*MV6#3>wUIBhO_A(9c9*S{P?6LF14W zu={t)+s~7t=UeE$b@E2-hzaa#gFiHf98975zc5kFGkpDKm|*!g3GHE9>;coeIcj^! z3b9e0^8Sn}FSb_gGfLTWQcB+4($TB1T5)i%2@)7#dL_@yRLh*_VC%X|T=<|UTd$LY zr|WtvRhB%9(0KRyRl(&J4aGWVwY!n@A9S;gvxueoep$2ps?oQNgJa@0w=@f^!=E`% znCZpQI!tvMY`Wwv&kpw#MRO!Ys?-uzhIXjuPVp$+cA4!xVOS)D-@cd8i(3=F$W=~b z{@3ZZJv@2bI01`T*R2ZctS753LV2543P9CxhF|deP&V<~bgn)0^{_s;+n+X0>B*2RTj6pAW6^3L)1IK`9C5WK`Y`C6`>03F4$N{5VAq;# zYbZ>A6cg<{!R|!bTun`X$#M5nIl?rgHPe|UvsF}l$!Ff)Xs(ol8J#Rx3P}c0YA_7A zFPn0QV)(F-?K}0v*a_LmjA@uPS_@PVPGS40b05v9t&75YLLNTcVe<^4${RBwFvqJi zWM^kT-JMd|I@x+BN2N$!_KVKlJ3vnSEbgF@YaUAHVIS>h^5^wsL)JGD&i%T!i-Fc> z>y+#=uHGvy-ni#7*>~c&4NgjkEEQ#u&cde(jei$GGpI!Gh%0Q5WK# zj-m!S;$&-9ftHihWK0^4l?e+{Zwf3K^KLQfxcbnn8Vu33g+qKOBa6A-Si9|^i%f`o zCWFs3zY390O=xN>G*QvMz`FW^q3x`Bf75k}7`+MwtC%w1K&0qOFb~yFz8$9(;4*<= z0}Q&(SDG~Z9j5$LHAqof9F_L5TKo2(#YmYtI*h9&%@&)X{P)T!tna-tt-lc2ZrEY! zv*5O&^kqSY+mc&Vm%g{*liFPEqoJ@4qs=e*R`0<8z_>7ZD`nP1cQwH*iK5tctyf=S{Q>EnM~12Fr1Y0L1ekz;L<&U=EsN+`U|2>bzwOS@lm2=xyJxEL zeZ4MdCl^3B(t*t^LB?<_G`MdypDlv<5&GcR)PbLTR;UGDq?t&HzpKv4&c?>#Zrw^F z9>T74t#o~aDOrVUgS2LHZi6tHE>JlQ+}_>SU842DV**d&3phtU0}~v=VzNs7i+G#^ zz^>pb6aYr)_B!A`x!nmYZ|aI4<)-HkP#Hza10Ue?$Gv|*ByX8RKf>jaP!stW=S&#S z2F(#(hPYt9@0DP=^vK0$wq!y*H6ptISqTDf?AgNbV2ZoyZqtzG=EY{K#}4yPaIU+I zO4t}tF-I`C5V5d3R}RV6>uG>0Uh#bdJg4ts7N>M zS6eTwtDYab0DSvJndfklk>@U5yJw{2V65i-F;yeS8ehP6E#L?{3wkX!xjQ8|qy&4q zt1C^XM8g?;rwkF}3PBJ(PowU^FcHc2m7R<&xeZ_dzFG^u0H*2II{aEaMGjWH>BlBu zirJ;fZnv+Zi1$Uk(Clt%4YO~BU>|Ye!9ck=7Orvd&d$GKkDt-`=a*+LA_-fP84`AC z89LbCo!Ne-sJbCLcwzXslH2*F;K_qee|iCsk8P)Hj&Il$6F!uK34Y18Giv6`sKHyU zf=d~tm$Pn#@3fN^Sx-Ppr-;=ryc0J_E=6x{M)^1$8y`PTNptWlva5BkxvU&{?R#`R zul?AVuvMN{DRUO3o7=SNbAya;t6gv97KnTLLM@~4DX%ZzC#?$>9!Umxd~NtcjloCX zW(M#A;6ATuJK3pB=x_l>FF`K8E zF6zIbe5{c})pyBflJJus+mCR6Ebj)e(7m2N4B`h^gd0ys0Ne;az3NrN`0a0e6dlsbJmu%GUqih zuu-Tt6()0om{1J@;E3UshbqrSmz5h{ebW2<>;;T=>cB>{0mbvi>P$}^v697o$~=7! zNX?gE6hMNT3yIX6DlrG8J}O&r3GDG~8ItyU*q?dxr{eu-Ff^kY?n}c^p$}sQ3zJPE z^(6w%?c+`PXcME-b8N?%J#_Ns-|uAx8uR%u{^T>>gdM7OIkKUbCYkv6C|Hm@4>~O* zr^5--Z6uycv*oqK_9Bf6J1X4X96TT7pgZJapH^xu;uDL{D;T=x)tEOWEIw&k#b?=c z6@Qq#_tC1+jW>d0&=~;=E=uDVNTurbGna?XiorR~uy9gPF4gK)>eN}<<*R4cD4Ivt z#nM9_4B`Zevdy~02|dk%Z+g6YFCHQ;eSGLb>1s?c+_Wi@4Yl=NRv+Ey>#~c3gP!in zw9NS~+>*PhMjz(L_mwwdE#7k8h}0dzrjyRe2>+-Jz1t4?@P>zRsE8gfqe`y4k!845 znSDR)QPvN5VV~PJ`_mav8|^R22aBYz#Wtw1-nMJiVKK6MFaJ$lF|iwY+of`a{K$x9f`6hL*_y>rR$0r z6^QJwAzK3HIpa;QG7{w!JR`>u3)UnZa2*Qbb|boT?-uVm@rmt63IdqL8}v9duN=kiIWW z<&xXPc)EVsH3g5&pjT#9jmJiBC@SiI(qm^2eK}Cg2*0j>rR)9OJoQ<%1{a#!~>i|bmrE1^R%Yr<UG7_z7G=32BT?` ziG8$UjJI=&ikFjk8BZnAl`0(q76CPc z74z8AYp^--(o93II>IAG&DPW<8$V{ppUj~8_)v_@ZK&$Jlk<{5rv0?MjguUsYB1%D zSRa)x!@YGAo;PK_ys7t7+CH%wl})eCv*Bt1hOI;Ko8OWG2M zJ(FJ&XFJi}F6%p)t~L*%gIMB*-|(Y;SUZi6b6Ku0U3n*IofcDdzZ8nk+C@|Dvc8+L zR#3D&qA6A@kfjnP^&({}h2g!CLgG|!q{;BEfmBK*DiYJ)Zf@DXnOy#mmEs;K=O>E8 zi>!xlfsykaJN&Si?GPieq!S%NmOaz_R%*}W?)8I*FPgtun(k`bIM*?fj@xp!5kZ_l zpMhv5fu6pCzUYvMMP)1YResfA1{hQ9tAGuk((Pk+h z)=mVXXS9a+RdZe+6_KyK?X$Yb^SXLtmc*g%<2<}|cl5^M|FQPo@l^N!|M($PN-CsO zMrA}OGnr{9GQv4FmF$(Bc~EF;*jt6{y;mjK9D7sQJL5PU;rnFk-?f3iR zeY>6Oy3X5qy`JMS?~nVvMd8-cj!H0zvGGP^Q^far!ZmV(rNTY-r;DETx@&FaKg`5r zC9<_weBdBd_Z=DzpJ^k^R6V1=G_G7ZP=s01U{hSbyuPqzs(&@k?s>7ml5A3@%Z*Zt z`AmJN8%x-z`s{>$HTCV9`T=J-7m;|m7IU4}t@OILujjsw)e6QG#VWdtJ1Z<%WKQq) z3Q?cSDk^lz!(by>Dx3L^y-R$$HWgf(>}Bq|4_`7T?g&(PFI7Ca{w;c2 zMTO1IAKAnagwTR?EIboY9naeKP#@L3ix*s*)e!l->@)s3FEH~GB=g1?4g%;Dx-jtLFe%+E z8(LW{8Uv{oTgDv~jf^A?(PRukC8|u5WQ=}&R?;x*eIn;UId>$u+RC(kWoa4^a$Nqr zChrS!OwmudvC{#pa_csnlI*OkRc>2~YD}*08mN38)vrFVW)yHGlCQB>ALF2=AW;y9 zzLuOzw^#9LtlUOsX~{A#%~TuJ83*HInrB6M9*wW6FQ^0w$2A058EquI_~q8??T)Q0 zL&u;0eE9~q<}n}qsL?TErO2M|@y9lAD2ys`*gSd<0aOI5?x8I>NIqU)i8zBcZBIUq zFt_4AxF3ij48U*}8$!FTAq+K#aooEFvK$_cI@F@%#)_g7kh8ez4qlxsYCzItH}W3M z$?ZhO_Lf}Un>`JOJ=WI<1F@Nf2<#EsSm_-0bj3Tld?883Ghcd1R9BTZ4iBb(7oNZGBm0md&k%Pruf$vEJR#OF!n+&ap7}$NT$76 z+*moUeAvGAa<%mtrof*jRUR>^CIb0^#mM0QbIvEab;^Z|&nb74VQnxDNuKiT| zth%!=Pqe3SA*3E??@!AcyJ-ypF_I~}r3VIW>#ebpK(y7~As{bQ`zuSyvdFsiS-Jq4 z3U!$<93YEmHKrK-E$5JmHik!7dSoU*7A?6x!h2w2gkkjJ59AFq_Osq7^Gfi&n<(ej ze7ekKzrpJt%y=z1`npGXZ>zt&t6pL8Kn+F2#at0_IKgyhMnCA*YFB(KXGT`3&hdjn zQ-Ki}W}GDy6Q5nAN|KF#@_2Z$WwQHWIg#O^`?}N-00mtrgQ3t63H@iu+6DDQLcjR) zNV=iNd9n;?n8Jme#Ca$}hktIn^3QqNgn4r%$`k%4?66=h=t@95lHZS;kUFN!vci}E1 zUx&pvo`$@<#Q;LXi!ngoXajSxB5lurYv2elxxaCRM6X>f6#W!bX*D*s^q!WhTTl)r z8H0(a;1`hEs219d9|7vYARteH!iFmgB4ALO%BBLNfL7AYT|CX9O-~8Hm%_?0Hq)8$ z3i#)moeQ&)A+V_+I)|NfmkcL(pZu#1l+qhGEaJTgGRnmK3^zNy!y4)ar9ie{?)Id&TyD4dyihOzRy;yRj9fy>Egx8P3f*l zPE0FX(nOE>U5=HFO~D%R=%WES{#7I8p_g7d;R;8d8e(+nSi*iF!OodfWqiN+4-nRY zFQ*zVqy&L~xtN^~3H&Nd+6t1~h)|G~Nw4WL%ocT9^5 zh$7b;Us0r670+FqoODx`H`dtF#L%1@=985}X_ul|%EcgjQFe#ts zgOXB%t2^8Cl&RYZ%HA|@Ya8+2Hc>}q_)@S(DTnu5_{tT`4%kC9f<26NwepR!3M%I5 z`xlz;3AV>xmtgc$&gH>FWIgzrFC<05dVI_}y)`=E8psa3WHEA#Ru3{8D?rkaR2|WX z`X)+#)Eda%)HKJ+8Gx2x+7Y2j06YzyZSn32iq0s%wOR$@4LU?kW`ToD3t? z#NI&fzqAffq!|G6?dJDs+Uv1yIOA|&VS;n?qpX7L(>cEg7P{J?TY+>H_e)m&E|X<;$8Bz`_DI6>hy&)HlFti801u8Q}{BtkmWcvrQbH0Q98`8((Je3J@jRcYyZ*z z5rtWEk{TE8YUAb4qa()1Q1g(g=SNJpsWJ~w^khi>h2>hiF;IN4k)_0Zfy%fneu8|p zLhJ160x;NA11)QP$5sn(9u_kasJQde*+Wi3S|{s~_0 z-H~;zcVhR`|1F04yJxK=0Qd%%kAj-OH6_D8)V(fQ>v^Z0&}5XeAR5V>r>B*jB&A5a z7U8MqT|Nra0sOkp|vrVB-w*m?%KQJQo)P0T+;oIj}`B% zCNYZmQ5A*DPnBaIER{;4yxs6da)bxOl;9t+2 zC$iFyULHr4IBuLOm@6f>IaVQ?YnY>QP|d$`*37VRUqXkBo;FV{X4aml$|rI*lCf8_ zCgAwz6I^5GZ8B-Qu5~;+8uC0;Qz@pGP|52UC1p0ZcIKc#qP_1I6LXJVQ%=VI%V@hl73Y_B0|JOoEx*5Ah)ywt2NlE$cxk2TKau0^|zY z>vNN%`K>Wmj@X4vcZBjC$ z(?D!;rqVmSB(!Gi2Q1+srh-4qRdNV&^JoUgOH|m zblK#am$2>ZGfTI3AD$czv01(qCtx1T9KflexV`D;31*IlMfW&wzS|o~EhwP#O4}dN z&bkKmbUvUfyPw4<9wFvrW2bve?XP4YyK|6TI7edvyO5|CH1q89h9=w0L@Cvze?Yu% zZaSynM+f!e+}tV`CGyU!B9Rt<2uuh?c0x=Tb=mZqu&-WgH-GwJ;ule{qU0n-HCvomI5u;?9+ ztJ{8qT{eH(O$m_&V}~GKcK#c&UpIW*Sq$rH}@^CaKzimuRF~Bd-g34$I;x@ z0snl9xkVMLAp772ay!Z98$Gv1a{pNGD#(!QQ~s|=W-}CVEMw>R#@KA8VfmbFwR43V zkJSnB!uC41Td(YArt#x$5MP?U(ut&Y9fL*dQp&K+mXmPJ@uTkdwexA5A~S#a`%F9GF{*AdvXt5=1;4* zEW$1S`s^LD1nrQoww8l+XMW_;uE?A~?E6e(gt$pi8m#&nW|;U_d%k;{E#Okwdp5QY)zK35 zL$7^?BMiI+_n5Kd8gG~E8N3t4{j5yw+x)2EtoQGabY|`h?)@1@&ppv-yxNw0fR{ad z_qvry0I z#FbL;V&LI(TFQElq?Hs2$q0U8K+9HJbO;1u;xYFgh}u-wtnpcQZ`_<5kjd2X!_*hg zdr{c9SJGs1`z>C%@sgcP=jHj=X&-FY^()0b8>Ms~*a1fI@m}|3x+~GwTx>V!xFy|; z4QKnWh}=G@vSH6BujFH4rSA%cM{)k$r9^|5<*f(_XcI{dP$m zkWoE(>Tv(V?Sc$PeUpJi&CfbYyN#5~jy>c)eq3SiUa!tmcf;c1A0849HCcOh$el$@ zUVWFh-aGZV^0aHDcDZUu%vF7*F&b#35sPtV=Yf#Z*#u-`gdZOvs+yEH`?Xs@Gu|Mqx$X`r_C z)x!x&4V)I*+bjk=_2-*9v~IRjYuS=z;TPMI{QX5!EjjUKLELwfj&~jha`=E~!EJ|` z^wRZ*?X9SiOulMxAsFPqgYM)9#lJyXUwtzzT0e3oAcM3%=}aszRwu1jyNo)%a?;X;!|EU z8d~8sxbtr+d)b+&sW^wL$eE%Q8+zpT3}Lh!U)QJ&SOs(~RlxI53Eg^Vxk#w&0f?a*tkI-@5NHK}hBgSp#&(oS0XT{$i?J&S!Y znJ((#IXGai9x=I-({Ob5!$iVxP-y6J-(B|)i3N{~eN&B*4sT7Q_+fxHXxgq>x*yiWhw_jt$u#t5k*y-k_a#IozJxfjP0d zv}{1w=CG^mT1BRnpPqx?wbA*BcuC$xKZ%ns0s~FlR6Ou0)G~amti#I(@J5QUvUAEQ znup$v4xadl6y7Za2krW+;kVae9x=ijD1{z59`OAyX6`$7?dt^=l*NFwjGsZ(=zzrw zf@IIJqU7DS*K_AF>4mi#?3cnu1Ye(j8Bq6<`r(Eh9zVeF2_!mEIh(V}FhG9%8TX>($KguhAoFit0WYpzi39M(VaM;Uu@Qnt#<;l{YGh04e$FO*}?%Lbls z9!OM5rU-8Mei=U?Xy9PR(i<*7v7hA=iL%RZqsCeP&E|L>fz#5>pMT*LYP!_IaY{CT zylnOvxtv4o%VC${ug~lV6VdUt{<2S7!qEO%nwUU-E!F1}=;wDNC`A8=QIV`h-{5t= zLLNNB2`W_+Q_YgNVGS{uNZ=*udoCW@}p)AxVmXecXLp}Z#{g^v9C-53B+tkaTT*8@s)pl z(+he?^!^Cq%{7+@#?4;psUDb&l>q&+OUN@ev!f1I_dK=z5qkVC;{5)!n-TG4YNWW& z1!bo>H}BO2$Q10Z?yvaLu@%BBeUKVm?)$d5|8IUIdJGx!d~^zq0XD7W+~xx^&jr@I z%w~%IGW@0nku3VC(?J`{&ENXHe(!R?2KmDQI+hA70*pCZTwtDprZT9(|FQF7t$nogL+~gLh#Q0l@z+fc7-hMEnV(Vh<>Ou|RQE zprv9Z4QhHTprk?t%xF2WXYWvSoo=;(_Q3q=Y#9*k_Z|Vk7290=yM|=V9N8&7Dd-(R zB)Zp2{5-CQf9C89Z}Y8FYbqDNlziGSRi}9*^+uBZj)-uNGudL+1uPG+lWW4*zzIMA z2SOvY{0}IJ6DG0pR%%+#aV88#{a0$*j_mc90h23=_6;5OM-Wwkvo;BTv8WR5EVBw{BPu z#GkPmS%!vZG|PjLp^htILiO5%^1^*X+G&2N-mX`pQP~ucRz=f7wz?^C;y_V$yo$H^ z9364z#}k^B;zM^dE^YlFA%Kf<=Dj;&dRq1*Y0SFz&XL{kSQ=^k>?Z+7b( zaftKUqKGOCE+rWg`u7^4NSzQw|JGwd_YsN>jdOdcV2smt^Z|uMPM;g059UVSCMVUd z%)i^pRCR}1BG{rL#3=GO(AQfc0~A1_S_}FjR{L~Z=PKr*A}N~mN^sl3E77gvSMITq zl1HDjV;DUdL+M7Lzb|EQCi+7s*;34b^q((D?m4z^tgk2!;Z@Zh>dep|_S(TyW&IBD zNiU!|Q+L7&rgF!y=WxG$z>iNH3dk$H0(!F3efY&cY}zL{>03uD+M7Tq`Hb12mn;ap zXpaaegAR=~y=pGBHwyt;(Sf3yz`#Ebj~_Pf0UIaNfCBUH{g%kVI(-_;c(i`$ebLm4q80tn8G;rn)hSdH{ z-AI0U3Fb%e&gJ)NW6Ig!tsV+7K<(l<0>7&Rs`$GhKx)SfXy}Gh%ON2l&82QGT_rAg z;h+&Xk~9;({HN-8-aje ztOnA%;h`6bfh~%Xec}9Y>AHmT?mv38v&nY+lz@`!^4IGLx+R4oh#h%d}S4t;iR-uzK&eCRRLZw-YnKt|b?(kO~GnQP*3M(%a* z1!uZrN?Zt`s}`UZnrS<#kO2KEW4)dnGj?>M>fFe2T=6<;9n^gur6>e(Yhg?~Qn?wH zleF?u2lTh{`xICle7xjrW!6SGEb4Fxd{``CQkzR$91}1pp?cIhbD*qH1s%hBp(U3q zvwZ+#RJS{UCwYwUP%e)+M{8qzh$YbkP50HXS_7gE-5AmBK=)SL0U2Ni4uUzj{jhXv zs*5E1+|rB%H-L?}rJuFO%$-;W3PFe&sIy+|Bmz@($=t_-&m$u(8B?3)6fa%+S};Ca zwqcp7rUvBvXa*s3<6K)pW5?)A-h*o^^GNe5LF8Tp%d7wgjlaWP{eukvtu&&+{MkI99NQDNZ zJIGEC!Ltgg4f6uaSR`-3(B7=aK0}CP*C^Ml8@avxIY(p7b8j@oyZegoq-#DV0>D2A z20sdf`CH%|1;QDU0p}jBA5kLJNB~W{Dln(=Z|Zet+}j4lK&i(D^hb;6!%V2$$W0mE zE~rhP!Ic7v@ni$c^3-G`P#EgD;n6gwYeALkqQg_A%1?S5M71aS2T$V*1^<{)LGUN-<&VEWn~}m)U*qPi^15uEp}yxnqd!1PzZz? zK#^E{sD|My2FB3!==h{elYE_snBE4YDcmX(J z%hVmxj>=eFSO$~*6qBMUGTBGt+y@{QzK4tNo*>FkSBh3gCvBTn*PEk&Vr+2_)rPaM zn;t^7tekPJ=c-xT9641_C4KO*<|8&?IsfVtPBUa zq*0o#XV&uY2SfoC=<$d2yt_EH8C&mnZcYq5IUwAcK0ph#+S|4^mp6yW=kG)4!Es<4 z&rzfnt)X4|{>9nLKE{L4pAVMGVobFfD1C|cED6JmL1Qnz?go{w3Hep3ym4P8crj#P ztiLE2W?<6g%MBU6*a|!DH|x$eu^Dh9gba@J`sB=KVa8f18#J3V!Z2~IyR$I?_%=3$ zaARqYr9#;N&JfBN26ZH|pqX!`Y+zVyF~!ZqvB+CE;Eh}&bRYH!gvXyvy%y%P@$t#w z$tetgH&xa&W=T?llhBFwA(jMWw8easOP!J9Q=BMFl69#jVni(%mfJjXFhgx$Q+@ig z`)q2t<6b(Rg^cXf4tze7*lnd5aHJuU*wXQ!_1L!ef+vzl6djp0lY$jP_*e&6#HdCm z@1THpW8<4}A{O*Kfu<|Z&CzvE3YpX|$)9m1|JFoAsaBjcy?=RRm& z*4XlnfpiV7n!HCx$pB#FkApfQ-$Q|+_5>An!i0H@0F{WT60qDmjN#sGKQQSVP7yy^ zA7->94iU(eZD)EslMkfaPGpf1Y|}d-`R!|YoK385d|&C>l9o!7a`{JwWg@sOSBhQ% z^>{jTj){^c*QC&lAi=!rKbT=f|7FBGk5d}>#kltZaG9{dy&0vqbEj`i@VYY94 z^pV7s&wagwyQRX@jr3H>lP=O>{XGon4Q4wkU077t>gAXgiGtBYkS`CZ&q>U8Pc0az z)x4@Ui=`5POsB^w{~clwM;H0ExtIuJP3J5D+SGI{(cRE_)#qgz!<*bB*~xM);>vWN zW$B9H3UFwIS1^2N-+H6C2jZS1!o9cdXh6eY>(2e3%)iX&MN{I4A+N4a07|HzEO8op zPrKB$U}YuUu%5wId+iafk#crljrE*FZrX~Jo9!%(u@+(V%Ir}po5^wtqRfC}cXLZi zeIDspV?t}IYSxwVPek3FapQM{7;^RUEF-$)XT2f*I~jZ~oqKcieTw(mMn8-4;S8qb z_V@drnL`mIq4AGo{+=Zm#3peG?FfXCOoIn}Ya{QgwwQG=zY(H3+07!6^%fr_PO51tQ7=M@2uyjV|tz z@9uaOq(*Ss;{EZQ$P7bqUU{8nH69c*@m+drtgDd7S#a((LoF^eN(u)&SZEe@IasnG zu($z-P8J-S{H2zlX&C<=>a}g8qdM1-rl$u3DF#gMizz6N7YaAj=03~p*t$*N)0-49 z>GO~v^%NJT>BS3vN}J`U(lTxFJtXjY!g9t%+Ao%6{92NDkzag^Wsp)ay>yq}tQlS~ zEykTn*sNvs5?9V-30(df@NasNDa{20mo7J^@pacHDrZD5rTHCM^QE-&ipj zLGWtRbb&r(tBGc|F$-vY6(lgGwQY+>xq zKC=j>f12Pv*RLme)IJ%{uM{S6{^r)tC3yzlflcq*P)wTFQ5g7b9Dim~ z!QgYfRx%tBU3#Me85NW>I8qw`Yld;Pcw|vTOvlmL35q37Ka*iR^;smMKhG*EAv=l0 zB&9T&?&x&jvuD>6&1MG522`K4QaL^Z|~#Fnyyma)$QyQWMe9aNBTHREMD< zX3GczElhjA2x){IRxwI~EjkIFX(ys6q8HCsn|&k+GnEtOXxywD8PsvDPFiH<4h0n- z;SR;QvTyTp2^v{(1GQ~RkwoKzpw@0Y-1RM6r^w-c|A6M@cD*dFxXCT#T$tpO)cZPn z;1G59jGO7^KK5UONn3_@&??C5%awLn#&+(MLZ(UlCnMiVHGaEKd zF~vd{6S_OkZI{~`M2zwk4iW9?a{ynCc_G2{X1pya2zV2i;*KmM`T*wFwZESo!EY&& zmEQzc`7bc_Hm$a=ag!D*a#U6f2<8WEozOao92TOI2ga&#S|VMta`BKewP^rBY8p;) zAP|s;HeTw(Fex=PYR&ovk{=nHm5p)fK~NUbSHq)OW4K*9$ZKD}-k&qr6%=P5LcyO}EL zk^&Vb)xp%Zq?|H_L$feKd<7(&ClfOpO`jr~+-!G~2-A>PK6AUXyP*%neAs#ud|OR( z131w(PZ(>YUNH*nUF!A)WNm0-ITA+|P{iMHXIpfS1U2aGsS{@KiV@s>gbxr0n0##0 z2=Tj*oQS>wDIFV0?U&T2jNgjn#dXB@n0!+IeiRx_1hKQI!qv{0nI!j*3Q#9|RD=n1 zkUV|Tw3VZ2u6<&f;bYrYDNL%i31hx>nIxX6dQm*JzN4IPW}Tc;YAaEL-?H~K&8Ifo zaTmE+t0He_?Ww_$C5AUvGj3ZfCf%b<@D4@q^H=xJm{5fhV2J2MbI0{^p8~bfU7m`v7Ax;LnK=P}&@cmPCKGK(XBmm`Uo5~i&fBiT3f*15>4i_JAIS+6fyY~I( zRZyC|<3QT*ynS1xrErp8sl=; zSJ!i$^A-S_EZu;?Hl52FTxhdkK3;ijK_RHxG*Qc?d{~8=aV<#o)TL@ZYu6#^lF&Wr zsqDgpO@pj3-W8O)4DldxJ9L*u;cH%kMk-n8%LLfIJ{Vyt-}@6Hxcu*BNW^lIc< z_L&OJ?UEnKjUp6+X%L)oPMZ)mL&Q_VWU=SHqDJ?U6hSgBJ! z;Si0^vrY?xFv-}y+bjF$F>r%p8KMok7KT~HKKLBdG97Wq=E8$kt4iaP2yHsU8kJqC zZ_`F6`%8+Fwel3E5(hMg^^(>g&e2*2In~afW5{?O$kB(b0AI-icgq5;==FlxG$~0l zP{bfPIolGhTi78@ zC59m59a24QzJp)B-0UxQQZBGDQ2C7J@?jKrR!xQBHTM061DcQ&!stk0xrHXT@|Gqj z(Cne|m^f7uCi;kuV==e`mF*Le^ZX5lK?f4sslK9))ohqtA&W+2hgBZKm@Z$Oa;~k7 zB#mVwve6S^4Ev^9;{Bqs4(XYz4Y#rO$5an$kw?~8ZOdaGOw~_DUs-5bENyiWljIf` z@9XV}!mbx2*rj?(>WrjaFhiYDT>>SuQzRJdT3!$q6qgk$G-f$x-ns7UtgM|DY@H=1 zl|MBmWKyHZ=pp_!sQ8CG_(F_++^6QIexXc5st07$>d%owp-zZ;@E8=xBZxLJzM5SahjcJkhO1@f9ekO@?(%1}j z_})K8bhK zrLr}>rj2;+0g2K;nIov_nY1)B%Iqs#m$vrUF;Nk$dUCldQ=#1goQiHuZ=+K?2rqJ9 z?)Px$@jJkO(HTDxP+sohxtjGswDn+}ktf00t-dIYmln2fPP$1?uVYGg2_nkN8|!QJ zFN;+t+NictF&ty4=@?nl-9`IIP;^17;qxyp0E0EUC#C%muJHj;TY_rBbEmJ&5)!&o z(bk|^26n}LkK0B**5P~c37BL;eRoVnog#LfcK>#pFdRBAwYFnqJu^*?dP;``cJleF zqZ0d&_$>(Hx5IW~iwm4eSzHf=Eqm1$`@eQ%zbsvQOi4_X)HB(b zaoEjP_#4tvwJHxCgQ{DEpb*ULD_p+3r>HyY@Gf_RMF-xOZp|RYr#1U|hGR=~Bt^L? zFe}-PHqbe;R`tI3MfPtC&QEOq-uBk<9M)sUsxHv$+)R8D38iA?cm+UQ#dsA=!4yOd z6!0wKrX@lTbm+ai>!ee(0zjNDkf_>C_07b76k318-UeOJsy!4RYMD-A?1*oLDyIsR zHYHZm-Sr^Nve78COVF4-9J*Na!jJAIeqZkEQP3B@3)Wix7g3DW-yZ&r-YiRnUpLx%Uu{y?B{M?avX5WOTbOK z>GUtad|j>>r~()Gl?tir;^sbj?Nur>naP~0-^}UrlE?{ko9CQev&3cBU8GN(` z21T?BM3Wmoy{xPpV4eeRj>0P0Z4!@K_{4FyO zM{4rQl{+wWf=Y0V>l(hp1_XeS7OV}Gq#Nj3^4SbsYT@dWDaRo-$&il3G^lFxxAbER z%GJq1h;I;S%`&t%+m@^oC*!)a2rG8(K$g}Fd@WgtKo|=RU4Mw%-iKR31^|Rp{QT3i zX^6+c1h?%oM`?1&n^l-tKorW#g1dBC^HBZ4L$B0<;$6Us)u4ppe-E*TXUc zE=0!Gee&NG-M+Iz*gI`iua{=R7M%Oc@Vb?A&SA$$*4uveypA89wKr9#!vgAT#lH51 zP&!7M2N8=si~LG=5| zlz!@IH|VifZJ`$XLO54-NVU~0t#7QIB#5;Ah$yM<*1Iz=T4dxSsOZKA_2{uV`>n6GE?*s`YCGhz4wmc!pT(rjsqMwr&8-C zc~L1b(?G5lHfR#vvuh%R{Oo!xiyBp$Ns?wxqVbzvHF6c5vfFbvTKuxJ1tO>lNwa78 zVMZzBl)jHbjR(n=p-7jRQ!S)VAsA?=F0IE+I>= zyh*L7(9PAgSlfMN_~pPM91z1TgcwJ4xR(G=r2!bh5u<1Q14P}LlpEI3>*TgrNTYmh zw5Qf7oT=JIy?f5ivbyP+4&Ty~PjZ+%J=I&#lH49eM@--HCklI>Z8tsr=z^n&Q;(>C z*7%)~?nOfL|GH`iWZTgp6z8XLFLVr?T#fDgwC+fxgKq{U zl=n>2j3S-l4xO>9QhkZ^(_D2Y!Mz@ZK4kv(mT~)KAnnyF(`}I4aJ5bN6?nRJomDj3 zhKR8mmH{`<0}LK-xs{rcHie6ZpDNezm+d{)wFIaGP#95_he?| zaHw6{4uQjuG~RsFNxR(WQq39^{MHS~*^H|)!Mcj@sEG?i1IlF})ZUp%+qPa%B)8VW zvtP}jLY2yjXwzoe%HZGrHLlNc|(o_xIqX*3t;x=1JOpUjDW{W^HMRe?*dNb4lw!$y`P(>08$ zBU9yuK&&j?+1ClQS5I_i5*-e zlplO9(Vf5BG0^2=Xk<8=J3KQ}QZ%q2W)mMNvLM3WaUM&sS}wj)>+McY=~Nc-ahfo` zdZlsc(ET1Ou9kt))tL@lz6v2 z4meh{h+f+&+CZ#-QO^~Jy&xsO5$kc#GM~l$(oLlLWE%sdtXf4(19r3h;+au&n;pso zBE3C-fE}e{`EKv#;9=W&usbs1>ReP1O(r;TeuNAwPBx74!b;rkezcm-uo{gddXJi? z&HzT&$v}lU5vVlXRlFN-?KgugVnY4;RVGWcy&ick?GR=g(nU-MuvQEDq9rVf(s4l@ zl;+xWc8kK<{ThU{r-?-6;bzw`PExMr_)p=XA6b(i_Y00BK`*0G4#3Ttiq(5pz(-t8Bb`+dw1DdGR<_DdD_ugm_i@6SQn!6JD8OBh%!$Wg2sfOO+j#P?g zS0Vc?dM0GnUWeY_?s}XyO?JozeY?^3IbEq6WN$k61pIoy{jJt{x7t6Ec8C6HS(qFi z;apH*wZSJz*({65QA#OBigoRRhRCOoF(?Bi<#t26M(wOlV-hDZ(zZb))iftHga?)4 zCTM_d6ek2HrY0RfpJ0TcYXrhUV

*LO+D)R8<}$A5+t!AX?AuyHPb7vMnmeq5wB5 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 z

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 diff --git a/docs/examples/usage_example.ipynb b/docs/examples/usage_example.ipynb index 7e0214f..3cea6df 100644 --- a/docs/examples/usage_example.ipynb +++ b/docs/examples/usage_example.ipynb @@ -51,7 +51,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -86,20 +86,9 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/client.py:195: UserWarning: You're connecting to Argilla Server 1.21.0 using a different client version (1.24.0).\n", - "This may lead to potential compatibility issues during your experience.\n", - "To ensure a seamless and optimized connection, we highly recommend aligning your client version with the server version.\n", - " warnings.warn(\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "import argilla as rg\n", "\n", @@ -112,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -128,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -144,18 +133,9 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/s0/4h4_2s7n3wxbm06wx8y43mm80000gn/T/ipykernel_86259/2413633764.py:1: DeprecationWarning: Call to deprecated class method from_defaults. (ServiceContext is deprecated, please use `llama_index.settings.Settings` instead.) -- Deprecated since version 0.10.0.\n", - " service_context = ServiceContext.from_defaults(llm=llm)\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "service_context = ServiceContext.from_defaults(llm=llm)\n", "docs = SimpleDirectoryReader(\"../data\").load_data()\n", @@ -172,20 +152,9 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Response(response='The author worked on writing and programming before college.', source_nodes=[NodeWithScore(node=TextNode(id_='c9202a57-b440-4d86-9a5e-795ada63ba29', embedding=None, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={: RelatedNodeInfo(node_id='5ea14634-052e-4b7f-b930-9025ae6202b3', node_type=, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, hash='d2f61ad5c414d7e0b68273550ae08d00f8931141e7666b3f86f68b0f81a6abdc'), : RelatedNodeInfo(node_id='a09c8100-edf6-4ccb-9cb1-dcf80bb979ef', node_type=, metadata={}, hash='692d74391b6ad961556d19669374a543e4752bab10e415d8eeeda9ccf682a597')}, text='What I Worked On\\n\\nFebruary 2021\\n\\nBefore college the two main things I worked on, outside of school, were writing and programming. I didn\\'t write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep.\\n\\nThe first programs I tried writing were on the IBM 1401 that our school district used for what was then called \"data processing.\" This was in 9th grade, so I was 13 or 14. The school district\\'s 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain\\'s lair down there, with all these alien-looking machines โ€” CPU, disk drives, printer, card reader โ€” sitting up on a raised floor under bright fluorescent lights.\\n\\nThe language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer.\\n\\nI was puzzled by the 1401. I couldn\\'t figure out what to do with it. And in retrospect there\\'s not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn\\'t have any data stored on punched cards. The only other option was to do things that didn\\'t rely on any input, like calculate approximations of pi, but I didn\\'t know enough math to do anything interesting of that type. So I\\'m not surprised I can\\'t remember any programs I wrote, because they can\\'t have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn\\'t. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager\\'s expression made clear.\\n\\nWith microcomputers, everything changed. Now you could have a computer sitting right in front of you, on a desk, that could respond to your keystrokes as it was running instead of just churning through a stack of punch cards and then stopping. [1]\\n\\nThe first of my friends to get a microcomputer built it himself. It was sold as a kit by Heathkit. I remember vividly how impressed and envious I felt watching him sitting in front of it, typing programs right into the computer.\\n\\nComputers were expensive in those days and it took me years of nagging before I convinced my father to buy one, a TRS-80, in about 1980. The gold standard then was the Apple II, but a TRS-80 was good enough. This was when I really started programming. I wrote simple games, a program to predict how high my model rockets would fly, and a word processor that my father used to write at least one book. There was only room in memory for about 2 pages of text, so he\\'d write 2 pages at a time and then print them out, but it was a lot better than a typewriter.\\n\\nThough I liked programming, I didn\\'t plan to study it in college. In college I was going to study philosophy, which sounded much more powerful. It seemed, to my naive high school self, to be the study of the ultimate truths, compared to which the things studied in other fields would be mere domain knowledge. What I discovered when I got to college was that the other fields took up so much of the space of ideas that there wasn\\'t much left for these supposed ultimate truths. All that seemed left for philosophy were edge cases that people in other fields felt could safely be ignored.\\n\\nI couldn\\'t have put this into words when I was 18. All I knew at the time was that I kept taking philosophy courses and they kept being boring. So I decided to switch to AI.\\n\\nAI was in the air in the mid 1980s, but there were two things especially that made me want to work on it: a novel by Heinlein called The Moon is a Harsh Mistress, which featured an intelligent computer called Mike, and a PBS documentary that showed Terry Winograd using SHRDLU. I haven\\'t tried rereading The Moon is a Harsh Mistress, so I don\\'t know how well it has aged, but when I read it I was drawn entirely into its world. It seemed only a matter of time before we\\'d have Mike, and when I saw Winograd using SHRDLU, it seemed like that time would be a few years at most.', start_char_idx=2, end_char_idx=4320, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n'), score=0.8174733404525298), NodeWithScore(node=TextNode(id_='8222d396-1cd5-4c5f-8e15-f44be1213d6a', embedding=None, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={: RelatedNodeInfo(node_id='5ea14634-052e-4b7f-b930-9025ae6202b3', node_type=, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, hash='d2f61ad5c414d7e0b68273550ae08d00f8931141e7666b3f86f68b0f81a6abdc'), : RelatedNodeInfo(node_id='a9c7fecd-4294-40f1-a3cd-4ac17d353690', node_type=, metadata={'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, hash='d400a52be04e5618ab70268c1d968c31994c6dac8f5bbf42b0718b20a20a87d1'), : RelatedNodeInfo(node_id='5414fc88-0d20-42e0-ac85-c0657e5b2495', node_type=, metadata={}, hash='e2113e037176fee3ca0a39e438391443ddef7be5532d5af8ec3fac40179c5a22')}, text='I didn\\'t want to drop out of grad school, but how else was I going to get out? I remember when my friend Robert Morris got kicked out of Cornell for writing the internet worm of 1988, I was envious that he\\'d found such a spectacular way to get out of grad school.\\n\\nThen one day in April 1990 a crack appeared in the wall. I ran into professor Cheatham and he asked if I was far enough along to graduate that June. I didn\\'t have a word of my dissertation written, but in what must have been the quickest bit of thinking in my life, I decided to take a shot at writing one in the 5 weeks or so that remained before the deadline, reusing parts of On Lisp where I could, and I was able to respond, with no perceptible delay \"Yes, I think so. I\\'ll give you something to read in a few days.\"\\n\\nI picked applications of continuations as the topic. In retrospect I should have written about macros and embedded languages. There\\'s a whole world there that\\'s barely been explored. But all I wanted was to get out of grad school, and my rapidly written dissertation sufficed, just barely.\\n\\nMeanwhile I was applying to art schools. I applied to two: RISD in the US, and the Accademia di Belli Arti in Florence, which, because it was the oldest art school, I imagined would be good. RISD accepted me, and I never heard back from the Accademia, so off to Providence I went.\\n\\nI\\'d applied for the BFA program at RISD, which meant in effect that I had to go to college again. This was not as strange as it sounds, because I was only 25, and art schools are full of people of different ages. RISD counted me as a transfer sophomore and said I had to do the foundation that summer. The foundation means the classes that everyone has to take in fundamental subjects like drawing, color, and design.\\n\\nToward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they\\'d sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I\\'d done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian.\\n\\nOnly stranieri (foreigners) had to take this entrance exam. In retrospect it may well have been a way of excluding them, because there were so many stranieri attracted by the idea of studying art in Florence that the Italian students would otherwise have been outnumbered. I was in decent shape at painting and drawing from the RISD foundation that summer, but I still don\\'t know how I managed to pass the written exam. I remember that I answered the essay question by writing about Cezanne, and that I cranked up the intellectual level as high as I could to make the most of my limited vocabulary. [2]\\n\\nI\\'m only up to age 25 and already there are such conspicuous patterns. Here I was, yet again about to attend some august institution in the hopes of learning about some prestigious subject, and yet again about to be disappointed. The students and faculty in the painting department at the Accademia were the nicest people you could imagine, but they had long since arrived at an arrangement whereby the students wouldn\\'t require the faculty to teach anything, and in return the faculty wouldn\\'t require the students to learn anything. And at the same time all involved would adhere outwardly to the conventions of a 19th century atelier. We actually had one of those little stoves, fed with kindling, that you see in 19th century studio paintings, and a nude model sitting as close to it as possible without getting burned. Except hardly anyone else painted her besides me. The rest of the students spent their time chatting or occasionally trying to imitate things they\\'d seen in American art magazines.\\n\\nOur model turned out to live just down the street from me. She made a living from a combination of modelling and making fakes for a local antique dealer. She\\'d copy an obscure old painting out of a book, and then he\\'d take the copy and maltreat it to make it look old. [3]\\n\\nWhile I was a student at the Accademia I started painting still lives in my bedroom at night. These paintings were tiny, because the room was, and because I painted them on leftover scraps of canvas, which was all I could afford at the time.', start_char_idx=10764, end_char_idx=15165, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n'), score=0.8070322562070888)], metadata={'c9202a57-b440-4d86-9a5e-795ada63ba29': {'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}, '8222d396-1cd5-4c5f-8e15-f44be1213d6a': {'file_path': '../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-02-21', 'last_modified_date': '2024-02-21', 'last_accessed_date': '2024-02-21'}})" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "response = query_engine.query(\"What did the author do growing up?\")\n", "response" diff --git a/src/argilla_llama_index/legacy_llama_index_handler.py b/src/argilla_llama_index/legacy_llama_index_handler.py deleted file mode 100644 index 645ae58..0000000 --- a/src/argilla_llama_index/legacy_llama_index_handler.py +++ /dev/null @@ -1,694 +0,0 @@ -from argilla._constants import DEFAULT_API_KEY, DEFAULT_API_URL -import argilla as rg -from typing import Any, Dict, List, Optional -from packaging.version import parse -import warnings -import os -from datetime import datetime -from collections import defaultdict -from contextvars import ContextVar - -from llama_index.core.callbacks.base_handler import BaseCallbackHandler -from llama_index.core.callbacks.schema import ( - BASE_TRACE_EVENT, - CBEventType, - EventPayload, - CBEvent, -) - -global_stack_trace = ContextVar("trace", default=[BASE_TRACE_EVENT]) - - -class ArgillaCallbackHandler(BaseCallbackHandler): - """Callback handler for Argilla. - - Args: - dataset_name: The name of the dataset to log the events to. If the dataset does not exist, - a new one will be created. - number_of_retrievals: The number of retrieved documents to log. - workspace_name: The name of the workspace to log the events to. - api_url: The URL of the Argilla server. - api_key: The API key to use to connect to Argilla. - event_starts_to_ignore: A list of event types to ignore when they start. - event_ends_to_ignore: A list of event types to ignore when they end. - handlers: A list of handlers to run when an event starts or ends. - - Raises: - ImportError: If the `argilla` Python package is not installed or the one installed is not compatible - ConnectionError: If the connection to Argilla fails - FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails - - Example: - >>> from argilla_llama_index import ArgillaCallbackHandler - >>> from llama_index import VectorStoreIndex, ServiceContext, SimpleDirectoryReader - >>> from llama_index.llms import OpenAI - >>> from llama_index import set_global_handler - >>> set_global_handler("argilla", dataset_name="query_model") - >>> llm = OpenAI(model="gpt-3.5-turbo", temperature=0.8) - >>> service_context = ServiceContext.from_defaults(llm=llm) - >>> docs = SimpleDirectoryReader("data").load_data() - >>> index = VectorStoreIndex.from_documents(docs, service_context=service_context) - >>> query_engine = index.as_query_engine() - >>> response = query_engine.query("What did the author do growing up dude?") - """ - - REPO_URL: str = "https://github.com/argilla-io/argilla" - ISSUES_URL: str = f"{REPO_URL}/issues" - - def __init__( - self, - dataset_name: str, - number_of_retrievals: int = 0, - workspace_name: Optional[str] = None, - api_url: Optional[str] = None, - api_key: Optional[str] = None, - event_starts_to_ignore: Optional[List[CBEventType]] = None, - event_ends_to_ignore: Optional[List[CBEventType]] = None, - handlers: Optional[List[BaseCallbackHandler]] = None, - ) -> None: - """Initialize the Argilla callback handler. - - Args: - dataset_name: The name of the dataset to log the events to. If the dataset does not exist, - a new one will be created. - number_of_retrievals: The number of retrieved documents to log. - workspace_name: The name of the workspace to log the events to. - api_url: The URL of the Argilla server. - api_key: The API key to use to connect to Argilla. - event_starts_to_ignore: A list of event types to ignore when they start. - event_ends_to_ignore: A list of event types to ignore when they end. - handlers: A list of handlers to run when an event starts or ends. - - Raises: - ImportError: If the `argilla` Python package is not installed or the one installed is not compatible - ConnectionError: If the connection to Argilla fails - FileNotFoundError: If the retrieval and creation of the `FeedbackDataset` fails - - """ - - self.event_starts_to_ignore = event_starts_to_ignore or [] - self.event_ends_to_ignore = event_ends_to_ignore or [] - self.handlers = handlers or [] - self.number_of_retrievals = number_of_retrievals - - # Import Argilla - try: - import argilla as rg - - self.ARGILLA_VERSION = rg.__version__ - - except ImportError: - raise ImportError( - "To use the Argilla callback manager you need to have the `argilla` " - "Python package installed. Please install it with `pip install argilla`" - ) - - # Check whether the Argilla version is compatible - if parse(self.ARGILLA_VERSION) < parse("1.18.0"): - raise ImportError( - f"The installed `argilla` version is {self.ARGILLA_VERSION} but " - "`ArgillaCallbackHandler` requires at least version 1.18.0. Please " - "upgrade `argilla` with `pip install --upgrade argilla`." - ) - - # API_URL and API_KEY - # Show a warning message if Argilla will assume the default values will be used - if api_url is None and os.getenv("ARGILLA_API_URL") is None: - warnings.warn( - ( - "Since `api_url` is None, and the env var `ARGILLA_API_URL` is not" - f" set, it will default to `{DEFAULT_API_URL}`, which is the" - " default API URL in Argilla Quickstart." - ), - ) - api_url = DEFAULT_API_URL - - if api_key is None and os.getenv("ARGILLA_API_KEY") is None: - warnings.warn( - ( - "Since `api_key` is None, and the env var `ARGILLA_API_KEY` is not" - f" set, it will default to `{DEFAULT_API_KEY}`, which is the" - " default API key in Argilla Quickstart." - ), - ) - api_key = DEFAULT_API_KEY - - # Connect to Argilla with the provided credentials, if applicable - try: - rg.init(api_key=api_key, api_url=api_url) - except Exception as e: - raise ConnectionError( - f"Could not connect to Argilla with exception: '{e}'.\n" - "Please check your `api_key` and `api_url`, and make sure that " - "the Argilla server is up and running. If the problem persists " - f"please report it to {self.ISSUES_URL} as an `integration` issue." - ) from e - - # Set the Argilla variables - self.dataset_name = dataset_name - self.workspace_name = workspace_name or rg.get_workspace() - - # Retrieve the `FeedbackDataset` from Argilla - try: - if self.dataset_name in [ds.name for ds in rg.FeedbackDataset.list()]: - self.dataset = rg.FeedbackDataset.from_argilla( - name=self.dataset_name, - workspace=self.workspace_name, - ) - self.is_new_dataset_created = False - - if number_of_retrievals > 0: - required_context_fields = self._add_context_fields( - number_of_retrievals - ) - required_context_questions = self._add_context_questions( - number_of_retrievals - ) - existing_fields = [ - field.to_local() for field in self.dataset.fields - ] - existing_questions = [ - question.to_local() for question in self.dataset.questions - ] - # If the required fields and questions do not match with the existing ones, update the dataset and upload it again with "-updated" added to the name - if ( - all( - element in existing_fields - for element in required_context_fields - ) - == False - or all( - element in existing_questions - for element in required_context_questions - ) - == False - ): - local_dataset = self.dataset.pull() - - fields_to_pop = [] - for index, field in enumerate(local_dataset.fields): - if field.name.startswith("retrieved_document_"): - fields_to_pop.append(index) - fields_to_pop.sort(reverse=True) - else: - for index in fields_to_pop: - local_dataset.fields.pop(index) - - questions_to_pop = [] - for index, question in enumerate(local_dataset.questions): - if question.name.startswith("rating_retrieved_document_"): - questions_to_pop.append(index) - questions_to_pop.sort(reverse=True) - else: - for index in questions_to_pop: - local_dataset.questions.pop(index) - - for field in required_context_fields: - local_dataset.fields.append(field) - for question in required_context_questions: - local_dataset.questions.append(question) - self.dataset = local_dataset.push_to_argilla( - self.dataset_name + "-updated" - ) - - # If the dataset does not exist, create a new one with the given name - else: - dataset = rg.FeedbackDataset( - fields=[ - rg.TextField(name="prompt", required=True), - rg.TextField(name="response", required=False), - rg.TextField( - name="time-details", title="Time Details", use_markdown=True - ), - ] - + self._add_context_fields(number_of_retrievals), - questions=[ - rg.RatingQuestion( - name="response-rating", - title="Rating for the response", - description="How would you rate the quality of the response?", - values=[1, 2, 3, 4, 5, 6, 7], - required=True, - ), - rg.TextQuestion( - name="response-feedback", - title="Feedback for the response", - description="What feedback do you have for the response?", - required=False, - ), - ] - + self._add_context_questions(number_of_retrievals), - guidelines="You're asked to rate the quality of the response and provide feedback.", - allow_extra_metadata=True, - ) - self.dataset = dataset.push_to_argilla(self.dataset_name) - self.is_new_dataset_created = True - warnings.warn( - ( - f"No dataset with the name {self.dataset_name} was found in workspace " - f"{self.workspace_name}. A new dataset with the name {self.dataset_name} " - "has been created with the question fields `prompt` and `response`" - "and the rating question `response-rating` with values 1-7 and text question" - " named `response-feedback`." - ), - ) - - except Exception as e: - raise FileNotFoundError( - f"`FeedbackDataset` retrieval and creation both failed with exception `{e}`." - f" If the problem persists please report it to {self.ISSUES_URL} " - f"as an `integration` issue." - ) from e - - supported_context_fields = [ - f"retrieved_document_{i+1}" for i in range(number_of_retrievals) - ] - supported_fields = [ - "prompt", - "response", - "time-details", - ] + supported_context_fields - if supported_fields != [field.name for field in self.dataset.fields]: - raise ValueError( - f"`FeedbackDataset` with name={self.dataset_name} in the workspace=" - f"{self.workspace_name} had fields that are not supported yet for the" - f"`llama-index` integration. Supported fields are: {supported_fields}," - f" and the current `FeedbackDataset` fields are {[field.name for field in self.dataset.fields]}." - ) - - self.events_data: Dict[str, List[CBEvent]] = defaultdict(list) - self.event_map_id_to_name = {} - self._ignore_components_in_tree = ["templating"] - self.components_to_log = set() - self.event_ids_traced = set() - - def _add_context_fields(self, number_of_retrievals: int) -> List: - """Create the context fields to be added to the dataset.""" - context_fields = [ - rg.TextField( - name="retrieved_document_" + str(doc + 1), - title="Retrieved Document " + str(doc + 1), - use_markdown=True, - required=False, - ) - for doc in range(number_of_retrievals) - ] - return context_fields - - def _add_context_questions(self, number_of_retrievals: int) -> List: - """Create the context questions to be added to the dataset.""" - rating_questions = [ - rg.RatingQuestion( - name="rating_retrieved_document_" + str(doc + 1), - title="Rate the relevance of the Retrieved Document " - + str(doc + 1) - + " (if present)", - values=list(range(1, 8)), - # After https://github.com/argilla-io/argilla/issues/4523 is fixed, we can use the description - description=None, # "Rate the relevance of the retrieved document." - required=False, - ) - for doc in range(number_of_retrievals) - ] - return rating_questions - - def _create_root_and_other_nodes(self, trace_map: Dict[str, List[str]]) -> None: - """Create the root node and the other nodes in the tree.""" - self.root_node = self._get_event_name_by_id(trace_map["root"][0]) - self.event_ids_traced = set(trace_map.keys()) - {"root"} - print(trace_map) - self.event_ids_traced.update(*trace_map.values()) - for id in self.event_ids_traced: - self.components_to_log.add(self._get_event_name_by_id(id)) - - def _get_event_name_by_id(self, event_id: str) -> str: - """Get the name of the event by its id.""" - return str(self.events_data[event_id][0].event_type).split(".")[1].lower() - - # TODO: If we have a component more than once, properties currently don't account for those after the first one and get overwritten - - def _add_missing_metadata_properties( - self, - dataset: rg.FeedbackDataset, - ) -> None: - """Add missing metadata properties to the dataset.""" - required_metadata_properties = [] - for property in self.components_to_log: - metadata_name = f"{property}_time" - if property == self.root_node: - metadata_name = "total_time" - required_metadata_properties.append(metadata_name) - - existing_metadata_properties = [ - property.name for property in dataset.metadata_properties - ] - missing_metadata_properties = [ - property - for property in required_metadata_properties - if property not in existing_metadata_properties - ] - - for property in missing_metadata_properties: - title = " ".join([word.capitalize() for word in property.split("_")]) - if title == "Llm Time": - title = "LLM Time" - dataset.add_metadata_property( - rg.FloatMetadataProperty(name=property, title=title) - ) - if self.is_new_dataset_created == False: - warnings.warn( - ( - f"The dataset given was missing some required metadata properties. " - f"Missing properties were {missing_metadata_properties}. " - f"Properties have been added to the dataset with " - ), - ) - - def _check_components_for_tree( - self, tree_structure_dict: Dict[str, List[str]] - ) -> Dict[str, List[str]]: - """ - Check whether the components in the tree are in the components to log. - Removes components that are not in the components to log so that they are not shown in the tree. - """ - final_components_in_tree = self.components_to_log.copy() - final_components_in_tree.add("root") - for component in self._ignore_components_in_tree: - if component in final_components_in_tree: - final_components_in_tree.remove(component) - for key in list(tree_structure_dict.keys()): - if key.strip("0") not in final_components_in_tree: - del tree_structure_dict[key] - for key, value in tree_structure_dict.items(): - if isinstance(value, list): - tree_structure_dict[key] = [ - element - for element in value - if element.strip("0") in final_components_in_tree - ] - return tree_structure_dict - - def _get_events_map_with_names( - self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] - ) -> Dict[str, List[str]]: - """ - Returns a dictionary where trace_map is mapped with the event names instead of the event ids. - Also returns a set of the event ids that were traced. - """ - self.event_map_id_to_name = {} - for event_id in self.event_ids_traced: - event_name = str(events_data[event_id][0].event_type).split(".")[1].lower() - while event_name in self.event_map_id_to_name.values(): - event_name = event_name + "0" - self.event_map_id_to_name[event_id] = event_name - events_trace_map = { - self.event_map_id_to_name.get(k, k): [ - self.event_map_id_to_name.get(v, v) for v in values - ] - for k, values in trace_map.items() - } - - print("Events trace map with names:") - print(events_trace_map) - - return events_trace_map - - def _extract_and_log_info( - self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] - ) -> None: - """ - Main function that extracts the information from the events and logs it to Argilla. - We currently log data if the root node is either "agent_step" or "query". - Otherwise, we do not log anything. - If we want to account for more root nodes, we just need to add them to the if statement. - """ - print(f"Events data:") - for key, value in events_data.items(): - print(f"{key}: {value}") - print(f"Trace map {trace_map}") - events_trace_map = self._get_events_map_with_names(events_data, trace_map) - root_node = trace_map["root"] - data_to_log = {} - - - if len(root_node) == 1: - - # Create logging data for the root node - if self.root_node == "agent_step": - # Event start - event = events_data[root_node[0]][0] - data_to_log["query"] = event.payload.get(EventPayload.MESSAGES)[0] - query_start_time = event.time - # Event end - event = events_data[root_node[0]][1] - data_to_log["response"] = event.payload.get( - EventPayload.RESPONSE - ).response - query_end_time = event.time - data_to_log["agent_step_time"] = _get_time_diff( - query_start_time, query_end_time - ) - - elif self.root_node == "query": - # Event start - event = events_data[root_node[0]][0] - data_to_log["query"] = event.payload.get(EventPayload.QUERY_STR) - query_start_time = event.time - # Event end - event = events_data[root_node[0]][1] - data_to_log["response"] = event.payload.get( - EventPayload.RESPONSE - ).response - query_end_time = event.time - data_to_log["query_time"] = _get_time_diff( - query_start_time, query_end_time - ) - - else: - return - - # Create logging data for the rest of the components - self.event_ids_traced.remove(root_node[0]) - number_of_components_used = defaultdict(int) - components_to_log_without_root_node = self.components_to_log.copy() - components_to_log_without_root_node.remove(self.root_node) - retrieval_metadata = {} - for id in self.event_ids_traced: - event_name = self.event_map_id_to_name[id] - if event_name.endswith("0"): - event_name_reduced = event_name.strip("0") - number_of_components_used[event_name_reduced] += 1 - else: - event_name_reduced = event_name - - for component in components_to_log_without_root_node: - if event_name_reduced == component: - data_to_log[f"{event_name}_time"] = _calc_time(events_data, id) - - if event_name_reduced == "llm": - data_to_log[f"{event_name}_system_prompt"] = ( - events_data[id][0].payload.get(EventPayload.MESSAGES)[0].content - ) - data_to_log[f"{event_name}_model_name"] = events_data[id][ - 0 - ].payload.get(EventPayload.SERIALIZED)["model"] - - retrieved_document_counter = 1 - if event_name_reduced == "retrieve": - for retrieval_node in events_data[id][1].payload.get( - EventPayload.NODES - ): - retrieve_dict = retrieval_node.to_dict() - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_score" - ] = retrieval_node.score - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_filename" - ] = retrieve_dict["node"]["metadata"]["file_name"] - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_text" - ] = retrieve_dict["node"]["text"] - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_start_character" - ] = retrieve_dict["node"]["start_char_idx"] - retrieval_metadata[ - f"{event_name}_document_{retrieved_document_counter}_end_character" - ] = retrieve_dict["node"]["end_char_idx"] - retrieved_document_counter += 1 - if retrieved_document_counter > self.number_of_retrievals: - break - - metadata_to_log = {} - - for keys in data_to_log.keys(): - if keys == "query_time" or keys == "agent_step_time": - metadata_to_log["total_time"] = data_to_log[keys] - elif keys.endswith("_time"): - metadata_to_log[keys] = data_to_log[keys] - elif keys != "query" and keys != "response": - metadata_to_log[keys] = data_to_log[keys] - - if len(number_of_components_used) > 0: - for key, value in number_of_components_used.items(): - metadata_to_log[f"number_of_{key}_used"] = value + 1 - - metadata_to_log.update(retrieval_metadata) - - tree_structure = self._create_tree_structure(events_trace_map, data_to_log) - tree = self._create_svg(tree_structure) - - fields = { - "prompt": data_to_log["query"], - "response": data_to_log["response"], - "time-details": tree, - } - - if self.number_of_retrievals > 0: - for key, value in list(retrieval_metadata.items()): - if key.endswith("_text"): - fields[f"retrieved_document_{key[-6]}"] = ( - f"DOCUMENT SCORE: {retrieval_metadata[key[:-5]+'_score']}\n\n" - + value - ) - del metadata_to_log[key] - - self.dataset.add_records( - records=[ - {"fields": fields, "metadata": metadata_to_log}, - ] - ) - - def _create_tree_structure( - self, events_trace_map: Dict[str, List[str]], data_to_log: Dict[str, Any] - ) -> List: - """Create the tree data to be converted to an SVG.""" - events_trace_map = self._check_components_for_tree(events_trace_map) - data = [] - data.append( - ( - 0, - 0, - self.root_node.strip("0").upper(), - data_to_log[f"{self.root_node}_time"], - ) - ) - current_row = 1 - for root_child in events_trace_map[self.root_node]: - data.append( - ( - current_row, - 1, - root_child.strip("0").upper(), - data_to_log[f"{root_child}_time"], - ) - ) - current_row += 1 - for child in events_trace_map[root_child]: - data.append( - ( - current_row, - 2, - child.strip("0").upper(), - data_to_log[f"{child}_time"], - ) - ) - current_row += 1 - return data - - def _create_svg(self, data: List) -> str: - # changing only the box height changes all other values as well - # others can be adjusted individually if needed - box_height = 47 - box_width = box_height * 8.65 - row_constant = box_height + 7 - indent_constant = 40 - font_size_node_name = box_height * 0.4188 - font_size_time = font_size_node_name - 4 - text_centering = box_height * 0.6341 - node_name_indent = box_height * 0.35 - time_indent = box_height * 7.15 - - body = "" - for each in data: - row, indent, node_name, node_time = each - body_raw = f""" - - -{node_name} -{node_time} - - """ - body += body_raw - base = ( - base - ) = f""" - - -{body} - - """ - base = base.strip() - return base - - def start_trace(self, trace_id: Optional[str] = None) -> None: - """Launch a trace.""" - self._trace_map = defaultdict(list) - self._cur_trace_id = trace_id - self._start_time = datetime.now() - - # Clearing the events and the components prior to running the query. They are usually events related to creating - # the docs and the index. - self.events_data.clear() - self.components_to_log.clear() - - def end_trace( - self, - trace_id: Optional[str] = None, - trace_map: Optional[Dict[str, List[str]]] = None, - ) -> None: - """End a trace.""" - self._trace_map = trace_map or defaultdict(list) - self._end_time = datetime.now() - self._create_root_and_other_nodes(trace_map) - self._add_missing_metadata_properties(self.dataset) - self._extract_and_log_info(self.events_data, trace_map) - - def on_event_start( - self, - event_type: CBEventType, - payload: Optional[Dict[str, Any]] = None, - event_id: Optional[str] = None, - parent_id: Optional[str] = None, - **kwargs: Any, - ) -> None: - """Run handlers when an event starts.""" - event = CBEvent(event_type, payload=payload, id_=event_id) - self.events_data[event_id].append(event) - - def on_event_end( - self, - event_type: CBEventType, - payload: Optional[Dict[str, Any]] = None, - event_id: Optional[str] = None, - **kwargs: Any, - ) -> None: - """Run handlers when an event ends.""" - event = CBEvent(event_type, payload=payload, id_=event_id) - self.events_data[event_id].append(event) - - -def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: - """Get the time difference between two events.""" - time_format = "%m/%d/%Y, %H:%M:%S.%f" - - event_1_time = datetime.strptime(event_1_time_str, time_format) - event_2_time = datetime.strptime(event_2_time_str, time_format) - - return round((event_2_time - event_1_time).total_seconds(), 4) - - -def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: - """Calculate the time difference between the start and end of an event using the events_data.""" - start_time = events_data[id][0].time - end_time = events_data[id][1].time - return _get_time_diff(start_time, end_time) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index 5724d14..2078c48 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional import warnings +import argilla as rg from argilla._constants import DEFAULT_API_KEY, DEFAULT_API_URL from llama_index.core.callbacks.base_handler import BaseCallbackHandler from llama_index.core.callbacks.schema import ( @@ -130,6 +131,17 @@ def __init__( ) self.dataset = dataset.push_to_argilla(self.dataset_name) + self.is_new_dataset_created = True + warnings.warn( + ( + f"No dataset with the name {self.dataset_name} was found in workspace " + f"{self.workspace_name}. A new dataset with the name {self.dataset_name} " + "has been created with the question fields `prompt` and `response`" + "and the rating question `response-rating` with values 1-7 and text question" + " named `response-feedback`." + ), + ) + else: # Update the existing dataset. If the fields and questions do not match, the dataset will be updated using the # -updated flag in the name. @@ -138,6 +150,7 @@ def __init__( name=self.dataset_name, workspace=self.workspace_name, ) + self.is_new_dataset_created = False if number_of_retrievals > 0: @@ -199,7 +212,7 @@ def __init__( except Exception as e: raise FileNotFoundError( f"`FeedbackDataset` retrieval and creation both failed with exception `{e}`." - f" If the problem persists please report it to {self.ISSUES_URL} " + f" If the problem persists please report it to https://github.com/argilla-io/argilla/issues/ " f"as an `integration` issue." ) from e @@ -225,7 +238,362 @@ def __init__( self.components_to_log = set() self.event_ids_traced = set() - + def _add_context_fields(self, number_of_retrievals: int) -> List: + """Create the context fields to be added to the dataset.""" + context_fields = [ + rg.TextField( + name="retrieved_document_" + str(doc + 1), + title="Retrieved Document " + str(doc + 1), + use_markdown=True, + required=False, + ) + for doc in range(number_of_retrievals) + ] + return context_fields + + def _add_context_questions(self, number_of_retrievals: int) -> List: + """Create the context questions to be added to the dataset.""" + rating_questions = [ + rg.RatingQuestion( + name="rating_retrieved_document_" + str(doc + 1), + title="Rate the relevance of the Retrieved Document " + + str(doc + 1) + + " (if present)", + values=list(range(1, 8)), + # After https://github.com/argilla-io/argilla/issues/4523 is fixed, we can use the description + description=None, # "Rate the relevance of the retrieved document." + required=False, + ) + for doc in range(number_of_retrievals) + ] + return rating_questions + + def _create_root_and_other_nodes(self, trace_map: Dict[str, List[str]]) -> None: + """Create the root node and the other nodes in the tree.""" + self.root_node = self._get_event_name_by_id(trace_map["root"][0]) + self.event_ids_traced = set(trace_map.keys()) - {"root"} + print(trace_map) + self.event_ids_traced.update(*trace_map.values()) + for id in self.event_ids_traced: + self.components_to_log.add(self._get_event_name_by_id(id)) + + def _get_event_name_by_id(self, event_id: str) -> str: + """Get the name of the event by its id.""" + return str(self.events_data[event_id][0].event_type).split(".")[1].lower() + + # TODO: If we have a component more than once, properties currently don't account for those after the first one and get overwritten + + def _add_missing_metadata_properties( + self, + dataset: rg.FeedbackDataset, + ) -> None: + """Add missing metadata properties to the dataset.""" + required_metadata_properties = [] + for property in self.components_to_log: + metadata_name = f"{property}_time" + if property == self.root_node: + metadata_name = "total_time" + required_metadata_properties.append(metadata_name) + + existing_metadata_properties = [ + property.name for property in dataset.metadata_properties + ] + missing_metadata_properties = [ + property + for property in required_metadata_properties + if property not in existing_metadata_properties + ] + + for property in missing_metadata_properties: + title = " ".join([word.capitalize() for word in property.split("_")]) + if title == "Llm Time": + title = "LLM Time" + dataset.add_metadata_property( + rg.FloatMetadataProperty(name=property, title=title) + ) + if self.is_new_dataset_created == False: + warnings.warn( + ( + f"The dataset given was missing some required metadata properties. " + f"Missing properties were {missing_metadata_properties}. " + f"Properties have been added to the dataset with " + ), + ) + + def _check_components_for_tree( + self, tree_structure_dict: Dict[str, List[str]] + ) -> Dict[str, List[str]]: + """ + Check whether the components in the tree are in the components to log. + Removes components that are not in the components to log so that they are not shown in the tree. + """ + final_components_in_tree = self.components_to_log.copy() + final_components_in_tree.add("root") + for component in self._ignore_components_in_tree: + if component in final_components_in_tree: + final_components_in_tree.remove(component) + for key in list(tree_structure_dict.keys()): + if key.strip("0") not in final_components_in_tree: + del tree_structure_dict[key] + for key, value in tree_structure_dict.items(): + if isinstance(value, list): + tree_structure_dict[key] = [ + element + for element in value + if element.strip("0") in final_components_in_tree + ] + return tree_structure_dict + + def _get_events_map_with_names( + self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] + ) -> Dict[str, List[str]]: + """ + Returns a dictionary where trace_map is mapped with the event names instead of the event ids. + Also returns a set of the event ids that were traced. + """ + self.event_map_id_to_name = {} + for event_id in self.event_ids_traced: + event_name = str(events_data[event_id][0].event_type).split(".")[1].lower() + while event_name in self.event_map_id_to_name.values(): + event_name = event_name + "0" + self.event_map_id_to_name[event_id] = event_name + events_trace_map = { + self.event_map_id_to_name.get(k, k): [ + self.event_map_id_to_name.get(v, v) for v in values + ] + for k, values in trace_map.items() + } + + print("Events trace map with names:") + print(events_trace_map) + + return events_trace_map + + def _extract_and_log_info( + self, events_data: Dict[str, List[CBEvent]], trace_map: Dict[str, List[str]] + ) -> None: + """ + Main function that extracts the information from the events and logs it to Argilla. + We currently log data if the root node is either "agent_step" or "query". + Otherwise, we do not log anything. + If we want to account for more root nodes, we just need to add them to the if statement. + """ + print(f"Events data:") + for key, value in events_data.items(): + print(f"{key}: {value}") + print(f"Trace map {trace_map}") + events_trace_map = self._get_events_map_with_names(events_data, trace_map) + root_node = trace_map["root"] + data_to_log = {} + + if len(root_node) == 1: + + # Create logging data for the root node + if self.root_node == "agent_step": + # Event start + event = events_data[root_node[0]][0] + data_to_log["query"] = event.payload.get(EventPayload.MESSAGES)[0] + query_start_time = event.time + # Event end + event = events_data[root_node[0]][1] + data_to_log["response"] = event.payload.get( + EventPayload.RESPONSE + ).response + query_end_time = event.time + data_to_log["agent_step_time"] = _get_time_diff( + query_start_time, query_end_time + ) + + elif self.root_node == "query": + # Event start + event = events_data[root_node[0]][0] + data_to_log["query"] = event.payload.get(EventPayload.QUERY_STR) + query_start_time = event.time + # Event end + event = events_data[root_node[0]][1] + data_to_log["response"] = event.payload.get( + EventPayload.RESPONSE + ).response + query_end_time = event.time + data_to_log["query_time"] = _get_time_diff( + query_start_time, query_end_time + ) + + else: + return + + # Create logging data for the rest of the components + self.event_ids_traced.remove(root_node[0]) + number_of_components_used = defaultdict(int) + components_to_log_without_root_node = self.components_to_log.copy() + components_to_log_without_root_node.remove(self.root_node) + retrieval_metadata = {} + for id in self.event_ids_traced: + event_name = self.event_map_id_to_name[id] + if event_name.endswith("0"): + event_name_reduced = event_name.strip("0") + number_of_components_used[event_name_reduced] += 1 + else: + event_name_reduced = event_name + + for component in components_to_log_without_root_node: + if event_name_reduced == component: + data_to_log[f"{event_name}_time"] = _calc_time(events_data, id) + + if event_name_reduced == "llm": + data_to_log[f"{event_name}_system_prompt"] = ( + events_data[id][0].payload.get(EventPayload.MESSAGES)[0].content + ) + data_to_log[f"{event_name}_model_name"] = events_data[id][ + 0 + ].payload.get(EventPayload.SERIALIZED)["model"] + + retrieved_document_counter = 1 + if event_name_reduced == "retrieve": + for retrieval_node in events_data[id][1].payload.get( + EventPayload.NODES + ): + retrieve_dict = retrieval_node.to_dict() + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_score" + ] = retrieval_node.score + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_filename" + ] = retrieve_dict["node"]["metadata"]["file_name"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_text" + ] = retrieve_dict["node"]["text"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_start_character" + ] = retrieve_dict["node"]["start_char_idx"] + retrieval_metadata[ + f"{event_name}_document_{retrieved_document_counter}_end_character" + ] = retrieve_dict["node"]["end_char_idx"] + retrieved_document_counter += 1 + if retrieved_document_counter > self.number_of_retrievals: + break + + metadata_to_log = {} + + for keys in data_to_log.keys(): + if keys == "query_time" or keys == "agent_step_time": + metadata_to_log["total_time"] = data_to_log[keys] + elif keys.endswith("_time"): + metadata_to_log[keys] = data_to_log[keys] + elif keys != "query" and keys != "response": + metadata_to_log[keys] = data_to_log[keys] + + if len(number_of_components_used) > 0: + for key, value in number_of_components_used.items(): + metadata_to_log[f"number_of_{key}_used"] = value + 1 + + metadata_to_log.update(retrieval_metadata) + + tree_structure = self._create_tree_structure(events_trace_map, data_to_log) + tree = self._create_svg(tree_structure) + + fields = { + "prompt": data_to_log["query"], + "response": data_to_log["response"], + "time-details": tree, + } + + if self.number_of_retrievals > 0: + for key, value in list(retrieval_metadata.items()): + if key.endswith("_text"): + fields[f"retrieved_document_{key[-6]}"] = ( + f"DOCUMENT SCORE: {retrieval_metadata[key[:-5]+'_score']}\n\n" + + value + ) + del metadata_to_log[key] + + self.dataset.add_records( + records=[ + {"fields": fields, "metadata": metadata_to_log}, + ] + ) + + def _create_tree_structure( + self, events_trace_map: Dict[str, List[str]], data_to_log: Dict[str, Any] + ) -> List: + """Create the tree data to be converted to an SVG.""" + events_trace_map = self._check_components_for_tree(events_trace_map) + data = [] + data.append( + ( + 0, + 0, + self.root_node.strip("0").upper(), + data_to_log[f"{self.root_node}_time"], + ) + ) + current_row = 1 + for root_child in events_trace_map[self.root_node]: + data.append( + ( + current_row, + 1, + root_child.strip("0").upper(), + data_to_log[f"{root_child}_time"], + ) + ) + current_row += 1 + for child in events_trace_map[root_child]: + data.append( + ( + current_row, + 2, + child.strip("0").upper(), + data_to_log[f"{child}_time"], + ) + ) + current_row += 1 + return data + + def _create_svg(self, data: List) -> str: + """ + Create an SVG file from the data. + + Args: + data (List): The data to create the SVG file from. + + Returns: + str: The SVG file. + """ + + # changing only the box height changes all other values as well + # others can be adjusted individually if needed + box_height = 47 + box_width = box_height * 8.65 + row_constant = box_height + 7 + indent_constant = 40 + font_size_node_name = box_height * 0.4188 + font_size_time = font_size_node_name - 4 + text_centering = box_height * 0.6341 + node_name_indent = box_height * 0.35 + time_indent = box_height * 7.15 + + body = "" + for each in data: + row, indent, node_name, node_time = each + body_raw = f""" + + +{node_name} +{node_time} + + """ + body += body_raw + base = ( + base + ) = f""" + + +{body} + + """ + base = base.strip() + return base # The four methods required by the abstrac class BaseCallbackHandler. # These methods are the one being executed on the different events, by the llama-index @@ -263,18 +631,9 @@ def end_trace( self._trace_map = trace_map or defaultdict(list) self._end_time = datetime.now() - print("Events data on end_trace()") - for key, value in self.events_data.items(): - print(key, value) - print("Trace map on end_trace()") - print(self._trace_map) - print() - - # The trace_map is a dictionary with the event_id as the key and the list of components as the value. However, - # it only register those events which payload is of type EventPayload.QUERY_STR. We must manually introduce - # the events that are not of this type, but are relevant to the prediction process. - # for node_id in self._trace_map: - # for event_id, event_id_object in self.events_data.items(): + self._create_root_and_other_nodes(trace_map) + self._add_missing_metadata_properties(self.dataset) + self._extract_and_log_info(self.events_data, trace_map) def on_event_start( self, @@ -318,40 +677,40 @@ def on_event_end( event = CBEvent(event_type, payload=payload, id_=event_id) self.events_data[event_id].append(event) - self._trace_map = defaultdict(list) - # Auxiliary methods - def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: - """ - Get the time difference between two events Follows the American format (month, day, year). +# Auxiliary methods +def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: + """ + Get the time difference between two events Follows the American format (month, day, year). - Args: - event_1_time_str (str): The first event time. - event_2_time_str (str): The second event time. + Args: + event_1_time_str (str): The first event time. + event_2_time_str (str): The second event time. - Returns: - float: The time difference between the two events. - """ - time_format = "%m/%d/%Y, %H:%M:%S.%f" + Returns: + float: The time difference between the two events. + """ + time_format = "%m/%d/%Y, %H:%M:%S.%f" - event_1_time = datetime.strptime(event_1_time_str, time_format) - event_2_time = datetime.strptime(event_2_time_str, time_format) + event_1_time = datetime.strptime(event_1_time_str, time_format) + event_2_time = datetime.strptime(event_2_time_str, time_format) - return round((event_2_time - event_1_time).total_seconds(), 4) + return round((event_2_time - event_1_time).total_seconds(), 4) - def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: - """ - Calculate the time difference between the start and end of an event using the events_data. - Args: - events_data (Dict[str, List[CBEvent]]): The events data, stored in a dictionary. - id (str): The event id to calculate the time difference between start and finish timestamps. +def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: + """ + Calculate the time difference between the start and end of an event using the events_data. - Returns: - float: The time difference between the start and end of the event. - """ + Args: + events_data (Dict[str, List[CBEvent]]): The events data, stored in a dictionary. + id (str): The event id to calculate the time difference between start and finish timestamps. + + Returns: + float: The time difference between the start and end of the event. + """ - start_time = events_data[id][0].time - end_time = events_data[id][1].time - return _get_time_diff(start_time, end_time) + start_time = events_data[id][0].time + end_time = events_data[id][1].time + return _get_time_diff(start_time, end_time) From 498034c9b6d05ac6da08d27a613e5c72592a3646 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 10:42:46 +0200 Subject: [PATCH 10/24] argilla pinned to 1.22.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 893ea52..0868e53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", ] dependencies = [ - "argilla >= 1.18.0", + "argilla >= 1.22.0", "llama-index >= 0.10.0", "packaging >= 23.2", "typing-extensions >= 4.3.0" From 8edf9afcde0d4bbf5951ebaad84928859a61d453 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 11:29:35 +0200 Subject: [PATCH 11/24] tests adapted --- .../llama_index_handler.py | 10 +-- tests/test_llama_index_callback.py | 87 +++++++++++++------ 2 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index 2078c48..93edc10 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -91,7 +91,7 @@ def __init__( f"Could not connect to Argilla with exception: '{e}'.\n" "Please check your `api_key` and `api_url`, and make sure that " "the Argilla server is up and running. If the problem persists " - f"please report it to {self.ISSUES_URL} as an `integration` issue." + f"please report it to https://github.com/argilla-io/argilla/issues/ as an `integration` issue." ) from e # Set the Argilla variables @@ -272,7 +272,6 @@ def _create_root_and_other_nodes(self, trace_map: Dict[str, List[str]]) -> None: """Create the root node and the other nodes in the tree.""" self.root_node = self._get_event_name_by_id(trace_map["root"][0]) self.event_ids_traced = set(trace_map.keys()) - {"root"} - print(trace_map) self.event_ids_traced.update(*trace_map.values()) for id in self.event_ids_traced: self.components_to_log.add(self._get_event_name_by_id(id)) @@ -364,9 +363,6 @@ def _get_events_map_with_names( for k, values in trace_map.items() } - print("Events trace map with names:") - print(events_trace_map) - return events_trace_map def _extract_and_log_info( @@ -378,10 +374,6 @@ def _extract_and_log_info( Otherwise, we do not log anything. If we want to account for more root nodes, we just need to add them to the if statement. """ - print(f"Events data:") - for key, value in events_data.items(): - print(f"{key}: {value}") - print(f"Trace map {trace_map}") events_trace_map = self._get_events_map_with_names(events_data, trace_map) root_node = trace_map["root"] data_to_log = {} diff --git a/tests/test_llama_index_callback.py b/tests/test_llama_index_callback.py index 998c05a..1788c14 100644 --- a/tests/test_llama_index_callback.py +++ b/tests/test_llama_index_callback.py @@ -1,13 +1,55 @@ +from datetime import datetime +from typing import Dict, List + import unittest from unittest.mock import patch, MagicMock -from argilla_llama_index import ArgillaCallbackHandler, _get_time_diff, _calc_time # TODO: correct import +from argilla_llama_index import ArgillaCallbackHandler +from llama_index.core.callbacks.schema import CBEvent + + +# Auxiliary methods +def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: + """ + Get the time difference between two events Follows the American format (month, day, year). + + Args: + event_1_time_str (str): The first event time. + event_2_time_str (str): The second event time. + + Returns: + float: The time difference between the two events. + """ + time_format = "%m/%d/%Y, %H:%M:%S.%f" + + event_1_time = datetime.strptime(event_1_time_str, time_format) + event_2_time = datetime.strptime(event_2_time_str, time_format) + + return round((event_2_time - event_1_time).total_seconds(), 4) + + +def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: + """ + Calculate the time difference between the start and end of an event using the events_data. + + Args: + events_data (Dict[str, List[CBEvent]]): The events data, stored in a dictionary. + id (str): The event id to calculate the time difference between start and finish timestamps. + + Returns: + float: The time difference between the start and end of the event. + """ + + start_time = events_data[id][0].time + end_time = events_data[id][1].time + return _get_time_diff(start_time, end_time) + class TestArgillaCallbackHandler(unittest.TestCase): def setUp(self): self.dataset_name = "test_dataset_llama_index" - self.workspace_name = "argilla" + self.workspace_name = "admin" self.api_url = "http://localhost:6900" - self.api_key = "argilla.apikey" + self.api_key = "admin.apikey" self.handler = ArgillaCallbackHandler( dataset_name=self.dataset_name, @@ -21,7 +63,7 @@ def setUp(self): self.components_to_log = MagicMock() self._ignore_components_in_tree = MagicMock() self.trace_map = MagicMock() - + self.tree_structure_dict = { "root": ["query"], "query": ["retrieve", "synthesize"], @@ -56,33 +98,23 @@ def test_init_file_not_found_error(self, mock_from_argilla, mock_list): api_key=self.api_key, ) - def test_add_missing_metadata_properties(self): - dataset = self.handler.dataset - is_new_dataset_created = True - self.handler._add_missing_metadata_properties(dataset, is_new_dataset_created) - self.assertEqual(len(dataset.metadata_properties), 6) - def test_check_components_for_tree(self): self.handler._check_components_for_tree(self.tree_structure_dict) - def test_create_tree(self): - - tree = self.handler._create_tree(self.tree_structure_dict, self.data_to_log) - self.assertIsInstance(tree, str) - def test_get_events_map_with_names(self): - trace_map = { - "query": ["retrieve"], - "llm": [] - } - events_map = self.handler._get_events_map_with_names(self.events_data, trace_map) - self.assertIsInstance(events_map, tuple) + trace_map = {"query": ["retrieve"], "llm": []} + events_map = self.handler._get_events_map_with_names( + self.events_data, trace_map + ) + self.assertIsInstance(events_map, dict) self.assertEqual(len(events_map), 2) def test_extract_and_log_info(self): - tree_structure_dict = self.handler._check_components_for_tree(self.tree_structure_dict) + tree_structure_dict = self.handler._check_components_for_tree( + self.tree_structure_dict + ) self.handler._extract_and_log_info(self.events_data, tree_structure_dict) def test_start_trace(self): @@ -97,7 +129,6 @@ def test_on_event_start(self): parent_id = "456" self.handler.on_event_start(event_type, payload, event_id, parent_id) - def test_on_event_end(self): event_type = "event1" payload = {} @@ -113,11 +144,15 @@ def test_get_time_diff(self): def test_calc_time(self): id = "event1" - self.events_data.__getitem__().__getitem__().time = "01/11/2024, 17:01:04.328656" - self.events_data.__getitem__().__getitem__().time = "01/11/2024, 17:02:07.328523" + self.events_data.__getitem__().__getitem__().time = ( + "01/11/2024, 17:01:04.328656" + ) + self.events_data.__getitem__().__getitem__().time = ( + "01/11/2024, 17:02:07.328523" + ) time = _calc_time(self.events_data, id) self.assertIsInstance(time, float) + if __name__ == "__main__": unittest.main() - From 149302fcf335a3cc0985069c2ac8585ec976a447 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 12:20:18 +0200 Subject: [PATCH 12/24] upload release workflow --- .github/workflows/release.yml | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b1b7dd0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,39 @@ +name: Release + +on: + release: + types: + - published + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + # Looks like it's not working very well for other people: + # https://github.com/actions/setup-python/issues/436 + # cache: "pip" + # cache-dependency-path: pyproject.toml + + - uses: actions/cache@v3 + id: cache + with: + path: ${{ env.pythonLocation }} + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-release-v00 + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: pip install build + + - name: Build distribution + run: python -m build + + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file From e881874c899530e9ef172d36abb100cbbf74df9e Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 12:21:52 +0200 Subject: [PATCH 13/24] remove unused import --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 0fd5dff..ae85c07 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ openai_api_key = os.getenv("OPENAI_API_KEY", None) or getpass("Enter OpenAI API Let's now write all the necessary imports ```python -from argilla_llama_index import ArgillaCallbackHandler from llama_index.core import VectorStoreIndex, ServiceContext, SimpleDirectoryReader, set_global_handler from llama_index.llms.openai import OpenAI ``` From 837f7703acbc6b4aba1df7c48457295208491591 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 16:27:43 +0200 Subject: [PATCH 14/24] uploading txt file into the data folder --- data/paul_graham_essay.txt | 353 ++++++++++++++++++++++++++++++ docs/examples/usage_example.ipynb | 190 +++++++++++++++- 2 files changed, 531 insertions(+), 12 deletions(-) create mode 100644 data/paul_graham_essay.txt diff --git a/data/paul_graham_essay.txt b/data/paul_graham_essay.txt new file mode 100644 index 0000000..7f0350d --- /dev/null +++ b/data/paul_graham_essay.txt @@ -0,0 +1,353 @@ + + +What I Worked On + +February 2021 + +Before college the two main things I worked on, outside of school, were writing and programming. I didn't write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep. + +The first programs I tried writing were on the IBM 1401 that our school district used for what was then called "data processing." This was in 9th grade, so I was 13 or 14. The school district's 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain's lair down there, with all these alien-looking machines โ€” CPU, disk drives, printer, card reader โ€” sitting up on a raised floor under bright fluorescent lights. + +The language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer. + +I was puzzled by the 1401. I couldn't figure out what to do with it. And in retrospect there's not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn't have any data stored on punched cards. The only other option was to do things that didn't rely on any input, like calculate approximations of pi, but I didn't know enough math to do anything interesting of that type. So I'm not surprised I can't remember any programs I wrote, because they can't have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn't. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager's expression made clear. + +With microcomputers, everything changed. Now you could have a computer sitting right in front of you, on a desk, that could respond to your keystrokes as it was running instead of just churning through a stack of punch cards and then stopping. [1] + +The first of my friends to get a microcomputer built it himself. It was sold as a kit by Heathkit. I remember vividly how impressed and envious I felt watching him sitting in front of it, typing programs right into the computer. + +Computers were expensive in those days and it took me years of nagging before I convinced my father to buy one, a TRS-80, in about 1980. The gold standard then was the Apple II, but a TRS-80 was good enough. This was when I really started programming. I wrote simple games, a program to predict how high my model rockets would fly, and a word processor that my father used to write at least one book. There was only room in memory for about 2 pages of text, so he'd write 2 pages at a time and then print them out, but it was a lot better than a typewriter. + +Though I liked programming, I didn't plan to study it in college. In college I was going to study philosophy, which sounded much more powerful. It seemed, to my naive high school self, to be the study of the ultimate truths, compared to which the things studied in other fields would be mere domain knowledge. What I discovered when I got to college was that the other fields took up so much of the space of ideas that there wasn't much left for these supposed ultimate truths. All that seemed left for philosophy were edge cases that people in other fields felt could safely be ignored. + +I couldn't have put this into words when I was 18. All I knew at the time was that I kept taking philosophy courses and they kept being boring. So I decided to switch to AI. + +AI was in the air in the mid 1980s, but there were two things especially that made me want to work on it: a novel by Heinlein called The Moon is a Harsh Mistress, which featured an intelligent computer called Mike, and a PBS documentary that showed Terry Winograd using SHRDLU. I haven't tried rereading The Moon is a Harsh Mistress, so I don't know how well it has aged, but when I read it I was drawn entirely into its world. It seemed only a matter of time before we'd have Mike, and when I saw Winograd using SHRDLU, it seemed like that time would be a few years at most. All you had to do was teach SHRDLU more words. + +There weren't any classes in AI at Cornell then, not even graduate classes, so I started trying to teach myself. Which meant learning Lisp, since in those days Lisp was regarded as the language of AI. The commonly used programming languages then were pretty primitive, and programmers' ideas correspondingly so. The default language at Cornell was a Pascal-like language called PL/I, and the situation was similar elsewhere. Learning Lisp expanded my concept of a program so fast that it was years before I started to have a sense of where the new limits were. This was more like it; this was what I had expected college to do. It wasn't happening in a class, like it was supposed to, but that was ok. For the next couple years I was on a roll. I knew what I was going to do. + +For my undergraduate thesis, I reverse-engineered SHRDLU. My God did I love working on that program. It was a pleasing bit of code, but what made it even more exciting was my belief โ€” hard to imagine now, but not unique in 1985 โ€” that it was already climbing the lower slopes of intelligence. + +I had gotten into a program at Cornell that didn't make you choose a major. You could take whatever classes you liked, and choose whatever you liked to put on your degree. I of course chose "Artificial Intelligence." When I got the actual physical diploma, I was dismayed to find that the quotes had been included, which made them read as scare-quotes. At the time this bothered me, but now it seems amusingly accurate, for reasons I was about to discover. + +I applied to 3 grad schools: MIT and Yale, which were renowned for AI at the time, and Harvard, which I'd visited because Rich Draves went there, and was also home to Bill Woods, who'd invented the type of parser I used in my SHRDLU clone. Only Harvard accepted me, so that was where I went. + +I don't remember the moment it happened, or if there even was a specific moment, but during the first year of grad school I realized that AI, as practiced at the time, was a hoax. By which I mean the sort of AI in which a program that's told "the dog is sitting on the chair" translates this into some formal representation and adds it to the list of things it knows. + +What these programs really showed was that there's a subset of natural language that's a formal language. But a very proper subset. It was clear that there was an unbridgeable gap between what they could do and actually understanding natural language. It was not, in fact, simply a matter of teaching SHRDLU more words. That whole way of doing AI, with explicit data structures representing concepts, was not going to work. Its brokenness did, as so often happens, generate a lot of opportunities to write papers about various band-aids that could be applied to it, but it was never going to get us Mike. + +So I looked around to see what I could salvage from the wreckage of my plans, and there was Lisp. I knew from experience that Lisp was interesting for its own sake and not just for its association with AI, even though that was the main reason people cared about it at the time. So I decided to focus on Lisp. In fact, I decided to write a book about Lisp hacking. It's scary to think how little I knew about Lisp hacking when I started writing that book. But there's nothing like writing a book about something to help you learn it. The book, On Lisp, wasn't published till 1993, but I wrote much of it in grad school. + +Computer Science is an uneasy alliance between two halves, theory and systems. The theory people prove things, and the systems people build things. I wanted to build things. I had plenty of respect for theory โ€” indeed, a sneaking suspicion that it was the more admirable of the two halves โ€” but building things seemed so much more exciting. + +The problem with systems work, though, was that it didn't last. Any program you wrote today, no matter how good, would be obsolete in a couple decades at best. People might mention your software in footnotes, but no one would actually use it. And indeed, it would seem very feeble work. Only people with a sense of the history of the field would even realize that, in its time, it had been good. + +There were some surplus Xerox Dandelions floating around the computer lab at one point. Anyone who wanted one to play around with could have one. I was briefly tempted, but they were so slow by present standards; what was the point? No one else wanted one either, so off they went. That was what happened to systems work. + +I wanted not just to build things, but to build things that would last. + +In this dissatisfied state I went in 1988 to visit Rich Draves at CMU, where he was in grad school. One day I went to visit the Carnegie Institute, where I'd spent a lot of time as a kid. While looking at a painting there I realized something that might seem obvious, but was a big surprise to me. There, right on the wall, was something you could make that would last. Paintings didn't become obsolete. Some of the best ones were hundreds of years old. + +And moreover this was something you could make a living doing. Not as easily as you could by writing software, of course, but I thought if you were really industrious and lived really cheaply, it had to be possible to make enough to survive. And as an artist you could be truly independent. You wouldn't have a boss, or even need to get research funding. + +I had always liked looking at paintings. Could I make them? I had no idea. I'd never imagined it was even possible. I knew intellectually that people made art โ€” that it didn't just appear spontaneously โ€” but it was as if the people who made it were a different species. They either lived long ago or were mysterious geniuses doing strange things in profiles in Life magazine. The idea of actually being able to make art, to put that verb before that noun, seemed almost miraculous. + +That fall I started taking art classes at Harvard. Grad students could take classes in any department, and my advisor, Tom Cheatham, was very easy going. If he even knew about the strange classes I was taking, he never said anything. + +So now I was in a PhD program in computer science, yet planning to be an artist, yet also genuinely in love with Lisp hacking and working away at On Lisp. In other words, like many a grad student, I was working energetically on multiple projects that were not my thesis. + +I didn't see a way out of this situation. I didn't want to drop out of grad school, but how else was I going to get out? I remember when my friend Robert Morris got kicked out of Cornell for writing the internet worm of 1988, I was envious that he'd found such a spectacular way to get out of grad school. + +Then one day in April 1990 a crack appeared in the wall. I ran into professor Cheatham and he asked if I was far enough along to graduate that June. I didn't have a word of my dissertation written, but in what must have been the quickest bit of thinking in my life, I decided to take a shot at writing one in the 5 weeks or so that remained before the deadline, reusing parts of On Lisp where I could, and I was able to respond, with no perceptible delay "Yes, I think so. I'll give you something to read in a few days." + +I picked applications of continuations as the topic. In retrospect I should have written about macros and embedded languages. There's a whole world there that's barely been explored. But all I wanted was to get out of grad school, and my rapidly written dissertation sufficed, just barely. + +Meanwhile I was applying to art schools. I applied to two: RISD in the US, and the Accademia di Belli Arti in Florence, which, because it was the oldest art school, I imagined would be good. RISD accepted me, and I never heard back from the Accademia, so off to Providence I went. + +I'd applied for the BFA program at RISD, which meant in effect that I had to go to college again. This was not as strange as it sounds, because I was only 25, and art schools are full of people of different ages. RISD counted me as a transfer sophomore and said I had to do the foundation that summer. The foundation means the classes that everyone has to take in fundamental subjects like drawing, color, and design. + +Toward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they'd sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I'd done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian. + +Only stranieri (foreigners) had to take this entrance exam. In retrospect it may well have been a way of excluding them, because there were so many stranieri attracted by the idea of studying art in Florence that the Italian students would otherwise have been outnumbered. I was in decent shape at painting and drawing from the RISD foundation that summer, but I still don't know how I managed to pass the written exam. I remember that I answered the essay question by writing about Cezanne, and that I cranked up the intellectual level as high as I could to make the most of my limited vocabulary. [2] + +I'm only up to age 25 and already there are such conspicuous patterns. Here I was, yet again about to attend some august institution in the hopes of learning about some prestigious subject, and yet again about to be disappointed. The students and faculty in the painting department at the Accademia were the nicest people you could imagine, but they had long since arrived at an arrangement whereby the students wouldn't require the faculty to teach anything, and in return the faculty wouldn't require the students to learn anything. And at the same time all involved would adhere outwardly to the conventions of a 19th century atelier. We actually had one of those little stoves, fed with kindling, that you see in 19th century studio paintings, and a nude model sitting as close to it as possible without getting burned. Except hardly anyone else painted her besides me. The rest of the students spent their time chatting or occasionally trying to imitate things they'd seen in American art magazines. + +Our model turned out to live just down the street from me. She made a living from a combination of modelling and making fakes for a local antique dealer. She'd copy an obscure old painting out of a book, and then he'd take the copy and maltreat it to make it look old. [3] + +While I was a student at the Accademia I started painting still lives in my bedroom at night. These paintings were tiny, because the room was, and because I painted them on leftover scraps of canvas, which was all I could afford at the time. Painting still lives is different from painting people, because the subject, as its name suggests, can't move. People can't sit for more than about 15 minutes at a time, and when they do they don't sit very still. So the traditional m.o. for painting people is to know how to paint a generic person, which you then modify to match the specific person you're painting. Whereas a still life you can, if you want, copy pixel by pixel from what you're seeing. You don't want to stop there, of course, or you get merely photographic accuracy, and what makes a still life interesting is that it's been through a head. You want to emphasize the visual cues that tell you, for example, that the reason the color changes suddenly at a certain point is that it's the edge of an object. By subtly emphasizing such things you can make paintings that are more realistic than photographs not just in some metaphorical sense, but in the strict information-theoretic sense. [4] + +I liked painting still lives because I was curious about what I was seeing. In everyday life, we aren't consciously aware of much we're seeing. Most visual perception is handled by low-level processes that merely tell your brain "that's a water droplet" without telling you details like where the lightest and darkest points are, or "that's a bush" without telling you the shape and position of every leaf. This is a feature of brains, not a bug. In everyday life it would be distracting to notice every leaf on every bush. But when you have to paint something, you have to look more closely, and when you do there's a lot to see. You can still be noticing new things after days of trying to paint something people usually take for granted, just as you can after days of trying to write an essay about something people usually take for granted. + +This is not the only way to paint. I'm not 100% sure it's even a good way to paint. But it seemed a good enough bet to be worth trying. + +Our teacher, professor Ulivi, was a nice guy. He could see I worked hard, and gave me a good grade, which he wrote down in a sort of passport each student had. But the Accademia wasn't teaching me anything except Italian, and my money was running out, so at the end of the first year I went back to the US. + +I wanted to go back to RISD, but I was now broke and RISD was very expensive, so I decided to get a job for a year and then return to RISD the next fall. I got one at a company called Interleaf, which made software for creating documents. You mean like Microsoft Word? Exactly. That was how I learned that low end software tends to eat high end software. But Interleaf still had a few years to live yet. [5] + +Interleaf had done something pretty bold. Inspired by Emacs, they'd added a scripting language, and even made the scripting language a dialect of Lisp. Now they wanted a Lisp hacker to write things in it. This was the closest thing I've had to a normal job, and I hereby apologize to my boss and coworkers, because I was a bad employee. Their Lisp was the thinnest icing on a giant C cake, and since I didn't know C and didn't want to learn it, I never understood most of the software. Plus I was terribly irresponsible. This was back when a programming job meant showing up every day during certain working hours. That seemed unnatural to me, and on this point the rest of the world is coming around to my way of thinking, but at the time it caused a lot of friction. Toward the end of the year I spent much of my time surreptitiously working on On Lisp, which I had by this time gotten a contract to publish. + +The good part was that I got paid huge amounts of money, especially by art student standards. In Florence, after paying my part of the rent, my budget for everything else had been $7 a day. Now I was getting paid more than 4 times that every hour, even when I was just sitting in a meeting. By living cheaply I not only managed to save enough to go back to RISD, but also paid off my college loans. + +I learned some useful things at Interleaf, though they were mostly about what not to do. I learned that it's better for technology companies to be run by product people than sales people (though sales is a real skill and people who are good at it are really good at it), that it leads to bugs when code is edited by too many people, that cheap office space is no bargain if it's depressing, that planned meetings are inferior to corridor conversations, that big, bureaucratic customers are a dangerous source of money, and that there's not much overlap between conventional office hours and the optimal time for hacking, or conventional offices and the optimal place for it. + +But the most important thing I learned, and which I used in both Viaweb and Y Combinator, is that the low end eats the high end: that it's good to be the "entry level" option, even though that will be less prestigious, because if you're not, someone else will be, and will squash you against the ceiling. Which in turn means that prestige is a danger sign. + +When I left to go back to RISD the next fall, I arranged to do freelance work for the group that did projects for customers, and this was how I survived for the next several years. When I came back to visit for a project later on, someone told me about a new thing called HTML, which was, as he described it, a derivative of SGML. Markup language enthusiasts were an occupational hazard at Interleaf and I ignored him, but this HTML thing later became a big part of my life. + +In the fall of 1992 I moved back to Providence to continue at RISD. The foundation had merely been intro stuff, and the Accademia had been a (very civilized) joke. Now I was going to see what real art school was like. But alas it was more like the Accademia than not. Better organized, certainly, and a lot more expensive, but it was now becoming clear that art school did not bear the same relationship to art that medical school bore to medicine. At least not the painting department. The textile department, which my next door neighbor belonged to, seemed to be pretty rigorous. No doubt illustration and architecture were too. But painting was post-rigorous. Painting students were supposed to express themselves, which to the more worldly ones meant to try to cook up some sort of distinctive signature style. + +A signature style is the visual equivalent of what in show business is known as a "schtick": something that immediately identifies the work as yours and no one else's. For example, when you see a painting that looks like a certain kind of cartoon, you know it's by Roy Lichtenstein. So if you see a big painting of this type hanging in the apartment of a hedge fund manager, you know he paid millions of dollars for it. That's not always why artists have a signature style, but it's usually why buyers pay a lot for such work. [6] + +There were plenty of earnest students too: kids who "could draw" in high school, and now had come to what was supposed to be the best art school in the country, to learn to draw even better. They tended to be confused and demoralized by what they found at RISD, but they kept going, because painting was what they did. I was not one of the kids who could draw in high school, but at RISD I was definitely closer to their tribe than the tribe of signature style seekers. + +I learned a lot in the color class I took at RISD, but otherwise I was basically teaching myself to paint, and I could do that for free. So in 1993 I dropped out. I hung around Providence for a bit, and then my college friend Nancy Parmet did me a big favor. A rent-controlled apartment in a building her mother owned in New York was becoming vacant. Did I want it? It wasn't much more than my current place, and New York was supposed to be where the artists were. So yes, I wanted it! [7] + +Asterix comics begin by zooming in on a tiny corner of Roman Gaul that turns out not to be controlled by the Romans. You can do something similar on a map of New York City: if you zoom in on the Upper East Side, there's a tiny corner that's not rich, or at least wasn't in 1993. It's called Yorkville, and that was my new home. Now I was a New York artist โ€” in the strictly technical sense of making paintings and living in New York. + +I was nervous about money, because I could sense that Interleaf was on the way down. Freelance Lisp hacking work was very rare, and I didn't want to have to program in another language, which in those days would have meant C++ if I was lucky. So with my unerring nose for financial opportunity, I decided to write another book on Lisp. This would be a popular book, the sort of book that could be used as a textbook. I imagined myself living frugally off the royalties and spending all my time painting. (The painting on the cover of this book, ANSI Common Lisp, is one that I painted around this time.) + +The best thing about New York for me was the presence of Idelle and Julian Weber. Idelle Weber was a painter, one of the early photorealists, and I'd taken her painting class at Harvard. I've never known a teacher more beloved by her students. Large numbers of former students kept in touch with her, including me. After I moved to New York I became her de facto studio assistant. + +She liked to paint on big, square canvases, 4 to 5 feet on a side. One day in late 1994 as I was stretching one of these monsters there was something on the radio about a famous fund manager. He wasn't that much older than me, and was super rich. The thought suddenly occurred to me: why don't I become rich? Then I'll be able to work on whatever I want. + +Meanwhile I'd been hearing more and more about this new thing called the World Wide Web. Robert Morris showed it to me when I visited him in Cambridge, where he was now in grad school at Harvard. It seemed to me that the web would be a big deal. I'd seen what graphical user interfaces had done for the popularity of microcomputers. It seemed like the web would do the same for the internet. + +If I wanted to get rich, here was the next train leaving the station. I was right about that part. What I got wrong was the idea. I decided we should start a company to put art galleries online. I can't honestly say, after reading so many Y Combinator applications, that this was the worst startup idea ever, but it was up there. Art galleries didn't want to be online, and still don't, not the fancy ones. That's not how they sell. I wrote some software to generate web sites for galleries, and Robert wrote some to resize images and set up an http server to serve the pages. Then we tried to sign up galleries. To call this a difficult sale would be an understatement. It was difficult to give away. A few galleries let us make sites for them for free, but none paid us. + +Then some online stores started to appear, and I realized that except for the order buttons they were identical to the sites we'd been generating for galleries. This impressive-sounding thing called an "internet storefront" was something we already knew how to build. + +So in the summer of 1995, after I submitted the camera-ready copy of ANSI Common Lisp to the publishers, we started trying to write software to build online stores. At first this was going to be normal desktop software, which in those days meant Windows software. That was an alarming prospect, because neither of us knew how to write Windows software or wanted to learn. We lived in the Unix world. But we decided we'd at least try writing a prototype store builder on Unix. Robert wrote a shopping cart, and I wrote a new site generator for stores โ€” in Lisp, of course. + +We were working out of Robert's apartment in Cambridge. His roommate was away for big chunks of time, during which I got to sleep in his room. For some reason there was no bed frame or sheets, just a mattress on the floor. One morning as I was lying on this mattress I had an idea that made me sit up like a capital L. What if we ran the software on the server, and let users control it by clicking on links? Then we'd never have to write anything to run on users' computers. We could generate the sites on the same server we'd serve them from. Users wouldn't need anything more than a browser. + +This kind of software, known as a web app, is common now, but at the time it wasn't clear that it was even possible. To find out, we decided to try making a version of our store builder that you could control through the browser. A couple days later, on August 12, we had one that worked. The UI was horrible, but it proved you could build a whole store through the browser, without any client software or typing anything into the command line on the server. + +Now we felt like we were really onto something. I had visions of a whole new generation of software working this way. You wouldn't need versions, or ports, or any of that crap. At Interleaf there had been a whole group called Release Engineering that seemed to be at least as big as the group that actually wrote the software. Now you could just update the software right on the server. + +We started a new company we called Viaweb, after the fact that our software worked via the web, and we got $10,000 in seed funding from Idelle's husband Julian. In return for that and doing the initial legal work and giving us business advice, we gave him 10% of the company. Ten years later this deal became the model for Y Combinator's. We knew founders needed something like this, because we'd needed it ourselves. + +At this stage I had a negative net worth, because the thousand dollars or so I had in the bank was more than counterbalanced by what I owed the government in taxes. (Had I diligently set aside the proper proportion of the money I'd made consulting for Interleaf? No, I had not.) So although Robert had his graduate student stipend, I needed that seed funding to live on. + +We originally hoped to launch in September, but we got more ambitious about the software as we worked on it. Eventually we managed to build a WYSIWYG site builder, in the sense that as you were creating pages, they looked exactly like the static ones that would be generated later, except that instead of leading to static pages, the links all referred to closures stored in a hash table on the server. + +It helped to have studied art, because the main goal of an online store builder is to make users look legit, and the key to looking legit is high production values. If you get page layouts and fonts and colors right, you can make a guy running a store out of his bedroom look more legit than a big company. + +(If you're curious why my site looks so old-fashioned, it's because it's still made with this software. It may look clunky today, but in 1996 it was the last word in slick.) + +In September, Robert rebelled. "We've been working on this for a month," he said, "and it's still not done." This is funny in retrospect, because he would still be working on it almost 3 years later. But I decided it might be prudent to recruit more programmers, and I asked Robert who else in grad school with him was really good. He recommended Trevor Blackwell, which surprised me at first, because at that point I knew Trevor mainly for his plan to reduce everything in his life to a stack of notecards, which he carried around with him. But Rtm was right, as usual. Trevor turned out to be a frighteningly effective hacker. + +It was a lot of fun working with Robert and Trevor. They're the two most independent-minded people I know, and in completely different ways. If you could see inside Rtm's brain it would look like a colonial New England church, and if you could see inside Trevor's it would look like the worst excesses of Austrian Rococo. + +We opened for business, with 6 stores, in January 1996. It was just as well we waited a few months, because although we worried we were late, we were actually almost fatally early. There was a lot of talk in the press then about ecommerce, but not many people actually wanted online stores. [8] + +There were three main parts to the software: the editor, which people used to build sites and which I wrote, the shopping cart, which Robert wrote, and the manager, which kept track of orders and statistics, and which Trevor wrote. In its time, the editor was one of the best general-purpose site builders. I kept the code tight and didn't have to integrate with any other software except Robert's and Trevor's, so it was quite fun to work on. If all I'd had to do was work on this software, the next 3 years would have been the easiest of my life. Unfortunately I had to do a lot more, all of it stuff I was worse at than programming, and the next 3 years were instead the most stressful. + +There were a lot of startups making ecommerce software in the second half of the 90s. We were determined to be the Microsoft Word, not the Interleaf. Which meant being easy to use and inexpensive. It was lucky for us that we were poor, because that caused us to make Viaweb even more inexpensive than we realized. We charged $100 a month for a small store and $300 a month for a big one. This low price was a big attraction, and a constant thorn in the sides of competitors, but it wasn't because of some clever insight that we set the price low. We had no idea what businesses paid for things. $300 a month seemed like a lot of money to us. + +We did a lot of things right by accident like that. For example, we did what's now called "doing things that don't scale," although at the time we would have described it as "being so lame that we're driven to the most desperate measures to get users." The most common of which was building stores for them. This seemed particularly humiliating, since the whole raison d'etre of our software was that people could use it to make their own stores. But anything to get users. + +We learned a lot more about retail than we wanted to know. For example, that if you could only have a small image of a man's shirt (and all images were small then by present standards), it was better to have a closeup of the collar than a picture of the whole shirt. The reason I remember learning this was that it meant I had to rescan about 30 images of men's shirts. My first set of scans were so beautiful too. + +Though this felt wrong, it was exactly the right thing to be doing. Building stores for users taught us about retail, and about how it felt to use our software. I was initially both mystified and repelled by "business" and thought we needed a "business person" to be in charge of it, but once we started to get users, I was converted, in much the same way I was converted to fatherhood once I had kids. Whatever users wanted, I was all theirs. Maybe one day we'd have so many users that I couldn't scan their images for them, but in the meantime there was nothing more important to do. + +Another thing I didn't get at the time is that growth rate is the ultimate test of a startup. Our growth rate was fine. We had about 70 stores at the end of 1996 and about 500 at the end of 1997. I mistakenly thought the thing that mattered was the absolute number of users. And that is the thing that matters in the sense that that's how much money you're making, and if you're not making enough, you might go out of business. But in the long term the growth rate takes care of the absolute number. If we'd been a startup I was advising at Y Combinator, I would have said: Stop being so stressed out, because you're doing fine. You're growing 7x a year. Just don't hire too many more people and you'll soon be profitable, and then you'll control your own destiny. + +Alas I hired lots more people, partly because our investors wanted me to, and partly because that's what startups did during the Internet Bubble. A company with just a handful of employees would have seemed amateurish. So we didn't reach breakeven until about when Yahoo bought us in the summer of 1998. Which in turn meant we were at the mercy of investors for the entire life of the company. And since both we and our investors were noobs at startups, the result was a mess even by startup standards. + +It was a huge relief when Yahoo bought us. In principle our Viaweb stock was valuable. It was a share in a business that was profitable and growing rapidly. But it didn't feel very valuable to me; I had no idea how to value a business, but I was all too keenly aware of the near-death experiences we seemed to have every few months. Nor had I changed my grad student lifestyle significantly since we started. So when Yahoo bought us it felt like going from rags to riches. Since we were going to California, I bought a car, a yellow 1998 VW GTI. I remember thinking that its leather seats alone were by far the most luxurious thing I owned. + +The next year, from the summer of 1998 to the summer of 1999, must have been the least productive of my life. I didn't realize it at the time, but I was worn out from the effort and stress of running Viaweb. For a while after I got to California I tried to continue my usual m.o. of programming till 3 in the morning, but fatigue combined with Yahoo's prematurely aged culture and grim cube farm in Santa Clara gradually dragged me down. After a few months it felt disconcertingly like working at Interleaf. + +Yahoo had given us a lot of options when they bought us. At the time I thought Yahoo was so overvalued that they'd never be worth anything, but to my astonishment the stock went up 5x in the next year. I hung on till the first chunk of options vested, then in the summer of 1999 I left. It had been so long since I'd painted anything that I'd half forgotten why I was doing this. My brain had been entirely full of software and men's shirts for 4 years. But I had done this to get rich so I could paint, I reminded myself, and now I was rich, so I should go paint. + +When I said I was leaving, my boss at Yahoo had a long conversation with me about my plans. I told him all about the kinds of pictures I wanted to paint. At the time I was touched that he took such an interest in me. Now I realize it was because he thought I was lying. My options at that point were worth about $2 million a month. If I was leaving that kind of money on the table, it could only be to go and start some new startup, and if I did, I might take people with me. This was the height of the Internet Bubble, and Yahoo was ground zero of it. My boss was at that moment a billionaire. Leaving then to start a new startup must have seemed to him an insanely, and yet also plausibly, ambitious plan. + +But I really was quitting to paint, and I started immediately. There was no time to lose. I'd already burned 4 years getting rich. Now when I talk to founders who are leaving after selling their companies, my advice is always the same: take a vacation. That's what I should have done, just gone off somewhere and done nothing for a month or two, but the idea never occurred to me. + +So I tried to paint, but I just didn't seem to have any energy or ambition. Part of the problem was that I didn't know many people in California. I'd compounded this problem by buying a house up in the Santa Cruz Mountains, with a beautiful view but miles from anywhere. I stuck it out for a few more months, then in desperation I went back to New York, where unless you understand about rent control you'll be surprised to hear I still had my apartment, sealed up like a tomb of my old life. Idelle was in New York at least, and there were other people trying to paint there, even though I didn't know any of them. + +When I got back to New York I resumed my old life, except now I was rich. It was as weird as it sounds. I resumed all my old patterns, except now there were doors where there hadn't been. Now when I was tired of walking, all I had to do was raise my hand, and (unless it was raining) a taxi would stop to pick me up. Now when I walked past charming little restaurants I could go in and order lunch. It was exciting for a while. Painting started to go better. I experimented with a new kind of still life where I'd paint one painting in the old way, then photograph it and print it, blown up, on canvas, and then use that as the underpainting for a second still life, painted from the same objects (which hopefully hadn't rotted yet). + +Meanwhile I looked for an apartment to buy. Now I could actually choose what neighborhood to live in. Where, I asked myself and various real estate agents, is the Cambridge of New York? Aided by occasional visits to actual Cambridge, I gradually realized there wasn't one. Huh. + +Around this time, in the spring of 2000, I had an idea. It was clear from our experience with Viaweb that web apps were the future. Why not build a web app for making web apps? Why not let people edit code on our server through the browser, and then host the resulting applications for them? [9] You could run all sorts of services on the servers that these applications could use just by making an API call: making and receiving phone calls, manipulating images, taking credit card payments, etc. + +I got so excited about this idea that I couldn't think about anything else. It seemed obvious that this was the future. I didn't particularly want to start another company, but it was clear that this idea would have to be embodied as one, so I decided to move to Cambridge and start it. I hoped to lure Robert into working on it with me, but there I ran into a hitch. Robert was now a postdoc at MIT, and though he'd made a lot of money the last time I'd lured him into working on one of my schemes, it had also been a huge time sink. So while he agreed that it sounded like a plausible idea, he firmly refused to work on it. + +Hmph. Well, I'd do it myself then. I recruited Dan Giffin, who had worked for Viaweb, and two undergrads who wanted summer jobs, and we got to work trying to build what it's now clear is about twenty companies and several open source projects worth of software. The language for defining applications would of course be a dialect of Lisp. But I wasn't so naive as to assume I could spring an overt Lisp on a general audience; we'd hide the parentheses, like Dylan did. + +By then there was a name for the kind of company Viaweb was, an "application service provider," or ASP. This name didn't last long before it was replaced by "software as a service," but it was current for long enough that I named this new company after it: it was going to be called Aspra. + +I started working on the application builder, Dan worked on network infrastructure, and the two undergrads worked on the first two services (images and phone calls). But about halfway through the summer I realized I really didn't want to run a company โ€” especially not a big one, which it was looking like this would have to be. I'd only started Viaweb because I needed the money. Now that I didn't need money anymore, why was I doing this? If this vision had to be realized as a company, then screw the vision. I'd build a subset that could be done as an open source project. + +Much to my surprise, the time I spent working on this stuff was not wasted after all. After we started Y Combinator, I would often encounter startups working on parts of this new architecture, and it was very useful to have spent so much time thinking about it and even trying to write some of it. + +The subset I would build as an open source project was the new Lisp, whose parentheses I now wouldn't even have to hide. A lot of Lisp hackers dream of building a new Lisp, partly because one of the distinctive features of the language is that it has dialects, and partly, I think, because we have in our minds a Platonic form of Lisp that all existing dialects fall short of. I certainly did. So at the end of the summer Dan and I switched to working on this new dialect of Lisp, which I called Arc, in a house I bought in Cambridge. + +The following spring, lightning struck. I was invited to give a talk at a Lisp conference, so I gave one about how we'd used Lisp at Viaweb. Afterward I put a postscript file of this talk online, on paulgraham.com, which I'd created years before using Viaweb but had never used for anything. In one day it got 30,000 page views. What on earth had happened? The referring urls showed that someone had posted it on Slashdot. [10] + +Wow, I thought, there's an audience. If I write something and put it on the web, anyone can read it. That may seem obvious now, but it was surprising then. In the print era there was a narrow channel to readers, guarded by fierce monsters known as editors. The only way to get an audience for anything you wrote was to get it published as a book, or in a newspaper or magazine. Now anyone could publish anything. + +This had been possible in principle since 1993, but not many people had realized it yet. I had been intimately involved with building the infrastructure of the web for most of that time, and a writer as well, and it had taken me 8 years to realize it. Even then it took me several years to understand the implications. It meant there would be a whole new generation of essays. [11] + +In the print era, the channel for publishing essays had been vanishingly small. Except for a few officially anointed thinkers who went to the right parties in New York, the only people allowed to publish essays were specialists writing about their specialties. There were so many essays that had never been written, because there had been no way to publish them. Now they could be, and I was going to write them. [12] + +I've worked on several different things, but to the extent there was a turning point where I figured out what to work on, it was when I started publishing essays online. From then on I knew that whatever else I did, I'd always write essays too. + +I knew that online essays would be a marginal medium at first. Socially they'd seem more like rants posted by nutjobs on their GeoCities sites than the genteel and beautifully typeset compositions published in The New Yorker. But by this point I knew enough to find that encouraging instead of discouraging. + +One of the most conspicuous patterns I've noticed in my life is how well it has worked, for me at least, to work on things that weren't prestigious. Still life has always been the least prestigious form of painting. Viaweb and Y Combinator both seemed lame when we started them. I still get the glassy eye from strangers when they ask what I'm writing, and I explain that it's an essay I'm going to publish on my web site. Even Lisp, though prestigious intellectually in something like the way Latin is, also seems about as hip. + +It's not that unprestigious types of work are good per se. But when you find yourself drawn to some kind of work despite its current lack of prestige, it's a sign both that there's something real to be discovered there, and that you have the right kind of motives. Impure motives are a big danger for the ambitious. If anything is going to lead you astray, it will be the desire to impress people. So while working on things that aren't prestigious doesn't guarantee you're on the right track, it at least guarantees you're not on the most common type of wrong one. + +Over the next several years I wrote lots of essays about all kinds of different topics. O'Reilly reprinted a collection of them as a book, called Hackers & Painters after one of the essays in it. I also worked on spam filters, and did some more painting. I used to have dinners for a group of friends every thursday night, which taught me how to cook for groups. And I bought another building in Cambridge, a former candy factory (and later, twas said, porn studio), to use as an office. + +One night in October 2003 there was a big party at my house. It was a clever idea of my friend Maria Daniels, who was one of the thursday diners. Three separate hosts would all invite their friends to one party. So for every guest, two thirds of the other guests would be people they didn't know but would probably like. One of the guests was someone I didn't know but would turn out to like a lot: a woman called Jessica Livingston. A couple days later I asked her out. + +Jessica was in charge of marketing at a Boston investment bank. This bank thought it understood startups, but over the next year, as she met friends of mine from the startup world, she was surprised how different reality was. And how colorful their stories were. So she decided to compile a book of interviews with startup founders. + +When the bank had financial problems and she had to fire half her staff, she started looking for a new job. In early 2005 she interviewed for a marketing job at a Boston VC firm. It took them weeks to make up their minds, and during this time I started telling her about all the things that needed to be fixed about venture capital. They should make a larger number of smaller investments instead of a handful of giant ones, they should be funding younger, more technical founders instead of MBAs, they should let the founders remain as CEO, and so on. + +One of my tricks for writing essays had always been to give talks. The prospect of having to stand up in front of a group of people and tell them something that won't waste their time is a great spur to the imagination. When the Harvard Computer Society, the undergrad computer club, asked me to give a talk, I decided I would tell them how to start a startup. Maybe they'd be able to avoid the worst of the mistakes we'd made. + +So I gave this talk, in the course of which I told them that the best sources of seed funding were successful startup founders, because then they'd be sources of advice too. Whereupon it seemed they were all looking expectantly at me. Horrified at the prospect of having my inbox flooded by business plans (if I'd only known), I blurted out "But not me!" and went on with the talk. But afterward it occurred to me that I should really stop procrastinating about angel investing. I'd been meaning to since Yahoo bought us, and now it was 7 years later and I still hadn't done one angel investment. + +Meanwhile I had been scheming with Robert and Trevor about projects we could work on together. I missed working with them, and it seemed like there had to be something we could collaborate on. + +As Jessica and I were walking home from dinner on March 11, at the corner of Garden and Walker streets, these three threads converged. Screw the VCs who were taking so long to make up their minds. We'd start our own investment firm and actually implement the ideas we'd been talking about. I'd fund it, and Jessica could quit her job and work for it, and we'd get Robert and Trevor as partners too. [13] + +Once again, ignorance worked in our favor. We had no idea how to be angel investors, and in Boston in 2005 there were no Ron Conways to learn from. So we just made what seemed like the obvious choices, and some of the things we did turned out to be novel. + +There are multiple components to Y Combinator, and we didn't figure them all out at once. The part we got first was to be an angel firm. In those days, those two words didn't go together. There were VC firms, which were organized companies with people whose job it was to make investments, but they only did big, million dollar investments. And there were angels, who did smaller investments, but these were individuals who were usually focused on other things and made investments on the side. And neither of them helped founders enough in the beginning. We knew how helpless founders were in some respects, because we remembered how helpless we'd been. For example, one thing Julian had done for us that seemed to us like magic was to get us set up as a company. We were fine writing fairly difficult software, but actually getting incorporated, with bylaws and stock and all that stuff, how on earth did you do that? Our plan was not only to make seed investments, but to do for startups everything Julian had done for us. + +YC was not organized as a fund. It was cheap enough to run that we funded it with our own money. That went right by 99% of readers, but professional investors are thinking "Wow, that means they got all the returns." But once again, this was not due to any particular insight on our part. We didn't know how VC firms were organized. It never occurred to us to try to raise a fund, and if it had, we wouldn't have known where to start. [14] + +The most distinctive thing about YC is the batch model: to fund a bunch of startups all at once, twice a year, and then to spend three months focusing intensively on trying to help them. That part we discovered by accident, not merely implicitly but explicitly due to our ignorance about investing. We needed to get experience as investors. What better way, we thought, than to fund a whole bunch of startups at once? We knew undergrads got temporary jobs at tech companies during the summer. Why not organize a summer program where they'd start startups instead? We wouldn't feel guilty for being in a sense fake investors, because they would in a similar sense be fake founders. So while we probably wouldn't make much money out of it, we'd at least get to practice being investors on them, and they for their part would probably have a more interesting summer than they would working at Microsoft. + +We'd use the building I owned in Cambridge as our headquarters. We'd all have dinner there once a week โ€” on tuesdays, since I was already cooking for the thursday diners on thursdays โ€” and after dinner we'd bring in experts on startups to give talks. + +We knew undergrads were deciding then about summer jobs, so in a matter of days we cooked up something we called the Summer Founders Program, and I posted an announcement on my site, inviting undergrads to apply. I had never imagined that writing essays would be a way to get "deal flow," as investors call it, but it turned out to be the perfect source. [15] We got 225 applications for the Summer Founders Program, and we were surprised to find that a lot of them were from people who'd already graduated, or were about to that spring. Already this SFP thing was starting to feel more serious than we'd intended. + +We invited about 20 of the 225 groups to interview in person, and from those we picked 8 to fund. They were an impressive group. That first batch included reddit, Justin Kan and Emmett Shear, who went on to found Twitch, Aaron Swartz, who had already helped write the RSS spec and would a few years later become a martyr for open access, and Sam Altman, who would later become the second president of YC. I don't think it was entirely luck that the first batch was so good. You had to be pretty bold to sign up for a weird thing like the Summer Founders Program instead of a summer job at a legit place like Microsoft or Goldman Sachs. + +The deal for startups was based on a combination of the deal we did with Julian ($10k for 10%) and what Robert said MIT grad students got for the summer ($6k). We invested $6k per founder, which in the typical two-founder case was $12k, in return for 6%. That had to be fair, because it was twice as good as the deal we ourselves had taken. Plus that first summer, which was really hot, Jessica brought the founders free air conditioners. [16] + +Fairly quickly I realized that we had stumbled upon the way to scale startup funding. Funding startups in batches was more convenient for us, because it meant we could do things for a lot of startups at once, but being part of a batch was better for the startups too. It solved one of the biggest problems faced by founders: the isolation. Now you not only had colleagues, but colleagues who understood the problems you were facing and could tell you how they were solving them. + +As YC grew, we started to notice other advantages of scale. The alumni became a tight community, dedicated to helping one another, and especially the current batch, whose shoes they remembered being in. We also noticed that the startups were becoming one another's customers. We used to refer jokingly to the "YC GDP," but as YC grows this becomes less and less of a joke. Now lots of startups get their initial set of customers almost entirely from among their batchmates. + +I had not originally intended YC to be a full-time job. I was going to do three things: hack, write essays, and work on YC. As YC grew, and I grew more excited about it, it started to take up a lot more than a third of my attention. But for the first few years I was still able to work on other things. + +In the summer of 2006, Robert and I started working on a new version of Arc. This one was reasonably fast, because it was compiled into Scheme. To test this new Arc, I wrote Hacker News in it. It was originally meant to be a news aggregator for startup founders and was called Startup News, but after a few months I got tired of reading about nothing but startups. Plus it wasn't startup founders we wanted to reach. It was future startup founders. So I changed the name to Hacker News and the topic to whatever engaged one's intellectual curiosity. + +HN was no doubt good for YC, but it was also by far the biggest source of stress for me. If all I'd had to do was select and help founders, life would have been so easy. And that implies that HN was a mistake. Surely the biggest source of stress in one's work should at least be something close to the core of the work. Whereas I was like someone who was in pain while running a marathon not from the exertion of running, but because I had a blister from an ill-fitting shoe. When I was dealing with some urgent problem during YC, there was about a 60% chance it had to do with HN, and a 40% chance it had do with everything else combined. [17] + +As well as HN, I wrote all of YC's internal software in Arc. But while I continued to work a good deal in Arc, I gradually stopped working on Arc, partly because I didn't have time to, and partly because it was a lot less attractive to mess around with the language now that we had all this infrastructure depending on it. So now my three projects were reduced to two: writing essays and working on YC. + +YC was different from other kinds of work I've done. Instead of deciding for myself what to work on, the problems came to me. Every 6 months there was a new batch of startups, and their problems, whatever they were, became our problems. It was very engaging work, because their problems were quite varied, and the good founders were very effective. If you were trying to learn the most you could about startups in the shortest possible time, you couldn't have picked a better way to do it. + +There were parts of the job I didn't like. Disputes between cofounders, figuring out when people were lying to us, fighting with people who maltreated the startups, and so on. But I worked hard even at the parts I didn't like. I was haunted by something Kevin Hale once said about companies: "No one works harder than the boss." He meant it both descriptively and prescriptively, and it was the second part that scared me. I wanted YC to be good, so if how hard I worked set the upper bound on how hard everyone else worked, I'd better work very hard. + +One day in 2010, when he was visiting California for interviews, Robert Morris did something astonishing: he offered me unsolicited advice. I can only remember him doing that once before. One day at Viaweb, when I was bent over double from a kidney stone, he suggested that it would be a good idea for him to take me to the hospital. That was what it took for Rtm to offer unsolicited advice. So I remember his exact words very clearly. "You know," he said, "you should make sure Y Combinator isn't the last cool thing you do." + +At the time I didn't understand what he meant, but gradually it dawned on me that he was saying I should quit. This seemed strange advice, because YC was doing great. But if there was one thing rarer than Rtm offering advice, it was Rtm being wrong. So this set me thinking. It was true that on my current trajectory, YC would be the last thing I did, because it was only taking up more of my attention. It had already eaten Arc, and was in the process of eating essays too. Either YC was my life's work or I'd have to leave eventually. And it wasn't, so I would. + +In the summer of 2012 my mother had a stroke, and the cause turned out to be a blood clot caused by colon cancer. The stroke destroyed her balance, and she was put in a nursing home, but she really wanted to get out of it and back to her house, and my sister and I were determined to help her do it. I used to fly up to Oregon to visit her regularly, and I had a lot of time to think on those flights. On one of them I realized I was ready to hand YC over to someone else. + +I asked Jessica if she wanted to be president, but she didn't, so we decided we'd try to recruit Sam Altman. We talked to Robert and Trevor and we agreed to make it a complete changing of the guard. Up till that point YC had been controlled by the original LLC we four had started. But we wanted YC to last for a long time, and to do that it couldn't be controlled by the founders. So if Sam said yes, we'd let him reorganize YC. Robert and I would retire, and Jessica and Trevor would become ordinary partners. + +When we asked Sam if he wanted to be president of YC, initially he said no. He wanted to start a startup to make nuclear reactors. But I kept at it, and in October 2013 he finally agreed. We decided he'd take over starting with the winter 2014 batch. For the rest of 2013 I left running YC more and more to Sam, partly so he could learn the job, and partly because I was focused on my mother, whose cancer had returned. + +She died on January 15, 2014. We knew this was coming, but it was still hard when it did. + +I kept working on YC till March, to help get that batch of startups through Demo Day, then I checked out pretty completely. (I still talk to alumni and to new startups working on things I'm interested in, but that only takes a few hours a week.) + +What should I do next? Rtm's advice hadn't included anything about that. I wanted to do something completely different, so I decided I'd paint. I wanted to see how good I could get if I really focused on it. So the day after I stopped working on YC, I started painting. I was rusty and it took a while to get back into shape, but it was at least completely engaging. [18] + +I spent most of the rest of 2014 painting. I'd never been able to work so uninterruptedly before, and I got to be better than I had been. Not good enough, but better. Then in November, right in the middle of a painting, I ran out of steam. Up till that point I'd always been curious to see how the painting I was working on would turn out, but suddenly finishing this one seemed like a chore. So I stopped working on it and cleaned my brushes and haven't painted since. So far anyway. + +I realize that sounds rather wimpy. But attention is a zero sum game. If you can choose what to work on, and you choose a project that's not the best one (or at least a good one) for you, then it's getting in the way of another project that is. And at 50 there was some opportunity cost to screwing around. + +I started writing essays again, and wrote a bunch of new ones over the next few months. I even wrote a couple that weren't about startups. Then in March 2015 I started working on Lisp again. + +The distinctive thing about Lisp is that its core is a language defined by writing an interpreter in itself. It wasn't originally intended as a programming language in the ordinary sense. It was meant to be a formal model of computation, an alternative to the Turing machine. If you want to write an interpreter for a language in itself, what's the minimum set of predefined operators you need? The Lisp that John McCarthy invented, or more accurately discovered, is an answer to that question. [19] + +McCarthy didn't realize this Lisp could even be used to program computers till his grad student Steve Russell suggested it. Russell translated McCarthy's interpreter into IBM 704 machine language, and from that point Lisp started also to be a programming language in the ordinary sense. But its origins as a model of computation gave it a power and elegance that other languages couldn't match. It was this that attracted me in college, though I didn't understand why at the time. + +McCarthy's 1960 Lisp did nothing more than interpret Lisp expressions. It was missing a lot of things you'd want in a programming language. So these had to be added, and when they were, they weren't defined using McCarthy's original axiomatic approach. That wouldn't have been feasible at the time. McCarthy tested his interpreter by hand-simulating the execution of programs. But it was already getting close to the limit of interpreters you could test that way โ€” indeed, there was a bug in it that McCarthy had overlooked. To test a more complicated interpreter, you'd have had to run it, and computers then weren't powerful enough. + +Now they are, though. Now you could continue using McCarthy's axiomatic approach till you'd defined a complete programming language. And as long as every change you made to McCarthy's Lisp was a discoveredness-preserving transformation, you could, in principle, end up with a complete language that had this quality. Harder to do than to talk about, of course, but if it was possible in principle, why not try? So I decided to take a shot at it. It took 4 years, from March 26, 2015 to October 12, 2019. It was fortunate that I had a precisely defined goal, or it would have been hard to keep at it for so long. + +I wrote this new Lisp, called Bel, in itself in Arc. That may sound like a contradiction, but it's an indication of the sort of trickery I had to engage in to make this work. By means of an egregious collection of hacks I managed to make something close enough to an interpreter written in itself that could actually run. Not fast, but fast enough to test. + +I had to ban myself from writing essays during most of this time, or I'd never have finished. In late 2015 I spent 3 months writing essays, and when I went back to working on Bel I could barely understand the code. Not so much because it was badly written as because the problem is so convoluted. When you're working on an interpreter written in itself, it's hard to keep track of what's happening at what level, and errors can be practically encrypted by the time you get them. + +So I said no more essays till Bel was done. But I told few people about Bel while I was working on it. So for years it must have seemed that I was doing nothing, when in fact I was working harder than I'd ever worked on anything. Occasionally after wrestling for hours with some gruesome bug I'd check Twitter or HN and see someone asking "Does Paul Graham still code?" + +Working on Bel was hard but satisfying. I worked on it so intensively that at any given time I had a decent chunk of the code in my head and could write more there. I remember taking the boys to the coast on a sunny day in 2015 and figuring out how to deal with some problem involving continuations while I watched them play in the tide pools. It felt like I was doing life right. I remember that because I was slightly dismayed at how novel it felt. The good news is that I had more moments like this over the next few years. + +In the summer of 2016 we moved to England. We wanted our kids to see what it was like living in another country, and since I was a British citizen by birth, that seemed the obvious choice. We only meant to stay for a year, but we liked it so much that we still live there. So most of Bel was written in England. + +In the fall of 2019, Bel was finally finished. Like McCarthy's original Lisp, it's a spec rather than an implementation, although like McCarthy's Lisp it's a spec expressed as code. + +Now that I could write essays again, I wrote a bunch about topics I'd had stacked up. I kept writing essays through 2020, but I also started to think about other things I could work on. How should I choose what to do? Well, how had I chosen what to work on in the past? I wrote an essay for myself to answer that question, and I was surprised how long and messy the answer turned out to be. If this surprised me, who'd lived it, then I thought perhaps it would be interesting to other people, and encouraging to those with similarly messy lives. So I wrote a more detailed version for others to read, and this is the last sentence of it. + + + + + + + + + +Notes + +[1] My experience skipped a step in the evolution of computers: time-sharing machines with interactive OSes. I went straight from batch processing to microcomputers, which made microcomputers seem all the more exciting. + +[2] Italian words for abstract concepts can nearly always be predicted from their English cognates (except for occasional traps like polluzione). It's the everyday words that differ. So if you string together a lot of abstract concepts with a few simple verbs, you can make a little Italian go a long way. + +[3] I lived at Piazza San Felice 4, so my walk to the Accademia went straight down the spine of old Florence: past the Pitti, across the bridge, past Orsanmichele, between the Duomo and the Baptistery, and then up Via Ricasoli to Piazza San Marco. I saw Florence at street level in every possible condition, from empty dark winter evenings to sweltering summer days when the streets were packed with tourists. + +[4] You can of course paint people like still lives if you want to, and they're willing. That sort of portrait is arguably the apex of still life painting, though the long sitting does tend to produce pained expressions in the sitters. + +[5] Interleaf was one of many companies that had smart people and built impressive technology, and yet got crushed by Moore's Law. In the 1990s the exponential growth in the power of commodity (i.e. Intel) processors rolled up high-end, special-purpose hardware and software companies like a bulldozer. + +[6] The signature style seekers at RISD weren't specifically mercenary. In the art world, money and coolness are tightly coupled. Anything expensive comes to be seen as cool, and anything seen as cool will soon become equally expensive. + +[7] Technically the apartment wasn't rent-controlled but rent-stabilized, but this is a refinement only New Yorkers would know or care about. The point is that it was really cheap, less than half market price. + +[8] Most software you can launch as soon as it's done. But when the software is an online store builder and you're hosting the stores, if you don't have any users yet, that fact will be painfully obvious. So before we could launch publicly we had to launch privately, in the sense of recruiting an initial set of users and making sure they had decent-looking stores. + +[9] We'd had a code editor in Viaweb for users to define their own page styles. They didn't know it, but they were editing Lisp expressions underneath. But this wasn't an app editor, because the code ran when the merchants' sites were generated, not when shoppers visited them. + +[10] This was the first instance of what is now a familiar experience, and so was what happened next, when I read the comments and found they were full of angry people. How could I claim that Lisp was better than other languages? Weren't they all Turing complete? People who see the responses to essays I write sometimes tell me how sorry they feel for me, but I'm not exaggerating when I reply that it has always been like this, since the very beginning. It comes with the territory. An essay must tell readers things they don't already know, and some people dislike being told such things. + +[11] People put plenty of stuff on the internet in the 90s of course, but putting something online is not the same as publishing it online. Publishing online means you treat the online version as the (or at least a) primary version. + +[12] There is a general lesson here that our experience with Y Combinator also teaches: Customs continue to constrain you long after the restrictions that caused them have disappeared. Customary VC practice had once, like the customs about publishing essays, been based on real constraints. Startups had once been much more expensive to start, and proportionally rare. Now they could be cheap and common, but the VCs' customs still reflected the old world, just as customs about writing essays still reflected the constraints of the print era. + +Which in turn implies that people who are independent-minded (i.e. less influenced by custom) will have an advantage in fields affected by rapid change (where customs are more likely to be obsolete). + +Here's an interesting point, though: you can't always predict which fields will be affected by rapid change. Obviously software and venture capital will be, but who would have predicted that essay writing would be? + +[13] Y Combinator was not the original name. At first we were called Cambridge Seed. But we didn't want a regional name, in case someone copied us in Silicon Valley, so we renamed ourselves after one of the coolest tricks in the lambda calculus, the Y combinator. + +I picked orange as our color partly because it's the warmest, and partly because no VC used it. In 2005 all the VCs used staid colors like maroon, navy blue, and forest green, because they were trying to appeal to LPs, not founders. The YC logo itself is an inside joke: the Viaweb logo had been a white V on a red circle, so I made the YC logo a white Y on an orange square. + +[14] YC did become a fund for a couple years starting in 2009, because it was getting so big I could no longer afford to fund it personally. But after Heroku got bought we had enough money to go back to being self-funded. + +[15] I've never liked the term "deal flow," because it implies that the number of new startups at any given time is fixed. This is not only false, but it's the purpose of YC to falsify it, by causing startups to be founded that would not otherwise have existed. + +[16] She reports that they were all different shapes and sizes, because there was a run on air conditioners and she had to get whatever she could, but that they were all heavier than she could carry now. + +[17] Another problem with HN was a bizarre edge case that occurs when you both write essays and run a forum. When you run a forum, you're assumed to see if not every conversation, at least every conversation involving you. And when you write essays, people post highly imaginative misinterpretations of them on forums. Individually these two phenomena are tedious but bearable, but the combination is disastrous. You actually have to respond to the misinterpretations, because the assumption that you're present in the conversation means that not responding to any sufficiently upvoted misinterpretation reads as a tacit admission that it's correct. But that in turn encourages more; anyone who wants to pick a fight with you senses that now is their chance. + +[18] The worst thing about leaving YC was not working with Jessica anymore. We'd been working on YC almost the whole time we'd known each other, and we'd neither tried nor wanted to separate it from our personal lives, so leaving was like pulling up a deeply rooted tree. + +[19] One way to get more precise about the concept of invented vs discovered is to talk about space aliens. Any sufficiently advanced alien civilization would certainly know about the Pythagorean theorem, for example. I believe, though with less certainty, that they would also know about the Lisp in McCarthy's 1960 paper. + +But if so there's no reason to suppose that this is the limit of the language that might be known to them. Presumably aliens need numbers and errors and I/O too. So it seems likely there exists at least one path out of McCarthy's Lisp along which discoveredness is preserved. + + + +Thanks to Trevor Blackwell, John Collison, Patrick Collison, Daniel Gackle, Ralph Hazell, Jessica Livingston, Robert Morris, and Harj Taggar for reading drafts of this. \ No newline at end of file diff --git a/docs/examples/usage_example.ipynb b/docs/examples/usage_example.ipynb index 3cea6df..b5be5b3 100644 --- a/docs/examples/usage_example.ipynb +++ b/docs/examples/usage_example.ipynb @@ -51,7 +51,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -86,9 +86,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/client.py:195: UserWarning: You're connecting to Argilla Server 1.19.0 using a different client version (1.26.1).\n", + "This may lead to potential compatibility issues during your experience.\n", + "To ensure a seamless and optimized connection, we highly recommend aligning your client version with the server version.\n", + " warnings.warn(\n" + ] + } + ], "source": [ "import argilla as rg\n", "\n", @@ -101,9 +112,104 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "

\n" + ], + "text/plain": [ + "\u001b[2;36m[04/09/24 16:26:24]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m INFO:argilla.client.feedback.dataset.local.mixins:โœ“ Dataset succesfully \u001b]8;id=154751;file:///Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/feedback/dataset/local/mixins.py\u001b\\\u001b[2mmixins.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=190584;file:///Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/feedback/dataset/local/mixins.py#271\u001b\\\u001b[2m271\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m pushed to Argilla \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
                    INFO     INFO:argilla.client.feedback.dataset.local.mixins:RemoteFeedbackDataset( mixins.py:272\n",
+       "                                id=f3ca83bf-14c0-49a8-9d30-7bdd7fe88cf0                                            \n",
+       "                                name=query_model                                                                   \n",
+       "                                workspace=Workspace(id=5b42d217-c190-4916-835b-924c9eb766ef,                       \n",
+       "                             name=admin, inserted_at=2024-04-09 08:59:41.374316,                                   \n",
+       "                             updated_at=2024-04-09 08:59:41.374316)                                                \n",
+       "                                url=http://localhost:6900/dataset/f3ca83bf-14c0-49a8-9d30-7bdd7fe88cf              \n",
+       "                             0/annotation-mode                                                                     \n",
+       "                                fields=[RemoteTextField(id=UUID('e199de61-ec75-43b3-85b8-75ca82f95d5d              \n",
+       "                             '), client=None, name='prompt', title='Prompt', required=True,                        \n",
+       "                             type='text', use_markdown=False),                                                     \n",
+       "                             RemoteTextField(id=UUID('fc7e8a06-7778-47b0-bbd3-69347586e951'),                      \n",
+       "                             client=None, name='response', title='Response', required=False,                       \n",
+       "                             type='text', use_markdown=False),                                                     \n",
+       "                             RemoteTextField(id=UUID('c65d166a-f9e4-4270-853e-68d935deee64'),                      \n",
+       "                             client=None, name='time-details', title='Time Details', required=True,                \n",
+       "                             type='text', use_markdown=True)]                                                      \n",
+       "                                questions=[RemoteRatingQuestion(id=UUID('199e8908-2c37-4e86-bf6e-a9dd              \n",
+       "                             c8813f6a'), client=None, name='response-rating', title='Rating for the                \n",
+       "                             response', description='How would you rate the quality of the                         \n",
+       "                             response?', required=True, type='rating', values=[1, 2, 3, 4, 5, 6, 7]),              \n",
+       "                             RemoteTextQuestion(id=UUID('82111561-fe34-44ad-952e-77d532152ebc'),                   \n",
+       "                             client=None, name='response-feedback', title='Feedback for the                        \n",
+       "                             response', description='What feedback do you have for the response?',                 \n",
+       "                             required=False, type='text', use_markdown=False)]                                     \n",
+       "                                guidelines=You're asked to rate the quality of the response and                    \n",
+       "                             provide feedback.                                                                     \n",
+       "                                metadata_properties=[]                                                             \n",
+       "                                vectors_settings=[]                                                                \n",
+       "                             )                                                                                     \n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m INFO:argilla.client.feedback.dataset.local.mixins:\u001b[1;35mRemoteFeedbackDataset\u001b[0m\u001b[1m(\u001b[0m \u001b]8;id=994278;file:///Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/feedback/dataset/local/mixins.py\u001b\\\u001b[2mmixins.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=162794;file:///Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/feedback/dataset/local/mixins.py#272\u001b\\\u001b[2m272\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m \u001b[33mid\u001b[0m=\u001b[93mf3ca83bf\u001b[0m\u001b[93m-14c0-49a8-9d30-7bdd7fe88cf0\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mname\u001b[0m=\u001b[35mquery_model\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mworkspace\u001b[0m=\u001b[1;35mWorkspace\u001b[0m\u001b[1m(\u001b[0m\u001b[33mid\u001b[0m=\u001b[93m5b42d217\u001b[0m\u001b[93m-c190-4916-835b-924c9eb766ef\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mname\u001b[0m=\u001b[35madmin\u001b[0m, \u001b[33minserted_at\u001b[0m=\u001b[1;36m2024\u001b[0m-\u001b[1;36m04\u001b[0m-\u001b[1;36m09\u001b[0m \u001b[1;92m08:59:41\u001b[0m.\u001b[1;36m374316\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mupdated_at\u001b[0m=\u001b[1;36m2024\u001b[0m-\u001b[1;36m04\u001b[0m-\u001b[1;36m09\u001b[0m \u001b[1;92m08:59:41\u001b[0m.\u001b[1;36m374316\u001b[0m\u001b[1m)\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33murl\u001b[0m=\u001b[4;94mhttp\u001b[0m\u001b[4;94m://localhost:6900/dataset/f3ca83bf-14c0-49a8-9d30-7bdd7fe88cf\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[4;94m0/annotation-mode\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mfields\u001b[0m=\u001b[1m[\u001b[0m\u001b[1;35mRemoteTextField\u001b[0m\u001b[1m(\u001b[0m\u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'e199de61-ec75-43b3-85b8-75ca82f95d5d\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'\u001b[0m\u001b[1m)\u001b[0m, \u001b[33mclient\u001b[0m=\u001b[3;35mNone\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'prompt'\u001b[0m, \u001b[33mtitle\u001b[0m=\u001b[32m'Prompt'\u001b[0m, \u001b[33mrequired\u001b[0m=\u001b[3;92mTrue\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mtype\u001b[0m=\u001b[32m'text'\u001b[0m, \u001b[33muse_markdown\u001b[0m=\u001b[3;91mFalse\u001b[0m\u001b[1m)\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[1;35mRemoteTextField\u001b[0m\u001b[1m(\u001b[0m\u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'fc7e8a06-7778-47b0-bbd3-69347586e951'\u001b[0m\u001b[1m)\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mclient\u001b[0m=\u001b[3;35mNone\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'response'\u001b[0m, \u001b[33mtitle\u001b[0m=\u001b[32m'Response'\u001b[0m, \u001b[33mrequired\u001b[0m=\u001b[3;91mFalse\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mtype\u001b[0m=\u001b[32m'text'\u001b[0m, \u001b[33muse_markdown\u001b[0m=\u001b[3;91mFalse\u001b[0m\u001b[1m)\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[1;35mRemoteTextField\u001b[0m\u001b[1m(\u001b[0m\u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'c65d166a-f9e4-4270-853e-68d935deee64'\u001b[0m\u001b[1m)\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mclient\u001b[0m=\u001b[3;35mNone\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'time-details'\u001b[0m, \u001b[33mtitle\u001b[0m=\u001b[32m'Time Details'\u001b[0m, \u001b[33mrequired\u001b[0m=\u001b[3;92mTrue\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mtype\u001b[0m=\u001b[32m'text'\u001b[0m, \u001b[33muse_markdown\u001b[0m=\u001b[3;92mTrue\u001b[0m\u001b[1m)\u001b[0m\u001b[1m]\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mquestions\u001b[0m=\u001b[1m[\u001b[0m\u001b[1;35mRemoteRatingQuestion\u001b[0m\u001b[1m(\u001b[0m\u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'199e8908-2c37-4e86-bf6e-a9dd\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32mc8813f6a'\u001b[0m\u001b[1m)\u001b[0m, \u001b[33mclient\u001b[0m=\u001b[3;35mNone\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'response-rating'\u001b[0m, \u001b[33mtitle\u001b[0m=\u001b[32m'Rating for the \u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32mresponse'\u001b[0m, \u001b[33mdescription\u001b[0m=\u001b[32m'How would you rate the quality of the \u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32mresponse?'\u001b[0m, \u001b[33mrequired\u001b[0m=\u001b[3;92mTrue\u001b[0m, \u001b[33mtype\u001b[0m=\u001b[32m'rating'\u001b[0m, \u001b[33mvalues\u001b[0m=\u001b[1m[\u001b[0m\u001b[1;36m1\u001b[0m, \u001b[1;36m2\u001b[0m, \u001b[1;36m3\u001b[0m, \u001b[1;36m4\u001b[0m, \u001b[1;36m5\u001b[0m, \u001b[1;36m6\u001b[0m, \u001b[1;36m7\u001b[0m\u001b[1m]\u001b[0m\u001b[1m)\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[1;35mRemoteTextQuestion\u001b[0m\u001b[1m(\u001b[0m\u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'82111561-fe34-44ad-952e-77d532152ebc'\u001b[0m\u001b[1m)\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mclient\u001b[0m=\u001b[3;35mNone\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'response-feedback'\u001b[0m, \u001b[33mtitle\u001b[0m=\u001b[32m'Feedback for the \u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32mresponse'\u001b[0m, \u001b[33mdescription\u001b[0m=\u001b[32m'What feedback do you have for the response?'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mrequired\u001b[0m=\u001b[3;91mFalse\u001b[0m, \u001b[33mtype\u001b[0m=\u001b[32m'text'\u001b[0m, \u001b[33muse_markdown\u001b[0m=\u001b[3;91mFalse\u001b[0m\u001b[1m)\u001b[0m\u001b[1m]\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mguidelines\u001b[0m=\u001b[35mYou\u001b[0m're asked to rate the quality of the response and \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m provide feedback. \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mmetadata_properties\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[33mvectors_settings\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[1m)\u001b[0m \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/ignacio/Documents/recognai/argilla-llama-index/src/argilla_llama_index/llama_index_handler.py:135: UserWarning: No dataset with the name query_model was found in workspace admin. A new dataset with the name query_model has been created with the question fields `prompt` and `response`and the rating question `response-rating` with values 1-7 and text question named `response-feedback`.\n", + " warnings.warn(\n" + ] + } + ], "source": [ "set_global_handler(\"argilla\", dataset_name=\"query_model\")" ] @@ -117,7 +223,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -128,14 +234,23 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "With the code snippet below, you can create a basic workflow with LlamaIndex. You will also need a txt file as the data source within a folder named \"data\". For a sample data file and more info regarding the use of Llama Index, you can refer to the [Llama Index documentation](https://docs.llamaindex.ai/en/stable/getting_started/starter_example.html)." + "With the code snippet below, you can create a basic workflow with LlamaIndex. You will also need a txt file as the data source within a folder named \"data\". We have an example `.txt` file ready for you inside that folder, obtained from the [Llama Index documentation](https://docs.llamaindex.ai/en/stable/getting_started/starter_example.html)." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/s0/4h4_2s7n3wxbm06wx8y43mm80000gn/T/ipykernel_24151/2413633764.py:1: DeprecationWarning: Call to deprecated class method from_defaults. (ServiceContext is deprecated, please use `llama_index.settings.Settings` instead.) -- Deprecated since version 0.10.0.\n", + " service_context = ServiceContext.from_defaults(llm=llm)\n" + ] + } + ], "source": [ "service_context = ServiceContext.from_defaults(llm=llm)\n", "docs = SimpleDirectoryReader(\"../data\").load_data()\n", @@ -152,9 +267,60 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
/Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/rich/live.py:231: \n",
+       "UserWarning: install \"ipywidgets\" for Jupyter support\n",
+       "  warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
+       "
\n" + ], + "text/plain": [ + "/Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/rich/live.py:231: \n", + "UserWarning: install \"ipywidgets\" for Jupyter support\n", + " warnings.warn('install \"ipywidgets\" for Jupyter support')\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Response(response='The author, growing up, worked on writing short stories and programming. Initially, he wrote short stories with minimal plots but strong character emotions. He then delved into programming on an IBM 1401 using an early version of Fortran, creating programs that had limited functionality due to the constraints of the system. Later, with the introduction of microcomputers, he transitioned to programming on more user-friendly platforms like the TRS-80, where he developed simple games and a word processor.', source_nodes=[NodeWithScore(node=TextNode(id_='9e4d418c-649e-4317-9cc5-777fc659528a', embedding=None, metadata={'file_path': '/Users/ignacio/Documents/recognai/argilla-llama-index/docs/examples/../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-03-25', 'last_modified_date': '2024-02-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={: RelatedNodeInfo(node_id='ab9ee02b-4635-4b53-acb7-c1f6714966a9', node_type=, metadata={'file_path': '/Users/ignacio/Documents/recognai/argilla-llama-index/docs/examples/../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-03-25', 'last_modified_date': '2024-02-21'}, hash='c34bd0969e513ba2da03a97709eddd65d16fe620402e90d98503e25c0a29fbc9'), : RelatedNodeInfo(node_id='7d532b80-c8bf-48c0-bfc1-5b25df1237b5', node_type=, metadata={}, hash='385569b09072ef6417168a265570a74d83f193a1e01c168e2038ad68f0ba5275')}, text='What I Worked On\\n\\nFebruary 2021\\n\\nBefore college the two main things I worked on, outside of school, were writing and programming. I didn\\'t write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep.\\n\\nThe first programs I tried writing were on the IBM 1401 that our school district used for what was then called \"data processing.\" This was in 9th grade, so I was 13 or 14. The school district\\'s 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain\\'s lair down there, with all these alien-looking machines โ€” CPU, disk drives, printer, card reader โ€” sitting up on a raised floor under bright fluorescent lights.\\n\\nThe language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer.\\n\\nI was puzzled by the 1401. I couldn\\'t figure out what to do with it. And in retrospect there\\'s not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn\\'t have any data stored on punched cards. The only other option was to do things that didn\\'t rely on any input, like calculate approximations of pi, but I didn\\'t know enough math to do anything interesting of that type. So I\\'m not surprised I can\\'t remember any programs I wrote, because they can\\'t have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn\\'t. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager\\'s expression made clear.\\n\\nWith microcomputers, everything changed. Now you could have a computer sitting right in front of you, on a desk, that could respond to your keystrokes as it was running instead of just churning through a stack of punch cards and then stopping. [1]\\n\\nThe first of my friends to get a microcomputer built it himself. It was sold as a kit by Heathkit. I remember vividly how impressed and envious I felt watching him sitting in front of it, typing programs right into the computer.\\n\\nComputers were expensive in those days and it took me years of nagging before I convinced my father to buy one, a TRS-80, in about 1980. The gold standard then was the Apple II, but a TRS-80 was good enough. This was when I really started programming. I wrote simple games, a program to predict how high my model rockets would fly, and a word processor that my father used to write at least one book. There was only room in memory for about 2 pages of text, so he\\'d write 2 pages at a time and then print them out, but it was a lot better than a typewriter.\\n\\nThough I liked programming, I didn\\'t plan to study it in college. In college I was going to study philosophy, which sounded much more powerful. It seemed, to my naive high school self, to be the study of the ultimate truths, compared to which the things studied in other fields would be mere domain knowledge. What I discovered when I got to college was that the other fields took up so much of the space of ideas that there wasn\\'t much left for these supposed ultimate truths. All that seemed left for philosophy were edge cases that people in other fields felt could safely be ignored.\\n\\nI couldn\\'t have put this into words when I was 18. All I knew at the time was that I kept taking philosophy courses and they kept being boring. So I decided to switch to AI.\\n\\nAI was in the air in the mid 1980s, but there were two things especially that made me want to work on it: a novel by Heinlein called The Moon is a Harsh Mistress, which featured an intelligent computer called Mike, and a PBS documentary that showed Terry Winograd using SHRDLU. I haven\\'t tried rereading The Moon is a Harsh Mistress, so I don\\'t know how well it has aged, but when I read it I was drawn entirely into its world.', start_char_idx=2, end_char_idx=4172, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n'), score=0.8214175012009751), NodeWithScore(node=TextNode(id_='2118264c-1adb-4bfa-9d98-68ab01e1120e', embedding=None, metadata={'file_path': '/Users/ignacio/Documents/recognai/argilla-llama-index/docs/examples/../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-03-25', 'last_modified_date': '2024-02-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={: RelatedNodeInfo(node_id='ab9ee02b-4635-4b53-acb7-c1f6714966a9', node_type=, metadata={'file_path': '/Users/ignacio/Documents/recognai/argilla-llama-index/docs/examples/../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-03-25', 'last_modified_date': '2024-02-21'}, hash='c34bd0969e513ba2da03a97709eddd65d16fe620402e90d98503e25c0a29fbc9'), : RelatedNodeInfo(node_id='dd85c016-46ac-4140-a09e-e534d9f4d81a', node_type=, metadata={'file_path': '/Users/ignacio/Documents/recognai/argilla-llama-index/docs/examples/../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-03-25', 'last_modified_date': '2024-02-21'}, hash='901f63f38cf3ad32a9a9b44650ec4bc23c3f06f9ebd99d9427d0ba2882d0d726'), : RelatedNodeInfo(node_id='1c49ca65-3b92-4202-a69a-ccb4bc9e6b8f', node_type=, metadata={}, hash='53bc5d0c0d3a671ffa8ade96a7e64d63c3315d9b55582ee33e3063ff908f3467')}, text='If he even knew about the strange classes I was taking, he never said anything.\\n\\nSo now I was in a PhD program in computer science, yet planning to be an artist, yet also genuinely in love with Lisp hacking and working away at On Lisp. In other words, like many a grad student, I was working energetically on multiple projects that were not my thesis.\\n\\nI didn\\'t see a way out of this situation. I didn\\'t want to drop out of grad school, but how else was I going to get out? I remember when my friend Robert Morris got kicked out of Cornell for writing the internet worm of 1988, I was envious that he\\'d found such a spectacular way to get out of grad school.\\n\\nThen one day in April 1990 a crack appeared in the wall. I ran into professor Cheatham and he asked if I was far enough along to graduate that June. I didn\\'t have a word of my dissertation written, but in what must have been the quickest bit of thinking in my life, I decided to take a shot at writing one in the 5 weeks or so that remained before the deadline, reusing parts of On Lisp where I could, and I was able to respond, with no perceptible delay \"Yes, I think so. I\\'ll give you something to read in a few days.\"\\n\\nI picked applications of continuations as the topic. In retrospect I should have written about macros and embedded languages. There\\'s a whole world there that\\'s barely been explored. But all I wanted was to get out of grad school, and my rapidly written dissertation sufficed, just barely.\\n\\nMeanwhile I was applying to art schools. I applied to two: RISD in the US, and the Accademia di Belli Arti in Florence, which, because it was the oldest art school, I imagined would be good. RISD accepted me, and I never heard back from the Accademia, so off to Providence I went.\\n\\nI\\'d applied for the BFA program at RISD, which meant in effect that I had to go to college again. This was not as strange as it sounds, because I was only 25, and art schools are full of people of different ages. RISD counted me as a transfer sophomore and said I had to do the foundation that summer. The foundation means the classes that everyone has to take in fundamental subjects like drawing, color, and design.\\n\\nToward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they\\'d sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I\\'d done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian.\\n\\nOnly stranieri (foreigners) had to take this entrance exam. In retrospect it may well have been a way of excluding them, because there were so many stranieri attracted by the idea of studying art in Florence that the Italian students would otherwise have been outnumbered. I was in decent shape at painting and drawing from the RISD foundation that summer, but I still don\\'t know how I managed to pass the written exam. I remember that I answered the essay question by writing about Cezanne, and that I cranked up the intellectual level as high as I could to make the most of my limited vocabulary. [2]\\n\\nI\\'m only up to age 25 and already there are such conspicuous patterns. Here I was, yet again about to attend some august institution in the hopes of learning about some prestigious subject, and yet again about to be disappointed. The students and faculty in the painting department at the Accademia were the nicest people you could imagine, but they had long since arrived at an arrangement whereby the students wouldn\\'t require the faculty to teach anything, and in return the faculty wouldn\\'t require the students to learn anything. And at the same time all involved would adhere outwardly to the conventions of a 19th century atelier. We actually had one of those little stoves, fed with kindling, that you see in 19th century studio paintings, and a nude model sitting as close to it as possible without getting burned. Except hardly anyone else painted her besides me. The rest of the students spent their time chatting or occasionally trying to imitate things they\\'d seen in American art magazines.\\n\\nOur model turned out to live just down the street from me.', start_char_idx=10369, end_char_idx=14708, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n'), score=0.8100195429647877)], metadata={'9e4d418c-649e-4317-9cc5-777fc659528a': {'file_path': '/Users/ignacio/Documents/recognai/argilla-llama-index/docs/examples/../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-03-25', 'last_modified_date': '2024-02-21'}, '2118264c-1adb-4bfa-9d98-68ab01e1120e': {'file_path': '/Users/ignacio/Documents/recognai/argilla-llama-index/docs/examples/../data/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75041, 'creation_date': '2024-03-25', 'last_modified_date': '2024-02-21'}})" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "response = query_engine.query(\"What did the author do growing up?\")\n", "response" From 2dad8879ce2408e4201400dd751a234c4ed6d54b Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 16:43:22 +0200 Subject: [PATCH 15/24] rephrasing --- docs/examples/usage_example.ipynb | 38 ++++++++----------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/docs/examples/usage_example.ipynb b/docs/examples/usage_example.ipynb index b5be5b3..07a7216 100644 --- a/docs/examples/usage_example.ipynb +++ b/docs/examples/usage_example.ipynb @@ -64,7 +64,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's now write all the necessary imports" + "Let's now write all the necessary imports and initialize the Argilla client" ] }, { @@ -74,33 +74,8 @@ "outputs": [], "source": [ "from llama_index.core import VectorStoreIndex, ServiceContext, SimpleDirectoryReader, set_global_handler\n", - "from llama_index.llms.openai import OpenAI" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What we need to do is to set Argilla as the global handler as below. Within the handler, we need to provide the dataset name that we will use. If the dataset does not exist, it will be created with the given name. You can also set the API KEY, API URL, and the Workspace name. You can learn more about the variables that controls Argilla initialization [here](https://docs.argilla.io/en/latest/getting_started/installation/configurations/workspace_management.html)." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/ignacio/Documents/recognai/argilla-llama-index/.venv/lib/python3.10/site-packages/argilla/client/client.py:195: UserWarning: You're connecting to Argilla Server 1.19.0 using a different client version (1.26.1).\n", - "This may lead to potential compatibility issues during your experience.\n", - "To ensure a seamless and optimized connection, we highly recommend aligning your client version with the server version.\n", - " warnings.warn(\n" - ] - } - ], - "source": [ + "from llama_index.llms.openai import OpenAI\n", + "\n", "import argilla as rg\n", "\n", "rg.init(\n", @@ -110,6 +85,13 @@ ")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we will set up an Argilla global handler for Llama Index. By doing so, we ensure that the predictions that we obtain using Llama Index is automatically uploaded to the Argilla client we initialized before Within the handler, we need to provide the dataset name that we will use. If the dataset does not exist, it will be created with the given name. You can also set the API KEY, API URL, and the Workspace name. You can learn more about the variables that controls Argilla initialization [here](https://docs.argilla.io/en/latest/getting_started/installation/configurations/workspace_management.html)." + ] + }, { "cell_type": "code", "execution_count": 4, From 62dff507fe4beaa1d1098aaa24349eab80de2874 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 9 Apr 2024 16:52:20 +0200 Subject: [PATCH 16/24] helpers.py added --- src/argilla_llama_index/helpers.py | 43 +++++++++++++++++++ .../llama_index_handler.py | 40 +---------------- tests/test_llama_index_callback.py | 41 +----------------- 3 files changed, 46 insertions(+), 78 deletions(-) create mode 100644 src/argilla_llama_index/helpers.py diff --git a/src/argilla_llama_index/helpers.py b/src/argilla_llama_index/helpers.py new file mode 100644 index 0000000..8b57db0 --- /dev/null +++ b/src/argilla_llama_index/helpers.py @@ -0,0 +1,43 @@ +""" +Auxiliary methods for the Argilla Llama Index integration. +""" + +from datetime import datetime +from typing import Dict, List + +from llama_index.core.callbacks.schema import CBEvent + +def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: + """ + Get the time difference between two events Follows the American format (month, day, year). + + Args: + event_1_time_str (str): The first event time. + event_2_time_str (str): The second event time. + + Returns: + float: The time difference between the two events. + """ + time_format = "%m/%d/%Y, %H:%M:%S.%f" + + event_1_time = datetime.strptime(event_1_time_str, time_format) + event_2_time = datetime.strptime(event_2_time_str, time_format) + + return round((event_2_time - event_1_time).total_seconds(), 4) + + +def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: + """ + Calculate the time difference between the start and end of an event using the events_data. + + Args: + events_data (Dict[str, List[CBEvent]]): The events data, stored in a dictionary. + id (str): The event id to calculate the time difference between start and finish timestamps. + + Returns: + float: The time difference between the start and end of the event. + """ + + start_time = events_data[id][0].time + end_time = events_data[id][1].time + return _get_time_diff(start_time, end_time) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index 93edc10..e2ad317 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -5,11 +5,12 @@ from typing import Any, Dict, List, Optional import warnings +from argilla_llama_index.helpers import _calc_time, _get_time_diff + import argilla as rg from argilla._constants import DEFAULT_API_KEY, DEFAULT_API_URL from llama_index.core.callbacks.base_handler import BaseCallbackHandler from llama_index.core.callbacks.schema import ( - BASE_TRACE_EVENT, CBEventType, EventPayload, CBEvent, @@ -669,40 +670,3 @@ def on_event_end( event = CBEvent(event_type, payload=payload, id_=event_id) self.events_data[event_id].append(event) - - -# Auxiliary methods -def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: - """ - Get the time difference between two events Follows the American format (month, day, year). - - Args: - event_1_time_str (str): The first event time. - event_2_time_str (str): The second event time. - - Returns: - float: The time difference between the two events. - """ - time_format = "%m/%d/%Y, %H:%M:%S.%f" - - event_1_time = datetime.strptime(event_1_time_str, time_format) - event_2_time = datetime.strptime(event_2_time_str, time_format) - - return round((event_2_time - event_1_time).total_seconds(), 4) - - -def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: - """ - Calculate the time difference between the start and end of an event using the events_data. - - Args: - events_data (Dict[str, List[CBEvent]]): The events data, stored in a dictionary. - id (str): The event id to calculate the time difference between start and finish timestamps. - - Returns: - float: The time difference between the start and end of the event. - """ - - start_time = events_data[id][0].time - end_time = events_data[id][1].time - return _get_time_diff(start_time, end_time) diff --git a/tests/test_llama_index_callback.py b/tests/test_llama_index_callback.py index 1788c14..d711e2b 100644 --- a/tests/test_llama_index_callback.py +++ b/tests/test_llama_index_callback.py @@ -1,47 +1,8 @@ -from datetime import datetime -from typing import Dict, List +from argilla_llama_index.helpers import _calc_time, _get_time_diff import unittest from unittest.mock import patch, MagicMock from argilla_llama_index import ArgillaCallbackHandler -from llama_index.core.callbacks.schema import CBEvent - - -# Auxiliary methods -def _get_time_diff(event_1_time_str: str, event_2_time_str: str) -> float: - """ - Get the time difference between two events Follows the American format (month, day, year). - - Args: - event_1_time_str (str): The first event time. - event_2_time_str (str): The second event time. - - Returns: - float: The time difference between the two events. - """ - time_format = "%m/%d/%Y, %H:%M:%S.%f" - - event_1_time = datetime.strptime(event_1_time_str, time_format) - event_2_time = datetime.strptime(event_2_time_str, time_format) - - return round((event_2_time - event_1_time).total_seconds(), 4) - - -def _calc_time(events_data: Dict[str, List[CBEvent]], id: str) -> float: - """ - Calculate the time difference between the start and end of an event using the events_data. - - Args: - events_data (Dict[str, List[CBEvent]]): The events data, stored in a dictionary. - id (str): The event id to calculate the time difference between start and finish timestamps. - - Returns: - float: The time difference between the start and end of the event. - """ - - start_time = events_data[id][0].time - end_time = events_data[id][1].time - return _get_time_diff(start_time, end_time) class TestArgillaCallbackHandler(unittest.TestCase): From 4df38626778b06582f818762b9bdf8caf7a10d86 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Mon, 15 Apr 2024 12:28:52 +0200 Subject: [PATCH 17/24] remove pointless comment --- src/argilla_llama_index/llama_index_handler.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index e2ad317..de28a28 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -44,7 +44,6 @@ def __init__( self.handlers = handlers or [] self.number_of_retrievals = number_of_retrievals - # Import Argilla try: import argilla as rg From 26bf85bc6ff832ce73d49d0629d5d44f62039a2b Mon Sep 17 00:00:00 2001 From: ignacioct Date: Mon, 15 Apr 2024 12:31:26 +0200 Subject: [PATCH 18/24] example txt was duplicated --- docs/data/paul_graham_essay.txt | 353 ------------------------------ docs/examples/usage_example.ipynb | 2 +- 2 files changed, 1 insertion(+), 354 deletions(-) delete mode 100644 docs/data/paul_graham_essay.txt diff --git a/docs/data/paul_graham_essay.txt b/docs/data/paul_graham_essay.txt deleted file mode 100644 index 7f0350d..0000000 --- a/docs/data/paul_graham_essay.txt +++ /dev/null @@ -1,353 +0,0 @@ - - -What I Worked On - -February 2021 - -Before college the two main things I worked on, outside of school, were writing and programming. I didn't write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep. - -The first programs I tried writing were on the IBM 1401 that our school district used for what was then called "data processing." This was in 9th grade, so I was 13 or 14. The school district's 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain's lair down there, with all these alien-looking machines โ€” CPU, disk drives, printer, card reader โ€” sitting up on a raised floor under bright fluorescent lights. - -The language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer. - -I was puzzled by the 1401. I couldn't figure out what to do with it. And in retrospect there's not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn't have any data stored on punched cards. The only other option was to do things that didn't rely on any input, like calculate approximations of pi, but I didn't know enough math to do anything interesting of that type. So I'm not surprised I can't remember any programs I wrote, because they can't have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn't. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager's expression made clear. - -With microcomputers, everything changed. Now you could have a computer sitting right in front of you, on a desk, that could respond to your keystrokes as it was running instead of just churning through a stack of punch cards and then stopping. [1] - -The first of my friends to get a microcomputer built it himself. It was sold as a kit by Heathkit. I remember vividly how impressed and envious I felt watching him sitting in front of it, typing programs right into the computer. - -Computers were expensive in those days and it took me years of nagging before I convinced my father to buy one, a TRS-80, in about 1980. The gold standard then was the Apple II, but a TRS-80 was good enough. This was when I really started programming. I wrote simple games, a program to predict how high my model rockets would fly, and a word processor that my father used to write at least one book. There was only room in memory for about 2 pages of text, so he'd write 2 pages at a time and then print them out, but it was a lot better than a typewriter. - -Though I liked programming, I didn't plan to study it in college. In college I was going to study philosophy, which sounded much more powerful. It seemed, to my naive high school self, to be the study of the ultimate truths, compared to which the things studied in other fields would be mere domain knowledge. What I discovered when I got to college was that the other fields took up so much of the space of ideas that there wasn't much left for these supposed ultimate truths. All that seemed left for philosophy were edge cases that people in other fields felt could safely be ignored. - -I couldn't have put this into words when I was 18. All I knew at the time was that I kept taking philosophy courses and they kept being boring. So I decided to switch to AI. - -AI was in the air in the mid 1980s, but there were two things especially that made me want to work on it: a novel by Heinlein called The Moon is a Harsh Mistress, which featured an intelligent computer called Mike, and a PBS documentary that showed Terry Winograd using SHRDLU. I haven't tried rereading The Moon is a Harsh Mistress, so I don't know how well it has aged, but when I read it I was drawn entirely into its world. It seemed only a matter of time before we'd have Mike, and when I saw Winograd using SHRDLU, it seemed like that time would be a few years at most. All you had to do was teach SHRDLU more words. - -There weren't any classes in AI at Cornell then, not even graduate classes, so I started trying to teach myself. Which meant learning Lisp, since in those days Lisp was regarded as the language of AI. The commonly used programming languages then were pretty primitive, and programmers' ideas correspondingly so. The default language at Cornell was a Pascal-like language called PL/I, and the situation was similar elsewhere. Learning Lisp expanded my concept of a program so fast that it was years before I started to have a sense of where the new limits were. This was more like it; this was what I had expected college to do. It wasn't happening in a class, like it was supposed to, but that was ok. For the next couple years I was on a roll. I knew what I was going to do. - -For my undergraduate thesis, I reverse-engineered SHRDLU. My God did I love working on that program. It was a pleasing bit of code, but what made it even more exciting was my belief โ€” hard to imagine now, but not unique in 1985 โ€” that it was already climbing the lower slopes of intelligence. - -I had gotten into a program at Cornell that didn't make you choose a major. You could take whatever classes you liked, and choose whatever you liked to put on your degree. I of course chose "Artificial Intelligence." When I got the actual physical diploma, I was dismayed to find that the quotes had been included, which made them read as scare-quotes. At the time this bothered me, but now it seems amusingly accurate, for reasons I was about to discover. - -I applied to 3 grad schools: MIT and Yale, which were renowned for AI at the time, and Harvard, which I'd visited because Rich Draves went there, and was also home to Bill Woods, who'd invented the type of parser I used in my SHRDLU clone. Only Harvard accepted me, so that was where I went. - -I don't remember the moment it happened, or if there even was a specific moment, but during the first year of grad school I realized that AI, as practiced at the time, was a hoax. By which I mean the sort of AI in which a program that's told "the dog is sitting on the chair" translates this into some formal representation and adds it to the list of things it knows. - -What these programs really showed was that there's a subset of natural language that's a formal language. But a very proper subset. It was clear that there was an unbridgeable gap between what they could do and actually understanding natural language. It was not, in fact, simply a matter of teaching SHRDLU more words. That whole way of doing AI, with explicit data structures representing concepts, was not going to work. Its brokenness did, as so often happens, generate a lot of opportunities to write papers about various band-aids that could be applied to it, but it was never going to get us Mike. - -So I looked around to see what I could salvage from the wreckage of my plans, and there was Lisp. I knew from experience that Lisp was interesting for its own sake and not just for its association with AI, even though that was the main reason people cared about it at the time. So I decided to focus on Lisp. In fact, I decided to write a book about Lisp hacking. It's scary to think how little I knew about Lisp hacking when I started writing that book. But there's nothing like writing a book about something to help you learn it. The book, On Lisp, wasn't published till 1993, but I wrote much of it in grad school. - -Computer Science is an uneasy alliance between two halves, theory and systems. The theory people prove things, and the systems people build things. I wanted to build things. I had plenty of respect for theory โ€” indeed, a sneaking suspicion that it was the more admirable of the two halves โ€” but building things seemed so much more exciting. - -The problem with systems work, though, was that it didn't last. Any program you wrote today, no matter how good, would be obsolete in a couple decades at best. People might mention your software in footnotes, but no one would actually use it. And indeed, it would seem very feeble work. Only people with a sense of the history of the field would even realize that, in its time, it had been good. - -There were some surplus Xerox Dandelions floating around the computer lab at one point. Anyone who wanted one to play around with could have one. I was briefly tempted, but they were so slow by present standards; what was the point? No one else wanted one either, so off they went. That was what happened to systems work. - -I wanted not just to build things, but to build things that would last. - -In this dissatisfied state I went in 1988 to visit Rich Draves at CMU, where he was in grad school. One day I went to visit the Carnegie Institute, where I'd spent a lot of time as a kid. While looking at a painting there I realized something that might seem obvious, but was a big surprise to me. There, right on the wall, was something you could make that would last. Paintings didn't become obsolete. Some of the best ones were hundreds of years old. - -And moreover this was something you could make a living doing. Not as easily as you could by writing software, of course, but I thought if you were really industrious and lived really cheaply, it had to be possible to make enough to survive. And as an artist you could be truly independent. You wouldn't have a boss, or even need to get research funding. - -I had always liked looking at paintings. Could I make them? I had no idea. I'd never imagined it was even possible. I knew intellectually that people made art โ€” that it didn't just appear spontaneously โ€” but it was as if the people who made it were a different species. They either lived long ago or were mysterious geniuses doing strange things in profiles in Life magazine. The idea of actually being able to make art, to put that verb before that noun, seemed almost miraculous. - -That fall I started taking art classes at Harvard. Grad students could take classes in any department, and my advisor, Tom Cheatham, was very easy going. If he even knew about the strange classes I was taking, he never said anything. - -So now I was in a PhD program in computer science, yet planning to be an artist, yet also genuinely in love with Lisp hacking and working away at On Lisp. In other words, like many a grad student, I was working energetically on multiple projects that were not my thesis. - -I didn't see a way out of this situation. I didn't want to drop out of grad school, but how else was I going to get out? I remember when my friend Robert Morris got kicked out of Cornell for writing the internet worm of 1988, I was envious that he'd found such a spectacular way to get out of grad school. - -Then one day in April 1990 a crack appeared in the wall. I ran into professor Cheatham and he asked if I was far enough along to graduate that June. I didn't have a word of my dissertation written, but in what must have been the quickest bit of thinking in my life, I decided to take a shot at writing one in the 5 weeks or so that remained before the deadline, reusing parts of On Lisp where I could, and I was able to respond, with no perceptible delay "Yes, I think so. I'll give you something to read in a few days." - -I picked applications of continuations as the topic. In retrospect I should have written about macros and embedded languages. There's a whole world there that's barely been explored. But all I wanted was to get out of grad school, and my rapidly written dissertation sufficed, just barely. - -Meanwhile I was applying to art schools. I applied to two: RISD in the US, and the Accademia di Belli Arti in Florence, which, because it was the oldest art school, I imagined would be good. RISD accepted me, and I never heard back from the Accademia, so off to Providence I went. - -I'd applied for the BFA program at RISD, which meant in effect that I had to go to college again. This was not as strange as it sounds, because I was only 25, and art schools are full of people of different ages. RISD counted me as a transfer sophomore and said I had to do the foundation that summer. The foundation means the classes that everyone has to take in fundamental subjects like drawing, color, and design. - -Toward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they'd sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I'd done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian. - -Only stranieri (foreigners) had to take this entrance exam. In retrospect it may well have been a way of excluding them, because there were so many stranieri attracted by the idea of studying art in Florence that the Italian students would otherwise have been outnumbered. I was in decent shape at painting and drawing from the RISD foundation that summer, but I still don't know how I managed to pass the written exam. I remember that I answered the essay question by writing about Cezanne, and that I cranked up the intellectual level as high as I could to make the most of my limited vocabulary. [2] - -I'm only up to age 25 and already there are such conspicuous patterns. Here I was, yet again about to attend some august institution in the hopes of learning about some prestigious subject, and yet again about to be disappointed. The students and faculty in the painting department at the Accademia were the nicest people you could imagine, but they had long since arrived at an arrangement whereby the students wouldn't require the faculty to teach anything, and in return the faculty wouldn't require the students to learn anything. And at the same time all involved would adhere outwardly to the conventions of a 19th century atelier. We actually had one of those little stoves, fed with kindling, that you see in 19th century studio paintings, and a nude model sitting as close to it as possible without getting burned. Except hardly anyone else painted her besides me. The rest of the students spent their time chatting or occasionally trying to imitate things they'd seen in American art magazines. - -Our model turned out to live just down the street from me. She made a living from a combination of modelling and making fakes for a local antique dealer. She'd copy an obscure old painting out of a book, and then he'd take the copy and maltreat it to make it look old. [3] - -While I was a student at the Accademia I started painting still lives in my bedroom at night. These paintings were tiny, because the room was, and because I painted them on leftover scraps of canvas, which was all I could afford at the time. Painting still lives is different from painting people, because the subject, as its name suggests, can't move. People can't sit for more than about 15 minutes at a time, and when they do they don't sit very still. So the traditional m.o. for painting people is to know how to paint a generic person, which you then modify to match the specific person you're painting. Whereas a still life you can, if you want, copy pixel by pixel from what you're seeing. You don't want to stop there, of course, or you get merely photographic accuracy, and what makes a still life interesting is that it's been through a head. You want to emphasize the visual cues that tell you, for example, that the reason the color changes suddenly at a certain point is that it's the edge of an object. By subtly emphasizing such things you can make paintings that are more realistic than photographs not just in some metaphorical sense, but in the strict information-theoretic sense. [4] - -I liked painting still lives because I was curious about what I was seeing. In everyday life, we aren't consciously aware of much we're seeing. Most visual perception is handled by low-level processes that merely tell your brain "that's a water droplet" without telling you details like where the lightest and darkest points are, or "that's a bush" without telling you the shape and position of every leaf. This is a feature of brains, not a bug. In everyday life it would be distracting to notice every leaf on every bush. But when you have to paint something, you have to look more closely, and when you do there's a lot to see. You can still be noticing new things after days of trying to paint something people usually take for granted, just as you can after days of trying to write an essay about something people usually take for granted. - -This is not the only way to paint. I'm not 100% sure it's even a good way to paint. But it seemed a good enough bet to be worth trying. - -Our teacher, professor Ulivi, was a nice guy. He could see I worked hard, and gave me a good grade, which he wrote down in a sort of passport each student had. But the Accademia wasn't teaching me anything except Italian, and my money was running out, so at the end of the first year I went back to the US. - -I wanted to go back to RISD, but I was now broke and RISD was very expensive, so I decided to get a job for a year and then return to RISD the next fall. I got one at a company called Interleaf, which made software for creating documents. You mean like Microsoft Word? Exactly. That was how I learned that low end software tends to eat high end software. But Interleaf still had a few years to live yet. [5] - -Interleaf had done something pretty bold. Inspired by Emacs, they'd added a scripting language, and even made the scripting language a dialect of Lisp. Now they wanted a Lisp hacker to write things in it. This was the closest thing I've had to a normal job, and I hereby apologize to my boss and coworkers, because I was a bad employee. Their Lisp was the thinnest icing on a giant C cake, and since I didn't know C and didn't want to learn it, I never understood most of the software. Plus I was terribly irresponsible. This was back when a programming job meant showing up every day during certain working hours. That seemed unnatural to me, and on this point the rest of the world is coming around to my way of thinking, but at the time it caused a lot of friction. Toward the end of the year I spent much of my time surreptitiously working on On Lisp, which I had by this time gotten a contract to publish. - -The good part was that I got paid huge amounts of money, especially by art student standards. In Florence, after paying my part of the rent, my budget for everything else had been $7 a day. Now I was getting paid more than 4 times that every hour, even when I was just sitting in a meeting. By living cheaply I not only managed to save enough to go back to RISD, but also paid off my college loans. - -I learned some useful things at Interleaf, though they were mostly about what not to do. I learned that it's better for technology companies to be run by product people than sales people (though sales is a real skill and people who are good at it are really good at it), that it leads to bugs when code is edited by too many people, that cheap office space is no bargain if it's depressing, that planned meetings are inferior to corridor conversations, that big, bureaucratic customers are a dangerous source of money, and that there's not much overlap between conventional office hours and the optimal time for hacking, or conventional offices and the optimal place for it. - -But the most important thing I learned, and which I used in both Viaweb and Y Combinator, is that the low end eats the high end: that it's good to be the "entry level" option, even though that will be less prestigious, because if you're not, someone else will be, and will squash you against the ceiling. Which in turn means that prestige is a danger sign. - -When I left to go back to RISD the next fall, I arranged to do freelance work for the group that did projects for customers, and this was how I survived for the next several years. When I came back to visit for a project later on, someone told me about a new thing called HTML, which was, as he described it, a derivative of SGML. Markup language enthusiasts were an occupational hazard at Interleaf and I ignored him, but this HTML thing later became a big part of my life. - -In the fall of 1992 I moved back to Providence to continue at RISD. The foundation had merely been intro stuff, and the Accademia had been a (very civilized) joke. Now I was going to see what real art school was like. But alas it was more like the Accademia than not. Better organized, certainly, and a lot more expensive, but it was now becoming clear that art school did not bear the same relationship to art that medical school bore to medicine. At least not the painting department. The textile department, which my next door neighbor belonged to, seemed to be pretty rigorous. No doubt illustration and architecture were too. But painting was post-rigorous. Painting students were supposed to express themselves, which to the more worldly ones meant to try to cook up some sort of distinctive signature style. - -A signature style is the visual equivalent of what in show business is known as a "schtick": something that immediately identifies the work as yours and no one else's. For example, when you see a painting that looks like a certain kind of cartoon, you know it's by Roy Lichtenstein. So if you see a big painting of this type hanging in the apartment of a hedge fund manager, you know he paid millions of dollars for it. That's not always why artists have a signature style, but it's usually why buyers pay a lot for such work. [6] - -There were plenty of earnest students too: kids who "could draw" in high school, and now had come to what was supposed to be the best art school in the country, to learn to draw even better. They tended to be confused and demoralized by what they found at RISD, but they kept going, because painting was what they did. I was not one of the kids who could draw in high school, but at RISD I was definitely closer to their tribe than the tribe of signature style seekers. - -I learned a lot in the color class I took at RISD, but otherwise I was basically teaching myself to paint, and I could do that for free. So in 1993 I dropped out. I hung around Providence for a bit, and then my college friend Nancy Parmet did me a big favor. A rent-controlled apartment in a building her mother owned in New York was becoming vacant. Did I want it? It wasn't much more than my current place, and New York was supposed to be where the artists were. So yes, I wanted it! [7] - -Asterix comics begin by zooming in on a tiny corner of Roman Gaul that turns out not to be controlled by the Romans. You can do something similar on a map of New York City: if you zoom in on the Upper East Side, there's a tiny corner that's not rich, or at least wasn't in 1993. It's called Yorkville, and that was my new home. Now I was a New York artist โ€” in the strictly technical sense of making paintings and living in New York. - -I was nervous about money, because I could sense that Interleaf was on the way down. Freelance Lisp hacking work was very rare, and I didn't want to have to program in another language, which in those days would have meant C++ if I was lucky. So with my unerring nose for financial opportunity, I decided to write another book on Lisp. This would be a popular book, the sort of book that could be used as a textbook. I imagined myself living frugally off the royalties and spending all my time painting. (The painting on the cover of this book, ANSI Common Lisp, is one that I painted around this time.) - -The best thing about New York for me was the presence of Idelle and Julian Weber. Idelle Weber was a painter, one of the early photorealists, and I'd taken her painting class at Harvard. I've never known a teacher more beloved by her students. Large numbers of former students kept in touch with her, including me. After I moved to New York I became her de facto studio assistant. - -She liked to paint on big, square canvases, 4 to 5 feet on a side. One day in late 1994 as I was stretching one of these monsters there was something on the radio about a famous fund manager. He wasn't that much older than me, and was super rich. The thought suddenly occurred to me: why don't I become rich? Then I'll be able to work on whatever I want. - -Meanwhile I'd been hearing more and more about this new thing called the World Wide Web. Robert Morris showed it to me when I visited him in Cambridge, where he was now in grad school at Harvard. It seemed to me that the web would be a big deal. I'd seen what graphical user interfaces had done for the popularity of microcomputers. It seemed like the web would do the same for the internet. - -If I wanted to get rich, here was the next train leaving the station. I was right about that part. What I got wrong was the idea. I decided we should start a company to put art galleries online. I can't honestly say, after reading so many Y Combinator applications, that this was the worst startup idea ever, but it was up there. Art galleries didn't want to be online, and still don't, not the fancy ones. That's not how they sell. I wrote some software to generate web sites for galleries, and Robert wrote some to resize images and set up an http server to serve the pages. Then we tried to sign up galleries. To call this a difficult sale would be an understatement. It was difficult to give away. A few galleries let us make sites for them for free, but none paid us. - -Then some online stores started to appear, and I realized that except for the order buttons they were identical to the sites we'd been generating for galleries. This impressive-sounding thing called an "internet storefront" was something we already knew how to build. - -So in the summer of 1995, after I submitted the camera-ready copy of ANSI Common Lisp to the publishers, we started trying to write software to build online stores. At first this was going to be normal desktop software, which in those days meant Windows software. That was an alarming prospect, because neither of us knew how to write Windows software or wanted to learn. We lived in the Unix world. But we decided we'd at least try writing a prototype store builder on Unix. Robert wrote a shopping cart, and I wrote a new site generator for stores โ€” in Lisp, of course. - -We were working out of Robert's apartment in Cambridge. His roommate was away for big chunks of time, during which I got to sleep in his room. For some reason there was no bed frame or sheets, just a mattress on the floor. One morning as I was lying on this mattress I had an idea that made me sit up like a capital L. What if we ran the software on the server, and let users control it by clicking on links? Then we'd never have to write anything to run on users' computers. We could generate the sites on the same server we'd serve them from. Users wouldn't need anything more than a browser. - -This kind of software, known as a web app, is common now, but at the time it wasn't clear that it was even possible. To find out, we decided to try making a version of our store builder that you could control through the browser. A couple days later, on August 12, we had one that worked. The UI was horrible, but it proved you could build a whole store through the browser, without any client software or typing anything into the command line on the server. - -Now we felt like we were really onto something. I had visions of a whole new generation of software working this way. You wouldn't need versions, or ports, or any of that crap. At Interleaf there had been a whole group called Release Engineering that seemed to be at least as big as the group that actually wrote the software. Now you could just update the software right on the server. - -We started a new company we called Viaweb, after the fact that our software worked via the web, and we got $10,000 in seed funding from Idelle's husband Julian. In return for that and doing the initial legal work and giving us business advice, we gave him 10% of the company. Ten years later this deal became the model for Y Combinator's. We knew founders needed something like this, because we'd needed it ourselves. - -At this stage I had a negative net worth, because the thousand dollars or so I had in the bank was more than counterbalanced by what I owed the government in taxes. (Had I diligently set aside the proper proportion of the money I'd made consulting for Interleaf? No, I had not.) So although Robert had his graduate student stipend, I needed that seed funding to live on. - -We originally hoped to launch in September, but we got more ambitious about the software as we worked on it. Eventually we managed to build a WYSIWYG site builder, in the sense that as you were creating pages, they looked exactly like the static ones that would be generated later, except that instead of leading to static pages, the links all referred to closures stored in a hash table on the server. - -It helped to have studied art, because the main goal of an online store builder is to make users look legit, and the key to looking legit is high production values. If you get page layouts and fonts and colors right, you can make a guy running a store out of his bedroom look more legit than a big company. - -(If you're curious why my site looks so old-fashioned, it's because it's still made with this software. It may look clunky today, but in 1996 it was the last word in slick.) - -In September, Robert rebelled. "We've been working on this for a month," he said, "and it's still not done." This is funny in retrospect, because he would still be working on it almost 3 years later. But I decided it might be prudent to recruit more programmers, and I asked Robert who else in grad school with him was really good. He recommended Trevor Blackwell, which surprised me at first, because at that point I knew Trevor mainly for his plan to reduce everything in his life to a stack of notecards, which he carried around with him. But Rtm was right, as usual. Trevor turned out to be a frighteningly effective hacker. - -It was a lot of fun working with Robert and Trevor. They're the two most independent-minded people I know, and in completely different ways. If you could see inside Rtm's brain it would look like a colonial New England church, and if you could see inside Trevor's it would look like the worst excesses of Austrian Rococo. - -We opened for business, with 6 stores, in January 1996. It was just as well we waited a few months, because although we worried we were late, we were actually almost fatally early. There was a lot of talk in the press then about ecommerce, but not many people actually wanted online stores. [8] - -There were three main parts to the software: the editor, which people used to build sites and which I wrote, the shopping cart, which Robert wrote, and the manager, which kept track of orders and statistics, and which Trevor wrote. In its time, the editor was one of the best general-purpose site builders. I kept the code tight and didn't have to integrate with any other software except Robert's and Trevor's, so it was quite fun to work on. If all I'd had to do was work on this software, the next 3 years would have been the easiest of my life. Unfortunately I had to do a lot more, all of it stuff I was worse at than programming, and the next 3 years were instead the most stressful. - -There were a lot of startups making ecommerce software in the second half of the 90s. We were determined to be the Microsoft Word, not the Interleaf. Which meant being easy to use and inexpensive. It was lucky for us that we were poor, because that caused us to make Viaweb even more inexpensive than we realized. We charged $100 a month for a small store and $300 a month for a big one. This low price was a big attraction, and a constant thorn in the sides of competitors, but it wasn't because of some clever insight that we set the price low. We had no idea what businesses paid for things. $300 a month seemed like a lot of money to us. - -We did a lot of things right by accident like that. For example, we did what's now called "doing things that don't scale," although at the time we would have described it as "being so lame that we're driven to the most desperate measures to get users." The most common of which was building stores for them. This seemed particularly humiliating, since the whole raison d'etre of our software was that people could use it to make their own stores. But anything to get users. - -We learned a lot more about retail than we wanted to know. For example, that if you could only have a small image of a man's shirt (and all images were small then by present standards), it was better to have a closeup of the collar than a picture of the whole shirt. The reason I remember learning this was that it meant I had to rescan about 30 images of men's shirts. My first set of scans were so beautiful too. - -Though this felt wrong, it was exactly the right thing to be doing. Building stores for users taught us about retail, and about how it felt to use our software. I was initially both mystified and repelled by "business" and thought we needed a "business person" to be in charge of it, but once we started to get users, I was converted, in much the same way I was converted to fatherhood once I had kids. Whatever users wanted, I was all theirs. Maybe one day we'd have so many users that I couldn't scan their images for them, but in the meantime there was nothing more important to do. - -Another thing I didn't get at the time is that growth rate is the ultimate test of a startup. Our growth rate was fine. We had about 70 stores at the end of 1996 and about 500 at the end of 1997. I mistakenly thought the thing that mattered was the absolute number of users. And that is the thing that matters in the sense that that's how much money you're making, and if you're not making enough, you might go out of business. But in the long term the growth rate takes care of the absolute number. If we'd been a startup I was advising at Y Combinator, I would have said: Stop being so stressed out, because you're doing fine. You're growing 7x a year. Just don't hire too many more people and you'll soon be profitable, and then you'll control your own destiny. - -Alas I hired lots more people, partly because our investors wanted me to, and partly because that's what startups did during the Internet Bubble. A company with just a handful of employees would have seemed amateurish. So we didn't reach breakeven until about when Yahoo bought us in the summer of 1998. Which in turn meant we were at the mercy of investors for the entire life of the company. And since both we and our investors were noobs at startups, the result was a mess even by startup standards. - -It was a huge relief when Yahoo bought us. In principle our Viaweb stock was valuable. It was a share in a business that was profitable and growing rapidly. But it didn't feel very valuable to me; I had no idea how to value a business, but I was all too keenly aware of the near-death experiences we seemed to have every few months. Nor had I changed my grad student lifestyle significantly since we started. So when Yahoo bought us it felt like going from rags to riches. Since we were going to California, I bought a car, a yellow 1998 VW GTI. I remember thinking that its leather seats alone were by far the most luxurious thing I owned. - -The next year, from the summer of 1998 to the summer of 1999, must have been the least productive of my life. I didn't realize it at the time, but I was worn out from the effort and stress of running Viaweb. For a while after I got to California I tried to continue my usual m.o. of programming till 3 in the morning, but fatigue combined with Yahoo's prematurely aged culture and grim cube farm in Santa Clara gradually dragged me down. After a few months it felt disconcertingly like working at Interleaf. - -Yahoo had given us a lot of options when they bought us. At the time I thought Yahoo was so overvalued that they'd never be worth anything, but to my astonishment the stock went up 5x in the next year. I hung on till the first chunk of options vested, then in the summer of 1999 I left. It had been so long since I'd painted anything that I'd half forgotten why I was doing this. My brain had been entirely full of software and men's shirts for 4 years. But I had done this to get rich so I could paint, I reminded myself, and now I was rich, so I should go paint. - -When I said I was leaving, my boss at Yahoo had a long conversation with me about my plans. I told him all about the kinds of pictures I wanted to paint. At the time I was touched that he took such an interest in me. Now I realize it was because he thought I was lying. My options at that point were worth about $2 million a month. If I was leaving that kind of money on the table, it could only be to go and start some new startup, and if I did, I might take people with me. This was the height of the Internet Bubble, and Yahoo was ground zero of it. My boss was at that moment a billionaire. Leaving then to start a new startup must have seemed to him an insanely, and yet also plausibly, ambitious plan. - -But I really was quitting to paint, and I started immediately. There was no time to lose. I'd already burned 4 years getting rich. Now when I talk to founders who are leaving after selling their companies, my advice is always the same: take a vacation. That's what I should have done, just gone off somewhere and done nothing for a month or two, but the idea never occurred to me. - -So I tried to paint, but I just didn't seem to have any energy or ambition. Part of the problem was that I didn't know many people in California. I'd compounded this problem by buying a house up in the Santa Cruz Mountains, with a beautiful view but miles from anywhere. I stuck it out for a few more months, then in desperation I went back to New York, where unless you understand about rent control you'll be surprised to hear I still had my apartment, sealed up like a tomb of my old life. Idelle was in New York at least, and there were other people trying to paint there, even though I didn't know any of them. - -When I got back to New York I resumed my old life, except now I was rich. It was as weird as it sounds. I resumed all my old patterns, except now there were doors where there hadn't been. Now when I was tired of walking, all I had to do was raise my hand, and (unless it was raining) a taxi would stop to pick me up. Now when I walked past charming little restaurants I could go in and order lunch. It was exciting for a while. Painting started to go better. I experimented with a new kind of still life where I'd paint one painting in the old way, then photograph it and print it, blown up, on canvas, and then use that as the underpainting for a second still life, painted from the same objects (which hopefully hadn't rotted yet). - -Meanwhile I looked for an apartment to buy. Now I could actually choose what neighborhood to live in. Where, I asked myself and various real estate agents, is the Cambridge of New York? Aided by occasional visits to actual Cambridge, I gradually realized there wasn't one. Huh. - -Around this time, in the spring of 2000, I had an idea. It was clear from our experience with Viaweb that web apps were the future. Why not build a web app for making web apps? Why not let people edit code on our server through the browser, and then host the resulting applications for them? [9] You could run all sorts of services on the servers that these applications could use just by making an API call: making and receiving phone calls, manipulating images, taking credit card payments, etc. - -I got so excited about this idea that I couldn't think about anything else. It seemed obvious that this was the future. I didn't particularly want to start another company, but it was clear that this idea would have to be embodied as one, so I decided to move to Cambridge and start it. I hoped to lure Robert into working on it with me, but there I ran into a hitch. Robert was now a postdoc at MIT, and though he'd made a lot of money the last time I'd lured him into working on one of my schemes, it had also been a huge time sink. So while he agreed that it sounded like a plausible idea, he firmly refused to work on it. - -Hmph. Well, I'd do it myself then. I recruited Dan Giffin, who had worked for Viaweb, and two undergrads who wanted summer jobs, and we got to work trying to build what it's now clear is about twenty companies and several open source projects worth of software. The language for defining applications would of course be a dialect of Lisp. But I wasn't so naive as to assume I could spring an overt Lisp on a general audience; we'd hide the parentheses, like Dylan did. - -By then there was a name for the kind of company Viaweb was, an "application service provider," or ASP. This name didn't last long before it was replaced by "software as a service," but it was current for long enough that I named this new company after it: it was going to be called Aspra. - -I started working on the application builder, Dan worked on network infrastructure, and the two undergrads worked on the first two services (images and phone calls). But about halfway through the summer I realized I really didn't want to run a company โ€” especially not a big one, which it was looking like this would have to be. I'd only started Viaweb because I needed the money. Now that I didn't need money anymore, why was I doing this? If this vision had to be realized as a company, then screw the vision. I'd build a subset that could be done as an open source project. - -Much to my surprise, the time I spent working on this stuff was not wasted after all. After we started Y Combinator, I would often encounter startups working on parts of this new architecture, and it was very useful to have spent so much time thinking about it and even trying to write some of it. - -The subset I would build as an open source project was the new Lisp, whose parentheses I now wouldn't even have to hide. A lot of Lisp hackers dream of building a new Lisp, partly because one of the distinctive features of the language is that it has dialects, and partly, I think, because we have in our minds a Platonic form of Lisp that all existing dialects fall short of. I certainly did. So at the end of the summer Dan and I switched to working on this new dialect of Lisp, which I called Arc, in a house I bought in Cambridge. - -The following spring, lightning struck. I was invited to give a talk at a Lisp conference, so I gave one about how we'd used Lisp at Viaweb. Afterward I put a postscript file of this talk online, on paulgraham.com, which I'd created years before using Viaweb but had never used for anything. In one day it got 30,000 page views. What on earth had happened? The referring urls showed that someone had posted it on Slashdot. [10] - -Wow, I thought, there's an audience. If I write something and put it on the web, anyone can read it. That may seem obvious now, but it was surprising then. In the print era there was a narrow channel to readers, guarded by fierce monsters known as editors. The only way to get an audience for anything you wrote was to get it published as a book, or in a newspaper or magazine. Now anyone could publish anything. - -This had been possible in principle since 1993, but not many people had realized it yet. I had been intimately involved with building the infrastructure of the web for most of that time, and a writer as well, and it had taken me 8 years to realize it. Even then it took me several years to understand the implications. It meant there would be a whole new generation of essays. [11] - -In the print era, the channel for publishing essays had been vanishingly small. Except for a few officially anointed thinkers who went to the right parties in New York, the only people allowed to publish essays were specialists writing about their specialties. There were so many essays that had never been written, because there had been no way to publish them. Now they could be, and I was going to write them. [12] - -I've worked on several different things, but to the extent there was a turning point where I figured out what to work on, it was when I started publishing essays online. From then on I knew that whatever else I did, I'd always write essays too. - -I knew that online essays would be a marginal medium at first. Socially they'd seem more like rants posted by nutjobs on their GeoCities sites than the genteel and beautifully typeset compositions published in The New Yorker. But by this point I knew enough to find that encouraging instead of discouraging. - -One of the most conspicuous patterns I've noticed in my life is how well it has worked, for me at least, to work on things that weren't prestigious. Still life has always been the least prestigious form of painting. Viaweb and Y Combinator both seemed lame when we started them. I still get the glassy eye from strangers when they ask what I'm writing, and I explain that it's an essay I'm going to publish on my web site. Even Lisp, though prestigious intellectually in something like the way Latin is, also seems about as hip. - -It's not that unprestigious types of work are good per se. But when you find yourself drawn to some kind of work despite its current lack of prestige, it's a sign both that there's something real to be discovered there, and that you have the right kind of motives. Impure motives are a big danger for the ambitious. If anything is going to lead you astray, it will be the desire to impress people. So while working on things that aren't prestigious doesn't guarantee you're on the right track, it at least guarantees you're not on the most common type of wrong one. - -Over the next several years I wrote lots of essays about all kinds of different topics. O'Reilly reprinted a collection of them as a book, called Hackers & Painters after one of the essays in it. I also worked on spam filters, and did some more painting. I used to have dinners for a group of friends every thursday night, which taught me how to cook for groups. And I bought another building in Cambridge, a former candy factory (and later, twas said, porn studio), to use as an office. - -One night in October 2003 there was a big party at my house. It was a clever idea of my friend Maria Daniels, who was one of the thursday diners. Three separate hosts would all invite their friends to one party. So for every guest, two thirds of the other guests would be people they didn't know but would probably like. One of the guests was someone I didn't know but would turn out to like a lot: a woman called Jessica Livingston. A couple days later I asked her out. - -Jessica was in charge of marketing at a Boston investment bank. This bank thought it understood startups, but over the next year, as she met friends of mine from the startup world, she was surprised how different reality was. And how colorful their stories were. So she decided to compile a book of interviews with startup founders. - -When the bank had financial problems and she had to fire half her staff, she started looking for a new job. In early 2005 she interviewed for a marketing job at a Boston VC firm. It took them weeks to make up their minds, and during this time I started telling her about all the things that needed to be fixed about venture capital. They should make a larger number of smaller investments instead of a handful of giant ones, they should be funding younger, more technical founders instead of MBAs, they should let the founders remain as CEO, and so on. - -One of my tricks for writing essays had always been to give talks. The prospect of having to stand up in front of a group of people and tell them something that won't waste their time is a great spur to the imagination. When the Harvard Computer Society, the undergrad computer club, asked me to give a talk, I decided I would tell them how to start a startup. Maybe they'd be able to avoid the worst of the mistakes we'd made. - -So I gave this talk, in the course of which I told them that the best sources of seed funding were successful startup founders, because then they'd be sources of advice too. Whereupon it seemed they were all looking expectantly at me. Horrified at the prospect of having my inbox flooded by business plans (if I'd only known), I blurted out "But not me!" and went on with the talk. But afterward it occurred to me that I should really stop procrastinating about angel investing. I'd been meaning to since Yahoo bought us, and now it was 7 years later and I still hadn't done one angel investment. - -Meanwhile I had been scheming with Robert and Trevor about projects we could work on together. I missed working with them, and it seemed like there had to be something we could collaborate on. - -As Jessica and I were walking home from dinner on March 11, at the corner of Garden and Walker streets, these three threads converged. Screw the VCs who were taking so long to make up their minds. We'd start our own investment firm and actually implement the ideas we'd been talking about. I'd fund it, and Jessica could quit her job and work for it, and we'd get Robert and Trevor as partners too. [13] - -Once again, ignorance worked in our favor. We had no idea how to be angel investors, and in Boston in 2005 there were no Ron Conways to learn from. So we just made what seemed like the obvious choices, and some of the things we did turned out to be novel. - -There are multiple components to Y Combinator, and we didn't figure them all out at once. The part we got first was to be an angel firm. In those days, those two words didn't go together. There were VC firms, which were organized companies with people whose job it was to make investments, but they only did big, million dollar investments. And there were angels, who did smaller investments, but these were individuals who were usually focused on other things and made investments on the side. And neither of them helped founders enough in the beginning. We knew how helpless founders were in some respects, because we remembered how helpless we'd been. For example, one thing Julian had done for us that seemed to us like magic was to get us set up as a company. We were fine writing fairly difficult software, but actually getting incorporated, with bylaws and stock and all that stuff, how on earth did you do that? Our plan was not only to make seed investments, but to do for startups everything Julian had done for us. - -YC was not organized as a fund. It was cheap enough to run that we funded it with our own money. That went right by 99% of readers, but professional investors are thinking "Wow, that means they got all the returns." But once again, this was not due to any particular insight on our part. We didn't know how VC firms were organized. It never occurred to us to try to raise a fund, and if it had, we wouldn't have known where to start. [14] - -The most distinctive thing about YC is the batch model: to fund a bunch of startups all at once, twice a year, and then to spend three months focusing intensively on trying to help them. That part we discovered by accident, not merely implicitly but explicitly due to our ignorance about investing. We needed to get experience as investors. What better way, we thought, than to fund a whole bunch of startups at once? We knew undergrads got temporary jobs at tech companies during the summer. Why not organize a summer program where they'd start startups instead? We wouldn't feel guilty for being in a sense fake investors, because they would in a similar sense be fake founders. So while we probably wouldn't make much money out of it, we'd at least get to practice being investors on them, and they for their part would probably have a more interesting summer than they would working at Microsoft. - -We'd use the building I owned in Cambridge as our headquarters. We'd all have dinner there once a week โ€” on tuesdays, since I was already cooking for the thursday diners on thursdays โ€” and after dinner we'd bring in experts on startups to give talks. - -We knew undergrads were deciding then about summer jobs, so in a matter of days we cooked up something we called the Summer Founders Program, and I posted an announcement on my site, inviting undergrads to apply. I had never imagined that writing essays would be a way to get "deal flow," as investors call it, but it turned out to be the perfect source. [15] We got 225 applications for the Summer Founders Program, and we were surprised to find that a lot of them were from people who'd already graduated, or were about to that spring. Already this SFP thing was starting to feel more serious than we'd intended. - -We invited about 20 of the 225 groups to interview in person, and from those we picked 8 to fund. They were an impressive group. That first batch included reddit, Justin Kan and Emmett Shear, who went on to found Twitch, Aaron Swartz, who had already helped write the RSS spec and would a few years later become a martyr for open access, and Sam Altman, who would later become the second president of YC. I don't think it was entirely luck that the first batch was so good. You had to be pretty bold to sign up for a weird thing like the Summer Founders Program instead of a summer job at a legit place like Microsoft or Goldman Sachs. - -The deal for startups was based on a combination of the deal we did with Julian ($10k for 10%) and what Robert said MIT grad students got for the summer ($6k). We invested $6k per founder, which in the typical two-founder case was $12k, in return for 6%. That had to be fair, because it was twice as good as the deal we ourselves had taken. Plus that first summer, which was really hot, Jessica brought the founders free air conditioners. [16] - -Fairly quickly I realized that we had stumbled upon the way to scale startup funding. Funding startups in batches was more convenient for us, because it meant we could do things for a lot of startups at once, but being part of a batch was better for the startups too. It solved one of the biggest problems faced by founders: the isolation. Now you not only had colleagues, but colleagues who understood the problems you were facing and could tell you how they were solving them. - -As YC grew, we started to notice other advantages of scale. The alumni became a tight community, dedicated to helping one another, and especially the current batch, whose shoes they remembered being in. We also noticed that the startups were becoming one another's customers. We used to refer jokingly to the "YC GDP," but as YC grows this becomes less and less of a joke. Now lots of startups get their initial set of customers almost entirely from among their batchmates. - -I had not originally intended YC to be a full-time job. I was going to do three things: hack, write essays, and work on YC. As YC grew, and I grew more excited about it, it started to take up a lot more than a third of my attention. But for the first few years I was still able to work on other things. - -In the summer of 2006, Robert and I started working on a new version of Arc. This one was reasonably fast, because it was compiled into Scheme. To test this new Arc, I wrote Hacker News in it. It was originally meant to be a news aggregator for startup founders and was called Startup News, but after a few months I got tired of reading about nothing but startups. Plus it wasn't startup founders we wanted to reach. It was future startup founders. So I changed the name to Hacker News and the topic to whatever engaged one's intellectual curiosity. - -HN was no doubt good for YC, but it was also by far the biggest source of stress for me. If all I'd had to do was select and help founders, life would have been so easy. And that implies that HN was a mistake. Surely the biggest source of stress in one's work should at least be something close to the core of the work. Whereas I was like someone who was in pain while running a marathon not from the exertion of running, but because I had a blister from an ill-fitting shoe. When I was dealing with some urgent problem during YC, there was about a 60% chance it had to do with HN, and a 40% chance it had do with everything else combined. [17] - -As well as HN, I wrote all of YC's internal software in Arc. But while I continued to work a good deal in Arc, I gradually stopped working on Arc, partly because I didn't have time to, and partly because it was a lot less attractive to mess around with the language now that we had all this infrastructure depending on it. So now my three projects were reduced to two: writing essays and working on YC. - -YC was different from other kinds of work I've done. Instead of deciding for myself what to work on, the problems came to me. Every 6 months there was a new batch of startups, and their problems, whatever they were, became our problems. It was very engaging work, because their problems were quite varied, and the good founders were very effective. If you were trying to learn the most you could about startups in the shortest possible time, you couldn't have picked a better way to do it. - -There were parts of the job I didn't like. Disputes between cofounders, figuring out when people were lying to us, fighting with people who maltreated the startups, and so on. But I worked hard even at the parts I didn't like. I was haunted by something Kevin Hale once said about companies: "No one works harder than the boss." He meant it both descriptively and prescriptively, and it was the second part that scared me. I wanted YC to be good, so if how hard I worked set the upper bound on how hard everyone else worked, I'd better work very hard. - -One day in 2010, when he was visiting California for interviews, Robert Morris did something astonishing: he offered me unsolicited advice. I can only remember him doing that once before. One day at Viaweb, when I was bent over double from a kidney stone, he suggested that it would be a good idea for him to take me to the hospital. That was what it took for Rtm to offer unsolicited advice. So I remember his exact words very clearly. "You know," he said, "you should make sure Y Combinator isn't the last cool thing you do." - -At the time I didn't understand what he meant, but gradually it dawned on me that he was saying I should quit. This seemed strange advice, because YC was doing great. But if there was one thing rarer than Rtm offering advice, it was Rtm being wrong. So this set me thinking. It was true that on my current trajectory, YC would be the last thing I did, because it was only taking up more of my attention. It had already eaten Arc, and was in the process of eating essays too. Either YC was my life's work or I'd have to leave eventually. And it wasn't, so I would. - -In the summer of 2012 my mother had a stroke, and the cause turned out to be a blood clot caused by colon cancer. The stroke destroyed her balance, and she was put in a nursing home, but she really wanted to get out of it and back to her house, and my sister and I were determined to help her do it. I used to fly up to Oregon to visit her regularly, and I had a lot of time to think on those flights. On one of them I realized I was ready to hand YC over to someone else. - -I asked Jessica if she wanted to be president, but she didn't, so we decided we'd try to recruit Sam Altman. We talked to Robert and Trevor and we agreed to make it a complete changing of the guard. Up till that point YC had been controlled by the original LLC we four had started. But we wanted YC to last for a long time, and to do that it couldn't be controlled by the founders. So if Sam said yes, we'd let him reorganize YC. Robert and I would retire, and Jessica and Trevor would become ordinary partners. - -When we asked Sam if he wanted to be president of YC, initially he said no. He wanted to start a startup to make nuclear reactors. But I kept at it, and in October 2013 he finally agreed. We decided he'd take over starting with the winter 2014 batch. For the rest of 2013 I left running YC more and more to Sam, partly so he could learn the job, and partly because I was focused on my mother, whose cancer had returned. - -She died on January 15, 2014. We knew this was coming, but it was still hard when it did. - -I kept working on YC till March, to help get that batch of startups through Demo Day, then I checked out pretty completely. (I still talk to alumni and to new startups working on things I'm interested in, but that only takes a few hours a week.) - -What should I do next? Rtm's advice hadn't included anything about that. I wanted to do something completely different, so I decided I'd paint. I wanted to see how good I could get if I really focused on it. So the day after I stopped working on YC, I started painting. I was rusty and it took a while to get back into shape, but it was at least completely engaging. [18] - -I spent most of the rest of 2014 painting. I'd never been able to work so uninterruptedly before, and I got to be better than I had been. Not good enough, but better. Then in November, right in the middle of a painting, I ran out of steam. Up till that point I'd always been curious to see how the painting I was working on would turn out, but suddenly finishing this one seemed like a chore. So I stopped working on it and cleaned my brushes and haven't painted since. So far anyway. - -I realize that sounds rather wimpy. But attention is a zero sum game. If you can choose what to work on, and you choose a project that's not the best one (or at least a good one) for you, then it's getting in the way of another project that is. And at 50 there was some opportunity cost to screwing around. - -I started writing essays again, and wrote a bunch of new ones over the next few months. I even wrote a couple that weren't about startups. Then in March 2015 I started working on Lisp again. - -The distinctive thing about Lisp is that its core is a language defined by writing an interpreter in itself. It wasn't originally intended as a programming language in the ordinary sense. It was meant to be a formal model of computation, an alternative to the Turing machine. If you want to write an interpreter for a language in itself, what's the minimum set of predefined operators you need? The Lisp that John McCarthy invented, or more accurately discovered, is an answer to that question. [19] - -McCarthy didn't realize this Lisp could even be used to program computers till his grad student Steve Russell suggested it. Russell translated McCarthy's interpreter into IBM 704 machine language, and from that point Lisp started also to be a programming language in the ordinary sense. But its origins as a model of computation gave it a power and elegance that other languages couldn't match. It was this that attracted me in college, though I didn't understand why at the time. - -McCarthy's 1960 Lisp did nothing more than interpret Lisp expressions. It was missing a lot of things you'd want in a programming language. So these had to be added, and when they were, they weren't defined using McCarthy's original axiomatic approach. That wouldn't have been feasible at the time. McCarthy tested his interpreter by hand-simulating the execution of programs. But it was already getting close to the limit of interpreters you could test that way โ€” indeed, there was a bug in it that McCarthy had overlooked. To test a more complicated interpreter, you'd have had to run it, and computers then weren't powerful enough. - -Now they are, though. Now you could continue using McCarthy's axiomatic approach till you'd defined a complete programming language. And as long as every change you made to McCarthy's Lisp was a discoveredness-preserving transformation, you could, in principle, end up with a complete language that had this quality. Harder to do than to talk about, of course, but if it was possible in principle, why not try? So I decided to take a shot at it. It took 4 years, from March 26, 2015 to October 12, 2019. It was fortunate that I had a precisely defined goal, or it would have been hard to keep at it for so long. - -I wrote this new Lisp, called Bel, in itself in Arc. That may sound like a contradiction, but it's an indication of the sort of trickery I had to engage in to make this work. By means of an egregious collection of hacks I managed to make something close enough to an interpreter written in itself that could actually run. Not fast, but fast enough to test. - -I had to ban myself from writing essays during most of this time, or I'd never have finished. In late 2015 I spent 3 months writing essays, and when I went back to working on Bel I could barely understand the code. Not so much because it was badly written as because the problem is so convoluted. When you're working on an interpreter written in itself, it's hard to keep track of what's happening at what level, and errors can be practically encrypted by the time you get them. - -So I said no more essays till Bel was done. But I told few people about Bel while I was working on it. So for years it must have seemed that I was doing nothing, when in fact I was working harder than I'd ever worked on anything. Occasionally after wrestling for hours with some gruesome bug I'd check Twitter or HN and see someone asking "Does Paul Graham still code?" - -Working on Bel was hard but satisfying. I worked on it so intensively that at any given time I had a decent chunk of the code in my head and could write more there. I remember taking the boys to the coast on a sunny day in 2015 and figuring out how to deal with some problem involving continuations while I watched them play in the tide pools. It felt like I was doing life right. I remember that because I was slightly dismayed at how novel it felt. The good news is that I had more moments like this over the next few years. - -In the summer of 2016 we moved to England. We wanted our kids to see what it was like living in another country, and since I was a British citizen by birth, that seemed the obvious choice. We only meant to stay for a year, but we liked it so much that we still live there. So most of Bel was written in England. - -In the fall of 2019, Bel was finally finished. Like McCarthy's original Lisp, it's a spec rather than an implementation, although like McCarthy's Lisp it's a spec expressed as code. - -Now that I could write essays again, I wrote a bunch about topics I'd had stacked up. I kept writing essays through 2020, but I also started to think about other things I could work on. How should I choose what to do? Well, how had I chosen what to work on in the past? I wrote an essay for myself to answer that question, and I was surprised how long and messy the answer turned out to be. If this surprised me, who'd lived it, then I thought perhaps it would be interesting to other people, and encouraging to those with similarly messy lives. So I wrote a more detailed version for others to read, and this is the last sentence of it. - - - - - - - - - -Notes - -[1] My experience skipped a step in the evolution of computers: time-sharing machines with interactive OSes. I went straight from batch processing to microcomputers, which made microcomputers seem all the more exciting. - -[2] Italian words for abstract concepts can nearly always be predicted from their English cognates (except for occasional traps like polluzione). It's the everyday words that differ. So if you string together a lot of abstract concepts with a few simple verbs, you can make a little Italian go a long way. - -[3] I lived at Piazza San Felice 4, so my walk to the Accademia went straight down the spine of old Florence: past the Pitti, across the bridge, past Orsanmichele, between the Duomo and the Baptistery, and then up Via Ricasoli to Piazza San Marco. I saw Florence at street level in every possible condition, from empty dark winter evenings to sweltering summer days when the streets were packed with tourists. - -[4] You can of course paint people like still lives if you want to, and they're willing. That sort of portrait is arguably the apex of still life painting, though the long sitting does tend to produce pained expressions in the sitters. - -[5] Interleaf was one of many companies that had smart people and built impressive technology, and yet got crushed by Moore's Law. In the 1990s the exponential growth in the power of commodity (i.e. Intel) processors rolled up high-end, special-purpose hardware and software companies like a bulldozer. - -[6] The signature style seekers at RISD weren't specifically mercenary. In the art world, money and coolness are tightly coupled. Anything expensive comes to be seen as cool, and anything seen as cool will soon become equally expensive. - -[7] Technically the apartment wasn't rent-controlled but rent-stabilized, but this is a refinement only New Yorkers would know or care about. The point is that it was really cheap, less than half market price. - -[8] Most software you can launch as soon as it's done. But when the software is an online store builder and you're hosting the stores, if you don't have any users yet, that fact will be painfully obvious. So before we could launch publicly we had to launch privately, in the sense of recruiting an initial set of users and making sure they had decent-looking stores. - -[9] We'd had a code editor in Viaweb for users to define their own page styles. They didn't know it, but they were editing Lisp expressions underneath. But this wasn't an app editor, because the code ran when the merchants' sites were generated, not when shoppers visited them. - -[10] This was the first instance of what is now a familiar experience, and so was what happened next, when I read the comments and found they were full of angry people. How could I claim that Lisp was better than other languages? Weren't they all Turing complete? People who see the responses to essays I write sometimes tell me how sorry they feel for me, but I'm not exaggerating when I reply that it has always been like this, since the very beginning. It comes with the territory. An essay must tell readers things they don't already know, and some people dislike being told such things. - -[11] People put plenty of stuff on the internet in the 90s of course, but putting something online is not the same as publishing it online. Publishing online means you treat the online version as the (or at least a) primary version. - -[12] There is a general lesson here that our experience with Y Combinator also teaches: Customs continue to constrain you long after the restrictions that caused them have disappeared. Customary VC practice had once, like the customs about publishing essays, been based on real constraints. Startups had once been much more expensive to start, and proportionally rare. Now they could be cheap and common, but the VCs' customs still reflected the old world, just as customs about writing essays still reflected the constraints of the print era. - -Which in turn implies that people who are independent-minded (i.e. less influenced by custom) will have an advantage in fields affected by rapid change (where customs are more likely to be obsolete). - -Here's an interesting point, though: you can't always predict which fields will be affected by rapid change. Obviously software and venture capital will be, but who would have predicted that essay writing would be? - -[13] Y Combinator was not the original name. At first we were called Cambridge Seed. But we didn't want a regional name, in case someone copied us in Silicon Valley, so we renamed ourselves after one of the coolest tricks in the lambda calculus, the Y combinator. - -I picked orange as our color partly because it's the warmest, and partly because no VC used it. In 2005 all the VCs used staid colors like maroon, navy blue, and forest green, because they were trying to appeal to LPs, not founders. The YC logo itself is an inside joke: the Viaweb logo had been a white V on a red circle, so I made the YC logo a white Y on an orange square. - -[14] YC did become a fund for a couple years starting in 2009, because it was getting so big I could no longer afford to fund it personally. But after Heroku got bought we had enough money to go back to being self-funded. - -[15] I've never liked the term "deal flow," because it implies that the number of new startups at any given time is fixed. This is not only false, but it's the purpose of YC to falsify it, by causing startups to be founded that would not otherwise have existed. - -[16] She reports that they were all different shapes and sizes, because there was a run on air conditioners and she had to get whatever she could, but that they were all heavier than she could carry now. - -[17] Another problem with HN was a bizarre edge case that occurs when you both write essays and run a forum. When you run a forum, you're assumed to see if not every conversation, at least every conversation involving you. And when you write essays, people post highly imaginative misinterpretations of them on forums. Individually these two phenomena are tedious but bearable, but the combination is disastrous. You actually have to respond to the misinterpretations, because the assumption that you're present in the conversation means that not responding to any sufficiently upvoted misinterpretation reads as a tacit admission that it's correct. But that in turn encourages more; anyone who wants to pick a fight with you senses that now is their chance. - -[18] The worst thing about leaving YC was not working with Jessica anymore. We'd been working on YC almost the whole time we'd known each other, and we'd neither tried nor wanted to separate it from our personal lives, so leaving was like pulling up a deeply rooted tree. - -[19] One way to get more precise about the concept of invented vs discovered is to talk about space aliens. Any sufficiently advanced alien civilization would certainly know about the Pythagorean theorem, for example. I believe, though with less certainty, that they would also know about the Lisp in McCarthy's 1960 paper. - -But if so there's no reason to suppose that this is the limit of the language that might be known to them. Presumably aliens need numbers and errors and I/O too. So it seems likely there exists at least one path out of McCarthy's Lisp along which discoveredness is preserved. - - - -Thanks to Trevor Blackwell, John Collison, Patrick Collison, Daniel Gackle, Ralph Hazell, Jessica Livingston, Robert Morris, and Harj Taggar for reading drafts of this. \ No newline at end of file diff --git a/docs/examples/usage_example.ipynb b/docs/examples/usage_example.ipynb index 07a7216..1eb2f5d 100644 --- a/docs/examples/usage_example.ipynb +++ b/docs/examples/usage_example.ipynb @@ -235,7 +235,7 @@ ], "source": [ "service_context = ServiceContext.from_defaults(llm=llm)\n", - "docs = SimpleDirectoryReader(\"../data\").load_data()\n", + "docs = SimpleDirectoryReader(\"../../data\").load_data()\n", "index = VectorStoreIndex.from_documents(docs, service_context=service_context)\n", "query_engine = index.as_query_engine()" ] From 07aa38fb7ba6757fdda8cce1a399ba10ffae3174 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Mon, 15 Apr 2024 12:49:02 +0200 Subject: [PATCH 19/24] including not in the check for fields and questions matching the existing one --- src/argilla_llama_index/llama_index_handler.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index de28a28..0449626 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -167,17 +167,15 @@ def __init__( question.to_local() for question in self.dataset.questions ] # If the required fields and questions do not match with the existing ones, update the dataset and upload it again with "-updated" added to the name - if ( + if not ( all( element in existing_fields for element in required_context_fields ) - == False - or all( + and all( element in existing_questions for element in required_context_questions ) - == False ): local_dataset = self.dataset.pull() From ed1ad7e1f648c6f5001f427d079eeee01bc9031f Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 16 Apr 2024 09:05:33 +0200 Subject: [PATCH 20/24] doscstrings updated --- .../llama_index_handler.py | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index 0449626..7621978 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -25,6 +25,46 @@ class ArgillaCallbackHandler(BaseCallbackHandler): without the need to create a dataset and log the predictions manually. Events relevant to the predictions are automatically logged to Argilla as well, including timestamps of all the different steps of the retrieval and prediction process. + + Attributes: + dataset_name (str): The name of the Argilla dataset. + number_of_retrievals (int): The number of retrievals to log. + workspace_name (str): The name of the Argilla workspace. + api_url (str): Argilla API URL. + api_key (str): Argilla API key. + event_starts_to_ignore (List[CBEventType]): List of event types to ignore at the start of the trace. + event_ends_to_ignore (List[CBEventType]): List of event types to ignore at the end of the trace. + handlers (List[BaseCallbackHandler]): List of extra handlers to include. + + Methods: + start_trace(trace_id: Optional[str] = None) -> None: + Logic to be executed at the beggining of the tracing process. + + end_trace(trace_id: Optional[str] = None, trace_map: Optional[Dict[str, List[str]]] = None) -> None: + Logic to be executed at the end of the tracing process. + + on_event_start(event_type: CBEventType, payload: Optional[Dict[str, Any]] = None, event_id: Optional[str] = None, parent_id: str = None) -> str: + Store event start data by event type. Executed at the start of an event. + + on_event_end(event_type: CBEventType, payload: Optional[Dict[str, Any]] = None, event_id: str = None) -> None: + Store event end data by event type. Executed at the end of an event. + + Usage: + ```python + from llama_index.core import VectorStoreIndex, ServiceContext, SimpleDirectoryReader, set_global_handler + from llama_index.llms.openai import OpenAI + + set_global_handler("argilla", dataset_name="query_model") + + llm = OpenAI(model="gpt-3.5-turbo", temperature=0.8, openai_api_key=os.getenv("OPENAI_API_KEY")) + + service_context = ServiceContext.from_defaults(llm=llm) + docs = SimpleDirectoryReader("../../data").load_data() + index = VectorStoreIndex.from_documents(docs, service_context=service_context) + query_engine = index.as_query_engine() + + response = query_engine.query("What did the author do growing up?") + ``` """ def __init__( @@ -633,7 +673,7 @@ def on_event_start( parent_id: str = None, ) -> str: """ - Store event start data by event type. + Store event start data by event type. Executed at the start of an event. Args: event_type (CBEventType): The event type to store. @@ -657,7 +697,7 @@ def on_event_end( event_id: str = None, ) -> None: """ - Store event end data by event type. + Store event end data by event type. Executed at the end of an event. Args: event_type (CBEventType): The event type to store. From 051db5be3712d532a704fd61da3493d4e252d0c2 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Tue, 16 Apr 2024 10:45:06 +0200 Subject: [PATCH 21/24] passing directly the api and the api url to the rg.init(), error logic already handled there --- src/argilla_llama_index/llama_index_handler.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/argilla_llama_index/llama_index_handler.py b/src/argilla_llama_index/llama_index_handler.py index 7621978..623f5c8 100644 --- a/src/argilla_llama_index/llama_index_handler.py +++ b/src/argilla_llama_index/llama_index_handler.py @@ -123,16 +123,8 @@ def __init__( ) api_key = DEFAULT_API_KEY - # Initialize the Argilla client - try: - rg.init(api_key=api_key, api_url=api_url) - except Exception as e: - raise ConnectionError( - f"Could not connect to Argilla with exception: '{e}'.\n" - "Please check your `api_key` and `api_url`, and make sure that " - "the Argilla server is up and running. If the problem persists " - f"please report it to https://github.com/argilla-io/argilla/issues/ as an `integration` issue." - ) from e + + rg.init(api_key=api_key, api_url=api_url) # Set the Argilla variables self.dataset_name = dataset_name From 52f5e43ee0943a5bf809ebb1b34a4b8b58367cf0 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Thu, 25 Apr 2024 14:59:57 +0200 Subject: [PATCH 22/24] current status on testing --- tests/test_llama_index_callback.py | 129 ++++------------------ tests/test_llama_index_callback_legacy.py | 119 ++++++++++++++++++++ 2 files changed, 142 insertions(+), 106 deletions(-) create mode 100644 tests/test_llama_index_callback_legacy.py diff --git a/tests/test_llama_index_callback.py b/tests/test_llama_index_callback.py index d711e2b..974a329 100644 --- a/tests/test_llama_index_callback.py +++ b/tests/test_llama_index_callback.py @@ -1,118 +1,35 @@ -from argilla_llama_index.helpers import _calc_time, _get_time_diff +from argilla import init +from argilla_llama_index import ArgillaCallbackHandler import unittest -from unittest.mock import patch, MagicMock -from argilla_llama_index import ArgillaCallbackHandler +from unittest import mock +from unittest.mock import Mock, MagicMock, patch +import requests_mock class TestArgillaCallbackHandler(unittest.TestCase): - def setUp(self): - self.dataset_name = "test_dataset_llama_index" - self.workspace_name = "admin" - self.api_url = "http://localhost:6900" - self.api_key = "admin.apikey" - - self.handler = ArgillaCallbackHandler( - dataset_name=self.dataset_name, - workspace_name=self.workspace_name, - api_url=self.api_url, - api_key=self.api_key, - ) - - self.events_data = MagicMock() - self.data_to_log = MagicMock() - self.components_to_log = MagicMock() - self._ignore_components_in_tree = MagicMock() - self.trace_map = MagicMock() - - self.tree_structure_dict = { - "root": ["query"], - "query": ["retrieve", "synthesize"], - "synthesize": ["llm", "grandchild1"], - } - - def test_init(self): - self.assertEqual(self.handler.dataset_name, self.dataset_name) - self.assertEqual(self.handler.workspace_name, self.workspace_name) - - @patch("argilla_llama_index.llama_index_handler.rg.init") - def test_init_connection_error(self, mock_init): - mock_init.side_effect = ConnectionError("Connection failed") - with self.assertRaises(ConnectionError): - ArgillaCallbackHandler( - dataset_name=self.dataset_name, - workspace_name=self.workspace_name, - api_url=self.api_url, - api_key=self.api_key, - ) - - @patch("argilla_llama_index.llama_index_handler.rg.FeedbackDataset.list") - @patch("argilla_llama_index.llama_index_handler.rg.FeedbackDataset.from_argilla") - def test_init_file_not_found_error(self, mock_from_argilla, mock_list): - mock_list.return_value = [] - mock_from_argilla.side_effect = FileNotFoundError("Dataset not found") - with self.assertRaises(FileNotFoundError): - ArgillaCallbackHandler( - dataset_name=self.dataset_name, - workspace_name=self.workspace_name, - api_url=self.api_url, - api_key=self.api_key, - ) - - def test_check_components_for_tree(self): - self.handler._check_components_for_tree(self.tree_structure_dict) - - def test_get_events_map_with_names(self): - trace_map = {"query": ["retrieve"], "llm": []} - events_map = self.handler._get_events_map_with_names( - self.events_data, trace_map + @mock.patch('httpx.get') + @mock.patch('argilla.init') # Replace 'your_module.some_method1' with the actual method to patch + #@mock.patch('argilla.datasets.push_to_argilla') # Replace 'your_module.some_method2' with the actual method to patch + def test_constructor_calls(self, mock_some_method1, mock_get): + # Mock the HTTP request made by your method + mock_get.return_value.status_code = 200 + mock_get.return_value.json.return_value = {'key': 'value'} + + # Create an instance of ArgillaCallbackHandler + handler = ArgillaCallbackHandler( + dataset_name="dataset_name", + workspace_name="workspace_name", + api_url="http://localhost:6900", + api_key="api_key", ) - self.assertIsInstance(events_map, dict) - self.assertEqual(len(events_map), 2) - def test_extract_and_log_info(self): + # Assert that some_method1 was called with the expected parameters + mock_some_method1.assert_called_once_with(api_key="api_key", api_url="http://localhost:6900") - tree_structure_dict = self.handler._check_components_for_tree( - self.tree_structure_dict - ) - self.handler._extract_and_log_info(self.events_data, tree_structure_dict) - - def test_start_trace(self): - self.handler.start_trace() - - # TODO: Create a test for end_trace - - def test_on_event_start(self): - event_type = "event1" - payload = {} - event_id = "123" - parent_id = "456" - self.handler.on_event_start(event_type, payload, event_id, parent_id) - - def test_on_event_end(self): - event_type = "event1" - payload = {} - event_id = "123" - self.handler.on_event_end(event_type, payload, event_id) - - def test_get_time_diff(self): - event_1_time_str = "01/11/2024, 17:01:04.328656" - event_2_time_str = "01/11/2024, 17:02:07.328523" - time_diff = _get_time_diff(event_1_time_str, event_2_time_str) - self.assertIsInstance(time_diff, float) - - def test_calc_time(self): - - id = "event1" - self.events_data.__getitem__().__getitem__().time = ( - "01/11/2024, 17:01:04.328656" - ) - self.events_data.__getitem__().__getitem__().time = ( - "01/11/2024, 17:02:07.328523" - ) - time = _calc_time(self.events_data, id) - self.assertIsInstance(time, float) + # Assert that some_method2 was called with the expected parameters + #mock_some_method2.assert_called_once_with('expected_param_for_some_method2') if __name__ == "__main__": diff --git a/tests/test_llama_index_callback_legacy.py b/tests/test_llama_index_callback_legacy.py new file mode 100644 index 0000000..d711e2b --- /dev/null +++ b/tests/test_llama_index_callback_legacy.py @@ -0,0 +1,119 @@ +from argilla_llama_index.helpers import _calc_time, _get_time_diff + +import unittest +from unittest.mock import patch, MagicMock +from argilla_llama_index import ArgillaCallbackHandler + + +class TestArgillaCallbackHandler(unittest.TestCase): + def setUp(self): + self.dataset_name = "test_dataset_llama_index" + self.workspace_name = "admin" + self.api_url = "http://localhost:6900" + self.api_key = "admin.apikey" + + self.handler = ArgillaCallbackHandler( + dataset_name=self.dataset_name, + workspace_name=self.workspace_name, + api_url=self.api_url, + api_key=self.api_key, + ) + + self.events_data = MagicMock() + self.data_to_log = MagicMock() + self.components_to_log = MagicMock() + self._ignore_components_in_tree = MagicMock() + self.trace_map = MagicMock() + + self.tree_structure_dict = { + "root": ["query"], + "query": ["retrieve", "synthesize"], + "synthesize": ["llm", "grandchild1"], + } + + def test_init(self): + self.assertEqual(self.handler.dataset_name, self.dataset_name) + self.assertEqual(self.handler.workspace_name, self.workspace_name) + + @patch("argilla_llama_index.llama_index_handler.rg.init") + def test_init_connection_error(self, mock_init): + mock_init.side_effect = ConnectionError("Connection failed") + with self.assertRaises(ConnectionError): + ArgillaCallbackHandler( + dataset_name=self.dataset_name, + workspace_name=self.workspace_name, + api_url=self.api_url, + api_key=self.api_key, + ) + + @patch("argilla_llama_index.llama_index_handler.rg.FeedbackDataset.list") + @patch("argilla_llama_index.llama_index_handler.rg.FeedbackDataset.from_argilla") + def test_init_file_not_found_error(self, mock_from_argilla, mock_list): + mock_list.return_value = [] + mock_from_argilla.side_effect = FileNotFoundError("Dataset not found") + with self.assertRaises(FileNotFoundError): + ArgillaCallbackHandler( + dataset_name=self.dataset_name, + workspace_name=self.workspace_name, + api_url=self.api_url, + api_key=self.api_key, + ) + + def test_check_components_for_tree(self): + self.handler._check_components_for_tree(self.tree_structure_dict) + + def test_get_events_map_with_names(self): + + trace_map = {"query": ["retrieve"], "llm": []} + events_map = self.handler._get_events_map_with_names( + self.events_data, trace_map + ) + self.assertIsInstance(events_map, dict) + self.assertEqual(len(events_map), 2) + + def test_extract_and_log_info(self): + + tree_structure_dict = self.handler._check_components_for_tree( + self.tree_structure_dict + ) + self.handler._extract_and_log_info(self.events_data, tree_structure_dict) + + def test_start_trace(self): + self.handler.start_trace() + + # TODO: Create a test for end_trace + + def test_on_event_start(self): + event_type = "event1" + payload = {} + event_id = "123" + parent_id = "456" + self.handler.on_event_start(event_type, payload, event_id, parent_id) + + def test_on_event_end(self): + event_type = "event1" + payload = {} + event_id = "123" + self.handler.on_event_end(event_type, payload, event_id) + + def test_get_time_diff(self): + event_1_time_str = "01/11/2024, 17:01:04.328656" + event_2_time_str = "01/11/2024, 17:02:07.328523" + time_diff = _get_time_diff(event_1_time_str, event_2_time_str) + self.assertIsInstance(time_diff, float) + + def test_calc_time(self): + + id = "event1" + self.events_data.__getitem__().__getitem__().time = ( + "01/11/2024, 17:01:04.328656" + ) + self.events_data.__getitem__().__getitem__().time = ( + "01/11/2024, 17:02:07.328523" + ) + time = _calc_time(self.events_data, id) + self.assertIsInstance(time, float) + + +if __name__ == "__main__": + unittest.main() From fb47d3d4043c709e725beb9929c187f7d6113bb5 Mon Sep 17 00:00:00 2001 From: ignacioct Date: Fri, 26 Apr 2024 11:17:07 +0200 Subject: [PATCH 23/24] integration test first approach --- .github/workflows/integration-tests.yml | 83 +++++++++++++++++++++++++ .github/workflows/release.yml | 2 +- tests/test_llama_index_callback.py | 36 ----------- 3 files changed, 84 insertions(+), 37 deletions(-) create mode 100644 .github/workflows/integration-tests.yml delete mode 100644 tests/test_llama_index_callback.py diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml new file mode 100644 index 0000000..5947f87 --- /dev/null +++ b/.github/workflows/integration-tests.yml @@ -0,0 +1,83 @@ +name: ๐Ÿงช Integration Tests + +on: + push: + branches: + - '*' + +jobs: + integration_tests: + name: Running integration tests, which require an Argilla instance running + runs-on: ubuntu-latest + services: + search-engine: + image: + searchEngineDockerImage: + description: "The name of the Docker image of the search engine to use." + default: docker.elastic.co/elasticsearch/elasticsearch:8.8.2 + required: false + type: string + ports: + - 6900:6900 + env: + searchEngineDockerEnv: + description: "The name of the Docker image of the search engine to use." + default: '{"discovery.type": "single-node", "xpack.security.enabled": "false"}' + required: false + type: string + defaults: + run: + shell: bash -l {0} + steps: + - name: Checkout Code ๐Ÿ›Ž + uses: actions/checkout@v3 + - name: Setup Conda Env ๐Ÿ + uses: conda-incubator/setup-miniconda@v2 + with: + miniforge-variant: Mambaforge + miniforge-version: latest + use-mamba: true + activate-environment: argilla + - name: Get date for conda cache + id: get-date + run: echo "::set-output name=today::$(/bin/date -u '+%Y%m%d')" + shell: bash + - name: Cache Conda env + uses: actions/cache@v3 + id: cache + with: + path: ${{ env.CONDA }}/envs + key: conda-${{ runner.os }}--${{ runner.arch }}--${{ steps.get-date.outputs.today }}-${{ hashFiles('environment_dev.yml') }}-${{ env.CACHE_NUMBER }} + - name: Update environment + if: steps.cache.outputs.cache-hit != 'true' + run: mamba env update -n argilla -f environment_dev.yml + - name: Cache pip ๐Ÿ‘œ + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ env.CACHE_NUMBER }}-${{ hashFiles('pyproject.toml') }} + - name: Set Argilla search engine env variable + if: startsWith(inputs.searchEngineDockerImage, 'docker.elastic.co') + run: | + echo "ARGILLA_SEARCH_ENGINE=elasticsearch" >> "$GITHUB_ENV" + echo "Configure elasticsearch engine" + - name: Set Argilla search engine env variable + if: startsWith(inputs.searchEngineDockerImage, 'opensearchproject') + run: | + echo "ARGILLA_SEARCH_ENGINE=opensearch" >> "$GITHUB_ENV" + echo "Configure opensearch engine" + - name: Launch Argilla Server + env: + ARGILLA_ENABLE_TELEMETRY: 0 + run: | + pip install -e ".[server]" + python -m argilla server database migrate + python -m argilla server database users create_default + python -m argilla server start & + - name: Run end2end examples ๐Ÿ“ˆ + env: + ARGILLA_ENABLE_TELEMETRY: 0 + run: | + pip install pytest + pytest tests + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b1b7dd0..11aba23 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Release +name: ๐ŸŽ‰ Release on: release: diff --git a/tests/test_llama_index_callback.py b/tests/test_llama_index_callback.py deleted file mode 100644 index 974a329..0000000 --- a/tests/test_llama_index_callback.py +++ /dev/null @@ -1,36 +0,0 @@ -from argilla import init -from argilla_llama_index import ArgillaCallbackHandler - -import unittest -from unittest import mock -from unittest.mock import Mock, MagicMock, patch - -import requests_mock - -class TestArgillaCallbackHandler(unittest.TestCase): - - @mock.patch('httpx.get') - @mock.patch('argilla.init') # Replace 'your_module.some_method1' with the actual method to patch - #@mock.patch('argilla.datasets.push_to_argilla') # Replace 'your_module.some_method2' with the actual method to patch - def test_constructor_calls(self, mock_some_method1, mock_get): - # Mock the HTTP request made by your method - mock_get.return_value.status_code = 200 - mock_get.return_value.json.return_value = {'key': 'value'} - - # Create an instance of ArgillaCallbackHandler - handler = ArgillaCallbackHandler( - dataset_name="dataset_name", - workspace_name="workspace_name", - api_url="http://localhost:6900", - api_key="api_key", - ) - - # Assert that some_method1 was called with the expected parameters - mock_some_method1.assert_called_once_with(api_key="api_key", api_url="http://localhost:6900") - - # Assert that some_method2 was called with the expected parameters - #mock_some_method2.assert_called_once_with('expected_param_for_some_method2') - - -if __name__ == "__main__": - unittest.main() From 1d470af287894bb7e52761792e9b984b49affc1a Mon Sep 17 00:00:00 2001 From: ignacioct Date: Fri, 26 Apr 2024 11:18:48 +0200 Subject: [PATCH 24/24] push to test of integration tests get triggered in PR --- ...lama_index_callback_legacy.py => test_llama_index_callback.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test_llama_index_callback_legacy.py => test_llama_index_callback.py} (100%) diff --git a/tests/test_llama_index_callback_legacy.py b/tests/test_llama_index_callback.py similarity index 100% rename from tests/test_llama_index_callback_legacy.py rename to tests/test_llama_index_callback.py
[04/09/24 16:26:24] INFO     INFO:argilla.client.feedback.dataset.local.mixins:โœ“ Dataset succesfully  mixins.py:271\n",
+       "                             pushed to Argilla                                                                     \n",
+       "