438 lines
99 KiB
Plaintext
438 lines
99 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "A4K2dtCUsJ9N",
|
|
"outputId": "b1df4765-7347-4c8e-aefb-3176664ee603"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Cloning into 'miniLLMFlow'...\n",
|
|
"remote: Enumerating objects: 171, done.\u001b[K\n",
|
|
"remote: Counting objects: 100% (171/171), done.\u001b[K\n",
|
|
"remote: Compressing objects: 100% (107/107), done.\u001b[K\n",
|
|
"remote: Total 171 (delta 66), reused 139 (delta 46), pack-reused 0 (from 0)\u001b[K\n",
|
|
"Receiving objects: 100% (171/171), 156.24 KiB | 6.25 MiB/s, done.\n",
|
|
"Resolving deltas: 100% (66/66), done.\n",
|
|
"Collecting minillmflow\n",
|
|
" Downloading minillmflow-0.0.2-py3-none-any.whl.metadata (257 bytes)\n",
|
|
"Downloading minillmflow-0.0.2-py3-none-any.whl (3.2 kB)\n",
|
|
"Installing collected packages: minillmflow\n",
|
|
"Successfully installed minillmflow-0.0.2\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Example App for text summarization & QA using minillmflow\n",
|
|
"# Download Paul Graham Essays, Create Summaries, and Enable Q&A\n",
|
|
"!git clone https://github.com/zachary62/miniLLMFlow.git\n",
|
|
"!pip install minillmflow"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/",
|
|
"height": 35
|
|
},
|
|
"id": "On06KSv4r38M",
|
|
"outputId": "05374537-dc86-4cc8-c1be-adc421c0483b"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.google.colaboratory.intrinsic+json": {
|
|
"type": "string"
|
|
},
|
|
"text/plain": [
|
|
"\"As an artificial intelligence, I don't have feelings, but thank you for asking! How can I assist you today?\""
|
|
]
|
|
},
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"from minillmflow import Node, BatchNode, Flow, BatchFlow, AsyncNode, AsyncFlow, BatchAsyncFlow\n",
|
|
"import os\n",
|
|
"\n",
|
|
"# 1) Implement a simple LLM helper (OpenAI in this example).\n",
|
|
"def call_llm(prompt):\n",
|
|
" from openai import OpenAI\n",
|
|
" # Users must set an OpenAI API key; can also load from env var, etc.\n",
|
|
" client = OpenAI(api_key=\"YOUR_API_KEY_HERE\")\n",
|
|
" r = client.chat.completions.create(\n",
|
|
" model=\"gpt-4\",\n",
|
|
" messages=[{\"role\": \"user\", \"content\": prompt}]\n",
|
|
" )\n",
|
|
" return r.choices[0].message.content\n",
|
|
"call_llm(\"How are you?\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "NvRvaed_r38N",
|
|
"outputId": "8e6c333f-e266-4a7f-93d7-afb45fbb4ba5"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{'apple.txt': '\\n\\nWant to start a startup? Get funded by\\nY Combinator.\\n\\n\\n\\n\\nNovember 2009I don\\'t think Apple realizes how badly the App Store approval process\\nis broken. Or rather, I don\\'t think they realize how much it matters\\nthat it\\'s broken.The way Apple runs the App Store has harmed their reputation with\\nprogrammers more than anything else they\\'ve ever done. \\nTheir reputation with programmers used to be great.\\nIt used to be the most common complaint you heard\\nabout Apple was that their fans admired them too uncritically.\\nThe App Store has changed that. Now a lot of programmers\\nhave started to see Apple as evil.How much of the goodwill Apple once had with programmers have they\\nlost over the App Store? A third? Half? And that\\'s just so far.\\nThe App Store is an ongoing karma leak.* * *How did Apple get into this mess? Their fundamental problem is\\nthat they don\\'t understand software.They treat iPhone apps the way they treat the music they sell through\\niTunes. Apple is the channel; they own the user; if you want to\\nreach users, you do it on their terms. The record labels agreed,\\nreluctantly. But this model doesn\\'t work for software. It doesn\\'t\\nwork for an intermediary to own the user. The software business\\nlearned that in the early 1980s, when companies like VisiCorp showed\\nthat although the words \"software\" and \"publisher\" fit together,\\nthe underlying concepts don\\'t. Software isn\\'t like music or books.\\nIt\\'s too complicated for a third party to act as an intermediary\\nbetween developer and user. And yet that\\'s what Apple is trying\\nto be with the App Store: a software publisher. And a particularly\\noverreaching one at that, with fussy tastes and a rigidly enforced\\nhouse style.If software publishing didn\\'t work in 1980, it works even less now\\nthat software development has evolved from a small number of big\\nreleases to a constant stream of small ones. But Apple doesn\\'t\\nunderstand that either. Their model of product development derives\\nfrom hardware. They work on something till they think it\\'s finished,\\nthen they release it. You have to do that with hardware, but because\\nsoftware is so easy to change, its design can benefit from evolution.\\nThe standard way to develop applications now is to launch fast and\\niterate. Which means it\\'s a disaster to have long, random delays\\neach time you release a new version.Apparently Apple\\'s attitude is that developers should be more careful\\nwhen they submit a new version to the App Store. They would say\\nthat. But powerful as they are, they\\'re not powerful enough to\\nturn back the evolution of technology. Programmers don\\'t use\\nlaunch-fast-and-iterate out of laziness. They use it because it\\nyields the best results. By obstructing that process, Apple is\\nmaking them do bad work, and programmers hate that as much as Apple\\nwould.How would Apple like it if when they discovered a serious bug in\\nOS\\xa0X, instead of releasing a software update immediately, they had\\nto submit their code to an intermediary who sat on it for a month\\nand then rejected it because it contained an icon they didn\\'t like?By breaking software development, Apple gets the opposite of what\\nthey intended: the version of an app currently available in the App\\nStore tends to be an old and buggy one. One developer told me:\\n\\n As a result of their process, the App Store is full of half-baked\\n applications. I make a new version almost every day that I release\\n to beta users. The version on the App Store feels old and crappy.\\n I\\'m sure that a lot of developers feel this way: One emotion is\\n \"I\\'m not really proud about what\\'s in the App Store\", and it\\'s\\n combined with the emotion \"Really, it\\'s Apple\\'s fault.\"\\n\\nAnother wrote:\\n\\n I believe that they think their approval process helps users by\\n ensuring quality. In reality, bugs like ours get through all the\\n time and then it can take 4-8 weeks to get that bug fix approved,\\n leaving users to think that iPhone apps sometimes just don\\'t work.\\n Worse for Apple, these apps work just fine on other platforms\\n that have immediate approval processes.\\n\\nActually I suppose Apple has a third misconception: that all the\\ncomplaints about App Store approvals are not a serious problem.\\nThey must hear developers complaining. But partners and suppliers\\nare always complaining. It would be a bad sign if they weren\\'t;\\nit would mean you were being too easy on them. Meanwhile the iPhone\\nis selling better than ever. So why do they need to fix anything?They get away with maltreating developers, in the short term, because\\nthey make such great hardware. I just bought a new 27\" iMac a\\ncouple days ago. It\\'s fabulous. The screen\\'s too shiny, and the\\ndisk is surprisingly loud, but it\\'s so beautiful that you can\\'t\\nmake yourself care.So I bought it, but I bought it, for the first time, with misgivings.\\nI felt the way I\\'d feel buying something made in a country with a\\nbad human rights record. That was new. In the past when I bought\\nthings from Apple it was an unalloyed pleasure. Oh boy! They make\\nsuch great stuff. This time it felt like a Faustian bargain. They\\nmake such great stuff, but they\\'re such assholes. Do I really want\\nto support this company?* * *Should Apple care what people like me think? What difference does\\nit make if they alienate a small minority of their users?There are a couple reasons they should care. One is that these\\nusers are the people they want as employees. If your company seems\\nevil, the best programmers won\\'t work for you. That hurt Microsoft\\na lot starting in the 90s. Programmers started to feel sheepish\\nabout working there. It seemed like selling out. When people from\\nMicrosoft were talking to other programmers and they mentioned where\\nthey worked, there were a lot of self-deprecating jokes about having\\ngone over to the dark side. But the real problem for Microsoft\\nwasn\\'t the embarrassment of the people they hired. It was the\\npeople they never got. And you know who got them? Google and\\nApple. If Microsoft was the Empire, they were the Rebel Alliance.\\nAnd it\\'s largely because they got more of the best people that\\nGoogle and Apple are doing so much better than Microsoft today.Why are programmers so fussy about their employers\\' morals? Partly\\nbecause they can afford to be. The best programmers can work\\nwherever they want. They don\\'t have to work for a company they\\nhave qualms about.But the other reason programmers are fussy, I think, is that evil\\nbegets stupidity. An organization that wins by exercising power\\nstarts to lose the ability to win by doing better work. And it\\'s\\nnot fun for a smart person to work in a place where the best ideas\\naren\\'t the ones that win. I think the reason Google embraced \"Don\\'t\\nbe evil\" so eagerly was not so much to impress the outside world\\nas to inoculate themselves against arrogance.\\n[1]That has worked for Google so far. They\\'ve become more\\nbureaucratic, but otherwise they seem to have held true to their\\noriginal principles. With Apple that seems less the case. When you\\nlook at the famous \\n1984 ad \\nnow, it\\'s easier to imagine Apple as the\\ndictator on the screen than the woman with the hammer.\\n[2]\\nIn fact, if you read the dictator\\'s speech it sounds uncannily like a\\nprophecy of the App Store.\\n\\n We have triumphed over the unprincipled dissemination of facts.We have created, for the first time in all history, a garden of\\n pure ideology, where each worker may bloom secure from the pests\\n of contradictory and confusing truths.\\n\\nThe other reason Apple should care what programmers think of them\\nis that when you sell a platform, developers make or break you. If\\nanyone should know this, Apple should. VisiCalc made the Apple II.And programmers build applications for the platforms they use. Most\\napplications—most startups, probably—grow out of personal projects.\\nApple itself did. Apple made microcomputers because that\\'s what\\nSteve Wozniak wanted for himself. He couldn\\'t have afforded a\\nminicomputer. \\n[3]\\n Microsoft likewise started out making interpreters\\nfor little microcomputers because\\nBill Gates and Paul Allen were interested in using them. It\\'s a\\nrare startup that doesn\\'t build something the founders use.The main reason there are so many iPhone apps is that so many programmers\\nhave iPhones. They may know, because they read it in an article,\\nthat Blackberry has such and such market share. But in practice\\nit\\'s as if RIM didn\\'t exist. If they\\'re going to build something,\\nthey want to be able to use it themselves, and that means building\\nan iPhone app.So programmers continue to develop iPhone apps, even though Apple\\ncontinues to maltreat them. They\\'re like someone stuck in an abusive\\nrelationship. They\\'re so attracted to the iPhone that they can\\'t\\nleave. But they\\'re looking for a way out. One wrote:\\n\\n While I did enjoy developing for the iPhone, the control they\\n place on the App Store does not give me the drive to develop\\n applications as I would like. In fact I don\\'t intend to make any\\n more iPhone applications unless absolutely necessary.\\n[4]\\n\\nCan anything break this cycle? No device I\\'ve seen so far could.\\nPalm and RIM haven\\'t a hope. The only credible contender is Android.\\nBut Android is an orphan; Google doesn\\'t really care about it, not\\nthe way Apple cares about the iPhone. Apple cares about the iPhone\\nthe way Google cares about search.* * *Is the future of handheld devices one locked down by Apple? It\\'s\\na worrying prospect. It would be a bummer to have another grim\\nmonoculture like we had in the 1990s. In 1995, writing software\\nfor end users was effectively identical with writing Windows\\napplications. Our horror at that prospect was the single biggest\\nthing that drove us to start building web apps.At least we know now what it would take to break Apple\\'s lock.\\nYou\\'d have to get iPhones out of programmers\\' hands. If programmers\\nused some other device for mobile web access, they\\'d start to develop\\napps for that instead.How could you make a device programmers liked better than the iPhone?\\nIt\\'s unlikely you could make something better designed. Apple\\nleaves no room there. So this alternative device probably couldn\\'t\\nwin on general appeal. It would have to win by virtue of some\\nappeal it had to programmers specifically.One way to appeal to programmers is with software. If you\\ncould think of an application programmers had to have, but that\\nwould be impossible in the circumscribed world of the iPhone, \\nyou could presumably get them to switch.That would definitely happen if programmers started to use handhelds\\nas development machines—if handhelds displaced laptops the\\nway laptops displaced desktops. You need more control of a development\\nmachine than Apple will let you have over an iPhone.Could anyone make a device that you\\'d carry around in your pocket\\nlike a phone, and yet would also work as a development machine?\\nIt\\'s hard to imagine what it would look like. But I\\'ve learned\\nnever to say never about technology. A phone-sized device that\\nwould work as a development machine is no more miraculous by present\\nstandards than the iPhone itself would have seemed by the standards\\nof 1995.My current development machine is a MacBook Air, which I use with\\nan external monitor and keyboard in my office, and by itself when\\ntraveling. If there was a version half the size I\\'d prefer it.\\nThat still wouldn\\'t be small enough to carry around everywhere like\\na phone, but we\\'re within a factor of 4 or so. Surely that gap is\\nbridgeable. In fact, let\\'s make it an\\nRFS. Wanted: \\nWoman with hammer.Notes[1]\\nWhen Google adopted \"Don\\'t be evil,\" they were still so small\\nthat no one would have expected them to be, yet.\\n[2]\\nThe dictator in the 1984 ad isn\\'t Microsoft, incidentally;\\nit\\'s IBM. IBM seemed a lot more frightening in those days, but\\nthey were friendlier to developers than Apple is now.[3]\\nHe couldn\\'t even afford a monitor. That\\'s why the Apple\\nI used a TV as a monitor.[4]\\nSeveral people I talked to mentioned how much they liked the\\niPhone SDK. The problem is not Apple\\'s products but their policies.\\nFortunately policies are software; Apple can change them instantly\\nif they want to. Handy that, isn\\'t it?Thanks to Sam Altman, Trevor Blackwell, Ross Boucher, \\nJames Bracy, Gabor Cselle,\\nPatrick Collison, Jason Freedman, John Gruber, Joe Hewitt, Jessica Livingston,\\nRobert Morris, Teng Siong Ong, Nikhil Pandit, Savraj Singh, and Jared Tame for reading drafts of this.', 'aord.txt': 'October 2015When I talk to a startup that\\'s been operating for more than 8 or\\n9 months, the first thing I want to know is almost always the same.\\nAssuming their expenses remain constant and their revenue growth\\nis what it has been over the last several months, do they make it to\\nprofitability on the money they have left? Or to put it more\\ndramatically, by default do they live or die?The startling thing is how often the founders themselves don\\'t know.\\nHalf the founders I talk to don\\'t know whether they\\'re default alive\\nor default dead.If you\\'re among that number, Trevor Blackwell has made a handy\\ncalculator you can use to find out.The reason I want to know first whether a startup is default alive\\nor default dead is that the rest of the conversation depends on the\\nanswer. If the company is default alive, we can talk about ambitious\\nnew things they could do. If it\\'s default dead, we probably need\\nto talk about how to save it. We know the current trajectory ends\\nbadly. How can they get off that trajectory?Why do so few founders know whether they\\'re default alive or default\\ndead? Mainly, I think, because they\\'re not used to asking that.\\nIt\\'s not a question that makes sense to ask early on, any more than\\nit makes sense to ask a 3 year old how he plans to support\\nhimself. But as the company grows older, the question switches from\\nmeaningless to critical. That kind of switch often takes people\\nby surprise.I propose the following solution: instead of starting to ask too\\nlate whether you\\'re default alive or default dead, start asking too\\nearly. It\\'s hard to say precisely when the question switches\\npolarity. But it\\'s probably not that dangerous to start worrying\\ntoo early that you\\'re default dead, whereas it\\'s very dangerous to\\nstart worrying too late.The reason is a phenomenon I wrote about earlier: the\\nfatal pinch.\\nThe fatal pinch is default dead + slow growth + not enough\\ntime to fix it. And the way founders end up in it is by not realizing\\nthat\\'s where they\\'re headed.There is another reason founders don\\'t ask themselves whether they\\'re\\ndefault alive or default dead: they assume it will be easy to raise\\nmore money. But that assumption is often false, and worse still, the\\nmore you depend on it, the falser it becomes.Maybe it will help to separate facts from hopes. Instead of thinking\\nof the future with vague optimism, explicitly separate the components.\\nSay \"We\\'re default dead, but we\\'re counting on investors to save\\nus.\" Maybe as you say that, it will set off the same alarms in your\\nhead that it does in mine. And if you set off the alarms sufficiently\\nearly, you may be able to avoid the fatal pinch.It would be safe to be default dead if you could count on investors\\nsaving you. As a rule their interest is a function of\\ngrowth. If you have steep revenue growth, say over 5x a year, you\\ncan start to count on investors being interested even if you\\'re not\\nprofitable.\\n[1]\\nBut investors are so fickle that you can never\\ndo more than start to count on them. Sometimes something about your\\nbusiness will spook investors even if your growth is great. So no\\nmatter how good your growth is, you can never safely treat fundraising\\nas more than a plan A. You should always have a plan B as well: you\\nshould know (as in write down) precisely what you\\'ll need to do to\\nsurvive if you can\\'t raise more money, and precisely when you\\'ll \\nhave to switch to plan B if plan A isn\\'t working.In any case, growing fast versus operating cheaply is far from the\\nsharp dichotomy many founders assume it to be. In practice there\\nis surprisingly little connection between how much a startup spends\\nand how fast it grows. When a startup grows fast, it\\'s usually\\nbecause the product hits a nerve, in the sense of hitting some big\\nneed straight on. When a startup spends a lot, it\\'s usually because\\nthe product is expensive to develop or sell, or simply because\\nthey\\'re wasteful.If you\\'re paying attention, you\\'ll be asking at this point not just\\nhow to avoid the fatal pinch, but how to avoid being default dead.\\nThat one is easy: don\\'t hire too fast. Hiring too fast is by far\\nthe biggest killer of startups that raise money.\\n[2]Founders tell themselves they need to hire in order to grow. But\\nmost err on the side of overestimating this need rather than\\nunderestimating it. Why? Partly because there\\'s so much work to\\ndo. Naive founders think that if they can just hire enough\\npeople, it will all get done. Partly because successful startups have\\nlots of employees, so it seems like that\\'s what one does in order\\nto be successful. In fact the large staffs of successful startups\\nare probably more the effect of growth than the cause. And\\npartly because when founders have slow growth they don\\'t want to\\nface what is usually the real reason: the product is not appealing\\nenough.Plus founders who\\'ve just raised money are often encouraged to\\noverhire by the VCs who funded them. Kill-or-cure strategies are\\noptimal for VCs because they\\'re protected by the portfolio effect.\\nVCs want to blow you up, in one sense of the phrase or the other.\\nBut as a founder your incentives are different. You want above all\\nto survive.\\n[3]Here\\'s a common way startups die. They make something moderately\\nappealing and have decent initial growth. They raise their first\\nround fairly easily, because the founders seem smart and the idea\\nsounds plausible. But because the product is only moderately\\nappealing, growth is ok but not great. The founders convince\\nthemselves that hiring a bunch of people is the way to boost growth.\\nTheir investors agree. But (because the product is only moderately\\nappealing) the growth never comes. Now they\\'re rapidly running out\\nof runway. They hope further investment will save them. But because\\nthey have high expenses and slow growth, they\\'re now unappealing\\nto investors. They\\'re unable to raise more, and the company dies.What the company should have done is address the fundamental problem:\\nthat the product is only moderately appealing. Hiring people is\\nrarely the way to fix that. More often than not it makes it harder.\\nAt this early stage, the product needs to evolve more than to be\\n\"built out,\" and that\\'s usually easier with fewer people.\\n[4]Asking whether you\\'re default alive or default dead may save you\\nfrom this. Maybe the alarm bells it sets off will counteract the\\nforces that push you to overhire. Instead you\\'ll be compelled to\\nseek growth in other ways. For example, by doing\\nthings that don\\'t scale, or by redesigning the product in the\\nway only founders can.\\nAnd for many if not most startups, these paths to growth will be\\nthe ones that actually work.Airbnb waited 4 months after raising money at the end of Y\\xa0Combinator\\nbefore they hired their first employee. In the meantime the founders\\nwere terribly overworked. But they were overworked evolving Airbnb\\ninto the astonishingly successful organism it is now.Notes[1]\\nSteep usage growth will also interest investors. Revenue\\nwill ultimately be a constant multiple of usage, so x% usage growth\\npredicts x% revenue growth. But in practice investors discount\\nmerely predicted revenue, so if you\\'re measuring usage you need a\\nhigher growth rate to impress investors.[2]\\nStartups that don\\'t raise money are saved from hiring too\\nfast because they can\\'t afford to. But that doesn\\'t mean you should\\navoid raising money in order to avoid this problem, any more than\\nthat total abstinence is the only way to avoid becoming an alcoholic.[3]\\nI would not be surprised if VCs\\' tendency to push founders\\nto overhire is not even in their own interest. They don\\'t know how\\nmany of the companies that get killed by overspending might have\\ndone well if they\\'d survived. My guess is a significant number.[4]\\nAfter reading a draft, Sam Altman wrote:\"I think you should make the hiring point more strongly. I think\\nit\\'s roughly correct to say that YC\\'s most successful companies\\nhave never been the fastest to hire, and one of the marks of a great\\nfounder is being able to resist this urge.\"Paul Buchheit adds:\"A related problem that I see a lot is premature scaling—founders\\ntake a small business that isn\\'t really working (bad unit economics,\\ntypically) and then scale it up because they want impressive growth\\nnumbers. This is similar to over-hiring in that it makes the business\\nmuch harder to fix once it\\'s big, plus they are bleeding cash really\\nfast.\"\\nThanks to Sam Altman, Paul Buchheit, Joe Gebbia, Jessica Livingston,\\nand Geoff Ralston for reading drafts of this.', 'addiction.txt': 'July 2010What hard liquor, cigarettes, heroin, and crack have in common is\\nthat they\\'re all more concentrated forms of less addictive predecessors.\\nMost if not all the things we describe as addictive are. And the\\nscary thing is, the process that created them is accelerating.We wouldn\\'t want to stop it. It\\'s the same process that cures\\ndiseases: technological progress. Technological progress means\\nmaking things do more of what we want. When the thing we want is\\nsomething we want to want, we consider technological progress good.\\nIf some new technique makes solar cells x% more efficient, that\\nseems strictly better. When progress concentrates something we\\ndon\\'t want to want—when it transforms opium into heroin—it seems\\nbad. But it\\'s the same process at work.\\n[1]No one doubts this process is accelerating, which means increasing\\nnumbers of things we like will be transformed into things we like\\ntoo much.\\n[2]As far as I know there\\'s no word for something we like too much.\\nThe closest is the colloquial sense of \"addictive.\" That usage has\\nbecome increasingly common during my lifetime. And it\\'s clear why:\\nthere are an increasing number of things we need it for. At the\\nextreme end of the spectrum are crack and meth. Food has been\\ntransformed by a combination of factory farming and innovations in\\nfood processing into something with way more immediate bang for the\\nbuck, and you can see the results in any town in America. Checkers\\nand solitaire have been replaced by World of Warcraft and FarmVille.\\nTV has become much more engaging, and even so it can\\'t compete with Facebook.The world is more addictive than it was 40 years ago. And unless\\nthe forms of technological progress that produced these things are\\nsubject to different laws than technological progress in general,\\nthe world will get more addictive in the next 40 years than it did\\nin the last 40.The next 40 years will bring us some wonderful things. I don\\'t\\nmean to imply they\\'re all to be avoided. Alcohol is a dangerous\\ndrug, but I\\'d rather live in a world with wine than one without.\\nMost people can coexist with alcohol; but you have to be careful.\\nMore things we like will mean more things we have to be careful\\nabout.Most people won\\'t, unfortunately. Which means that as the world\\nbecomes more addictive, the two senses in which one can live a\\nnormal life will be driven ever further apart. One sense of \"normal\"\\nis statistically normal: what everyone else does. The other is the\\nsense we mean when we talk about the normal operating range of a\\npiece of machinery: what works best.These two senses are already quite far apart. Already someone\\ntrying to live well would seem eccentrically abstemious in most of\\nthe US. That phenomenon is only going to become more pronounced.\\nYou can probably take it as a rule of thumb from now on that if\\npeople don\\'t think you\\'re weird, you\\'re living badly.Societies eventually develop antibodies to addictive new things.\\nI\\'ve seen that happen with cigarettes. When cigarettes first\\nappeared, they spread the way an infectious disease spreads through\\na previously isolated population. Smoking rapidly became a\\n(statistically) normal thing. There were ashtrays everywhere. We\\nhad ashtrays in our house when I was a kid, even though neither of\\nmy parents smoked. You had to for guests.As knowledge spread about the dangers of smoking, customs changed.\\nIn the last 20 years, smoking has been transformed from something\\nthat seemed totally normal into a rather seedy habit: from something\\nmovie stars did in publicity shots to something small huddles of\\naddicts do outside the doors of office buildings. A lot of the\\nchange was due to legislation, of course, but the legislation\\ncouldn\\'t have happened if customs hadn\\'t already changed.It took a while though—on the order of 100 years. And unless the\\nrate at which social antibodies evolve can increase to match the\\naccelerating rate at which technological progress throws off new\\naddictions, we\\'ll be increasingly unable to rely on customs to\\nprotect us.\\n[3]\\nUnless we want to be canaries in the coal mine\\nof each new addiction—the people whose sad example becomes a\\nlesson to future generations—we\\'ll have to figure out for ourselves\\nwhat to avoid and how. It will actually become a reasonable strategy\\n(or a more reasonable strategy) to suspect \\neverything new.In fact, even that won\\'t be enough. We\\'ll have to worry not just\\nabout new things, but also about existing things becoming more\\naddictive. That\\'s what bit me. I\\'ve avoided most addictions, but\\nthe Internet got me because it became addictive while I was using\\nit.\\n[4]Most people I know have problems with Internet addiction. We\\'re\\nall trying to figure out our own customs for getting free of it.\\nThat\\'s why I don\\'t have an iPhone, for example; the last thing I\\nwant is for the Internet to follow me out into the world.\\n[5]\\nMy latest trick is taking long hikes. I used to think running was a\\nbetter form of exercise than hiking because it took less time. Now\\nthe slowness of hiking seems an advantage, because the longer I\\nspend on the trail, the longer I have to think without interruption.Sounds pretty eccentric, doesn\\'t it? It always will when you\\'re\\ntrying to solve problems where there are no customs yet to guide\\nyou. Maybe I can\\'t plead Occam\\'s razor; maybe I\\'m simply eccentric.\\nBut if I\\'m right about the acceleration of addictiveness, then this\\nkind of lonely squirming to avoid it will increasingly be the fate\\nof anyone who wants to get things done. We\\'ll increasingly be\\ndefined by what we say no to.\\nNotes[1]\\nCould you restrict technological progress to areas where you\\nwanted it? Only in a limited way, without becoming a police state.\\nAnd even then your restrictions would have undesirable side effects.\\n\"Good\" and \"bad\" technological progress aren\\'t sharply differentiated,\\nso you\\'d find you couldn\\'t slow the latter without also slowing the\\nformer. And in any case, as Prohibition and the \"war on drugs\"\\nshow, bans often do more harm than good.[2]\\nTechnology has always been accelerating. By Paleolithic\\nstandards, technology evolved at a blistering pace in the Neolithic\\nperiod.[3]\\nUnless we mass produce social customs. I suspect the recent\\nresurgence of evangelical Christianity in the US is partly a reaction\\nto drugs. In desperation people reach for the sledgehammer; if\\ntheir kids won\\'t listen to them, maybe they\\'ll listen to God. But\\nthat solution has broader consequences than just getting kids to\\nsay no to drugs. You end up saying no to \\nscience as well.\\nI worry we may be heading for a future in which only a few people\\nplot their own itinerary through no-land, while everyone else books\\na package tour. Or worse still, has one booked for them by the\\ngovernment.[4]\\nPeople commonly use the word \"procrastination\" to describe\\nwhat they do on the Internet. It seems to me too mild to describe\\nwhat\\'s happening as merely not-doing-work. We don\\'t call it\\nprocrastination when someone gets drunk instead of working.[5]\\nSeveral people have told me they like the iPad because it\\nlets them bring the Internet into situations where a laptop would\\nbe too conspicuous. In other words, it\\'s a hip flask. (This is\\ntrue of the iPhone too, of course, but this advantage isn\\'t as\\nobvious because it reads as a phone, and everyone\\'s used to those.)Thanks to Sam Altman, Patrick Collison, Jessica Livingston, and\\nRobert Morris for reading drafts of this.', 'avg.txt': '\\n\\nWant to start a startup? Get funded by\\nY Combinator.\\n\\n\\n\\n\\nApril 2001, rev. April 2003(This article is derived from a talk given at the 2001 Franz\\nDeveloper Symposium.)\\nIn the summer of 1995, my friend Robert Morris and I\\nstarted a startup called \\nViaweb. \\nOur plan was to write\\nsoftware that would let end users build online stores.\\nWhat was novel about this software, at the time, was\\nthat it ran on our server, using ordinary Web pages\\nas the interface.A lot of people could have been having this idea at the\\nsame time, of course, but as far as I know, Viaweb was\\nthe first Web-based application. It seemed such\\na novel idea to us that we named the company after it:\\nViaweb, because our software worked via the Web,\\ninstead of running on your desktop computer.Another unusual thing about this software was that it\\nwas written primarily in a programming language called\\nLisp. It was one of the first big end-user\\napplications to be written in Lisp, which up till then\\nhad been used mostly in universities and research labs. [1]The Secret WeaponEric Raymond has written an essay called \"How to Become a Hacker,\"\\nand in it, among other things, he tells would-be hackers what\\nlanguages they should learn. He suggests starting with Python and\\nJava, because they are easy to learn. The serious hacker will also\\nwant to learn C, in order to hack Unix, and Perl for system\\nadministration and cgi scripts. Finally, the truly serious hacker\\nshould consider learning Lisp:\\n\\n Lisp is worth learning for the profound enlightenment experience\\n you will have when you finally get it; that experience will make\\n you a better programmer for the rest of your days, even if you\\n never actually use Lisp itself a lot.\\n\\nThis is the same argument you tend to hear for learning Latin. It\\nwon\\'t get you a job, except perhaps as a classics professor, but\\nit will improve your mind, and make you a better writer in languages\\nyou do want to use, like English.But wait a minute. This metaphor doesn\\'t stretch that far. The\\nreason Latin won\\'t get you a job is that no one speaks it. If you\\nwrite in Latin, no one can understand you. But Lisp is a computer\\nlanguage, and computers speak whatever language you, the programmer,\\ntell them to.So if Lisp makes you a better programmer, like he says, why wouldn\\'t\\nyou want to use it? If a painter were offered a brush that would\\nmake him a better painter, it seems to me that he would want to\\nuse it in all his paintings, wouldn\\'t he? I\\'m not trying to make\\nfun of Eric Raymond here. On the whole, his advice is good. What\\nhe says about Lisp is pretty much the conventional wisdom. But\\nthere is a contradiction in the conventional wisdom: Lisp will\\nmake you a better programmer, and yet you won\\'t use it.Why not? Programming languages are just tools, after all. If Lisp\\nreally does yield better programs, you should use it. And if it\\ndoesn\\'t, then who needs it?This is not just a theoretical question. Software is a very\\ncompetitive business, prone to natural monopolies. A company that\\ngets software written faster and better will, all other things\\nbeing equal, put its competitors out of business. And when you\\'re\\nstarting a startup, you feel this very keenly. Startups tend to\\nbe an all or nothing proposition. You either get rich, or you get\\nnothing. In a startup, if you bet on the wrong technology, your\\ncompetitors will crush you.Robert and I both knew Lisp well, and we couldn\\'t see any reason\\nnot to trust our instincts and go with Lisp. We knew that everyone\\nelse was writing their software in C++ or Perl. But we also knew\\nthat that didn\\'t mean anything. If you chose technology that way,\\nyou\\'d be running Windows. When you choose technology, you have to\\nignore what other people are doing, and consider only what will\\nwork the best.This is especially true in a startup. In a big company, you can\\ndo what all the other big companies are doing. But a startup can\\'t\\ndo what all the other startups do. I don\\'t think a lot of people\\nrealize this, even in startups.The average big company grows at about ten percent a year. So if\\nyou\\'re running a big company and you do everything the way the\\naverage big company does it, you can expect to do as well as the\\naverage big company-- that is, to grow about ten percent a year.The same thing will happen if you\\'re running a startup, of course.\\nIf you do everything the way the average startup does it, you should\\nexpect average performance. The problem here is, average performance\\nmeans that you\\'ll go out of business. The survival rate for startups\\nis way less than fifty percent. So if you\\'re running a startup,\\nyou had better be doing something odd. If not, you\\'re in trouble.Back in 1995, we knew something that I don\\'t think our competitors\\nunderstood, and few understand even now: when you\\'re writing\\nsoftware that only has to run on your own servers, you can use\\nany language you want. When you\\'re writing desktop software,\\nthere\\'s a strong bias toward writing applications in the same\\nlanguage as the operating system. Ten years ago, writing applications\\nmeant writing applications in C. But with Web-based software,\\nespecially when you have the source code of both the language and\\nthe operating system, you can use whatever language you want.This new freedom is a double-edged sword, however. Now that you\\ncan use any language, you have to think about which one to use.\\nCompanies that try to pretend nothing has changed risk finding that\\ntheir competitors do not.If you can use any language, which do you use? We chose Lisp.\\nFor one thing, it was obvious that rapid development would be\\nimportant in this market. We were all starting from scratch, so\\na company that could get new features done before its competitors\\nwould have a big advantage. We knew Lisp was a really good language\\nfor writing software quickly, and server-based applications magnify\\nthe effect of rapid development, because you can release software\\nthe minute it\\'s done.If other companies didn\\'t want to use Lisp, so much the better.\\nIt might give us a technological edge, and we needed all the help\\nwe could get. When we started Viaweb, we had no experience in\\nbusiness. We didn\\'t know anything about marketing, or hiring\\npeople, or raising money, or getting customers. Neither of us had\\never even had what you would call a real job. The only thing we\\nwere good at was writing software. We hoped that would save us.\\nAny advantage we could get in the software department, we would\\ntake.So you could say that using Lisp was an experiment. Our hypothesis\\nwas that if we wrote our software in Lisp, we\\'d be able to get\\nfeatures done faster than our competitors, and also to do things\\nin our software that they couldn\\'t do. And because Lisp was so\\nhigh-level, we wouldn\\'t need a big development team, so our costs\\nwould be lower. If this were so, we could offer a better product\\nfor less money, and still make a profit. We would end up getting\\nall the users, and our competitors would get none, and eventually\\ngo out of business. That was what we hoped would happen, anyway.What were the results of this experiment? Somewhat surprisingly,\\nit worked. We eventually had many competitors, on the order of\\ntwenty to thirty of them, but none of their software could compete\\nwith ours. We had a wysiwyg online store builder that ran on the\\nserver and yet felt like a desktop application. Our competitors\\nhad cgi scripts. And we were always far ahead of them in features.\\nSometimes, in desperation, competitors would try to introduce\\nfeatures that we didn\\'t have. But with Lisp our development cycle\\nwas so fast that we could sometimes duplicate a new feature within\\na day or two of a competitor announcing it in a press release. By\\nthe time journalists covering the press release got round to calling\\nus, we would have the new feature too.It must have seemed to our competitors that we had some kind of\\nsecret weapon-- that we were decoding their Enigma traffic or\\nsomething. In fact we did have a secret weapon, but it was simpler\\nthan they realized. No one was leaking news of their features to\\nus. We were just able to develop software faster than anyone\\nthought possible.When I was about nine I happened to get hold of a copy of The Day\\nof the Jackal, by Frederick Forsyth. The main character is an\\nassassin who is hired to kill the president of France. The assassin\\nhas to get past the police to get up to an apartment that overlooks\\nthe president\\'s route. He walks right by them, dressed up as an\\nold man on crutches, and they never suspect him.Our secret weapon was similar. We wrote our software in a weird\\nAI language, with a bizarre syntax full of parentheses. For years\\nit had annoyed me to hear Lisp described that way. But now it\\nworked to our advantage. In business, there is nothing more valuable\\nthan a technical advantage your competitors don\\'t understand. In\\nbusiness, as in war, surprise is worth as much as force.And so, I\\'m a little embarrassed to say, I never said anything\\npublicly about Lisp while we were working on Viaweb. We never\\nmentioned it to the press, and if you searched for Lisp on our Web\\nsite, all you\\'d find were the titles of two books in my bio. This\\nwas no accident. A startup should give its competitors as little\\ninformation as possible. If they didn\\'t know what language our\\nsoftware was written in, or didn\\'t care, I wanted to keep it that\\nway.[2]The people who understood our technology best were the customers.\\nThey didn\\'t care what language Viaweb was written in either, but\\nthey noticed that it worked really well. It let them build great\\nlooking online stores literally in minutes. And so, by word of\\nmouth mostly, we got more and more users. By the end of 1996 we\\nhad about 70 stores online. At the end of 1997 we had 500. Six\\nmonths later, when Yahoo bought us, we had 1070 users. Today, as\\nYahoo Store, this software continues to dominate its market. It\\'s\\none of the more profitable pieces of Yahoo, and the stores built\\nwith it are the foundation of Yahoo Shopping. I left Yahoo in\\n1999, so I don\\'t know exactly how many users they have now, but\\nthe last I heard there were about 20,000.\\nThe Blub ParadoxWhat\\'s so great about Lisp? And if Lisp is so great, why doesn\\'t\\neveryone use it? These sound like rhetorical questions, but actually\\nthey have straightforward answers. Lisp is so great not because\\nof some magic quality visible only to devotees, but because it is\\nsimply the most powerful language available. And the reason everyone\\ndoesn\\'t use it is that programming languages are not merely\\ntechnologies, but habits of mind as well, and nothing changes\\nslower. Of course, both these answers need explaining.I\\'ll begin with a shockingly controversial statement: programming\\nlanguages vary in power.Few would dispute, at least, that high level languages are more\\npowerful than machine language. Most programmers today would agree\\nthat you do not, ordinarily, want to program in machine language.\\nInstead, you should program in a high-level language, and have a\\ncompiler translate it into machine language for you. This idea is\\neven built into the hardware now: since the 1980s, instruction sets\\nhave been designed for compilers rather than human programmers.Everyone knows it\\'s a mistake to write your whole program by hand\\nin machine language. What\\'s less often understood is that there\\nis a more general principle here: that if you have a choice of\\nseveral languages, it is, all other things being equal, a mistake\\nto program in anything but the most powerful one. [3]There are many exceptions to this rule. If you\\'re writing a program\\nthat has to work very closely with a program written in a certain\\nlanguage, it might be a good idea to write the new program in the\\nsame language. If you\\'re writing a program that only has to do\\nsomething very simple, like number crunching or bit manipulation,\\nyou may as well use a less abstract language, especially since it\\nmay be slightly faster. And if you\\'re writing a short, throwaway\\nprogram, you may be better off just using whatever language has\\nthe best library functions for the task. But in general, for\\napplication software, you want to be using the most powerful\\n(reasonably efficient) language you can get, and using anything\\nelse is a mistake, of exactly the same kind, though possibly in a\\nlesser degree, as programming in machine language.You can see that machine language is very low level. But, at least\\nas a kind of social convention, high-level languages are often all\\ntreated as equivalent. They\\'re not. Technically the term \"high-level\\nlanguage\" doesn\\'t mean anything very definite. There\\'s no dividing\\nline with machine languages on one side and all the high-level\\nlanguages on the other. Languages fall along a continuum [4] of\\nabstractness, from the most powerful all the way down to machine\\nlanguages, which themselves vary in power.Consider Cobol. Cobol is a high-level language, in the sense that\\nit gets compiled into machine language. Would anyone seriously\\nargue that Cobol is equivalent in power to, say, Python? It\\'s\\nprobably closer to machine language than Python.Or how about Perl 4? Between Perl 4 and Perl 5, lexical closures\\ngot added to the language. Most Perl hackers would agree that Perl\\n5 is more powerful than Perl 4. But once you\\'ve admitted that,\\nyou\\'ve admitted that one high level language can be more powerful\\nthan another. And it follows inexorably that, except in special\\ncases, you ought to use the most powerful you can get.This idea is rarely followed to its conclusion, though. After a\\ncertain age, programmers rarely switch languages voluntarily.\\nWhatever language people happen to be used to, they tend to consider\\njust good enough.Programmers get very attached to their favorite languages, and I\\ndon\\'t want to hurt anyone\\'s feelings, so to explain this point I\\'m\\ngoing to use a hypothetical language called Blub. Blub falls right\\nin the middle of the abstractness continuum. It is not the most\\npowerful language, but it is more powerful than Cobol or machine\\nlanguage.And in fact, our hypothetical Blub programmer wouldn\\'t use either\\nof them. Of course he wouldn\\'t program in machine language. That\\'s\\nwhat compilers are for. And as for Cobol, he doesn\\'t know how\\nanyone can get anything done with it. It doesn\\'t even have x (Blub\\nfeature of your choice).As long as our hypothetical Blub programmer is looking down the\\npower continuum, he knows he\\'s looking down. Languages less powerful\\nthan Blub are obviously less powerful, because they\\'re missing some\\nfeature he\\'s used to. But when our hypothetical Blub programmer\\nlooks in the other direction, up the power continuum, he doesn\\'t\\nrealize he\\'s looking up. What he sees are merely weird languages.\\nHe probably considers them about equivalent in power to Blub, but\\nwith all this other hairy stuff thrown in as well. Blub is good\\nenough for him, because he thinks in Blub.When we switch to the point of view of a programmer using any of\\nthe languages higher up the power continuum, however, we find that\\nhe in turn looks down upon Blub. How can you get anything done in\\nBlub? It doesn\\'t even have y.By induction, the only programmers in a position to see all the\\ndifferences in power between the various languages are those who\\nunderstand the most powerful one. (This is probably what Eric\\nRaymond meant about Lisp making you a better programmer.) You can\\'t\\ntrust the opinions of the others, because of the Blub paradox:\\nthey\\'re satisfied with whatever language they happen to use, because\\nit dictates the way they think about programs.I know this from my own experience, as a high school kid writing\\nprograms in Basic. That language didn\\'t even support recursion.\\nIt\\'s hard to imagine writing programs without using recursion, but\\nI didn\\'t miss it at the time. I thought in Basic. And I was a\\nwhiz at it. Master of all I surveyed.The five languages that Eric Raymond recommends to hackers fall at\\nvarious points on the power continuum. Where they fall relative\\nto one another is a sensitive topic. What I will say is that I\\nthink Lisp is at the top. And to support this claim I\\'ll tell you\\nabout one of the things I find missing when I look at the other\\nfour languages. How can you get anything done in them, I think,\\nwithout macros? [5]Many languages have something called a macro. But Lisp macros are\\nunique. And believe it or not, what they do is related to the\\nparentheses. The designers of Lisp didn\\'t put all those parentheses\\nin the language just to be different. To the Blub programmer, Lisp\\ncode looks weird. But those parentheses are there for a reason.\\nThey are the outward evidence of a fundamental difference between\\nLisp and other languages.Lisp code is made out of Lisp data objects. And not in the trivial\\nsense that the source files contain characters, and strings are\\none of the data types supported by the language. Lisp code, after\\nit\\'s read by the parser, is made of data structures that you can\\ntraverse.If you understand how compilers work, what\\'s really going on is\\nnot so much that Lisp has a strange syntax as that Lisp has no\\nsyntax. You write programs in the parse trees that get generated\\nwithin the compiler when other languages are parsed. But these\\nparse trees are fully accessible to your programs. You can write\\nprograms that manipulate them. In Lisp, these programs are called\\nmacros. They are programs that write programs.Programs that write programs? When would you ever want to do that?\\nNot very often, if you think in Cobol. All the time, if you think\\nin Lisp. It would be convenient here if I could give an example\\nof a powerful macro, and say there! how about that? But if I did,\\nit would just look like gibberish to someone who didn\\'t know Lisp;\\nthere isn\\'t room here to explain everything you\\'d need to know to\\nunderstand what it meant. In \\nAnsi Common Lisp I tried to move\\nthings along as fast as I could, and even so I didn\\'t get to macros\\nuntil page 160.But I think I can give a kind of argument that might be convincing.\\nThe source code of the Viaweb editor was probably about 20-25%\\nmacros. Macros are harder to write than ordinary Lisp functions,\\nand it\\'s considered to be bad style to use them when they\\'re not\\nnecessary. So every macro in that code is there because it has to\\nbe. What that means is that at least 20-25% of the code in this\\nprogram is doing things that you can\\'t easily do in any other\\nlanguage. However skeptical the Blub programmer might be about my\\nclaims for the mysterious powers of Lisp, this ought to make him\\ncurious. We weren\\'t writing this code for our own amusement. We\\nwere a tiny startup, programming as hard as we could in order to\\nput technical barriers between us and our competitors.A suspicious person might begin to wonder if there was some\\ncorrelation here. A big chunk of our code was doing things that\\nare very hard to do in other languages. The resulting software\\ndid things our competitors\\' software couldn\\'t do. Maybe there was\\nsome kind of connection. I encourage you to follow that thread.\\nThere may be more to that old man hobbling along on his crutches\\nthan meets the eye.Aikido for StartupsBut I don\\'t expect to convince anyone \\n(over 25) \\nto go out and learn\\nLisp. The purpose of this article is not to change anyone\\'s mind,\\nbut to reassure people already interested in using Lisp-- people\\nwho know that Lisp is a powerful language, but worry because it\\nisn\\'t widely used. In a competitive situation, that\\'s an advantage.\\nLisp\\'s power is multiplied by the fact that your competitors don\\'t\\nget it.If you think of using Lisp in a startup, you shouldn\\'t worry that\\nit isn\\'t widely understood. You should hope that it stays that\\nway. And it\\'s likely to. It\\'s the nature of programming languages\\nto make most people satisfied with whatever they currently use.\\nComputer hardware changes so much faster than personal habits that\\nprogramming practice is usually ten to twenty years behind the\\nprocessor. At places like MIT they were writing programs in\\nhigh-level languages in the early 1960s, but many companies continued\\nto write code in machine language well into the 1980s. I bet a\\nlot of people continued to write machine language until the processor,\\nlike a bartender eager to close up and go home, finally kicked them\\nout by switching to a risc instruction set.Ordinarily technology changes fast. But programming languages are\\ndifferent: programming languages are not just technology, but what\\nprogrammers think in. They\\'re half technology and half religion.[6]\\nAnd so the median language, meaning whatever language the median\\nprogrammer uses, moves as slow as an iceberg. Garbage collection,\\nintroduced by Lisp in about 1960, is now widely considered to be\\na good thing. Runtime typing, ditto, is growing in popularity.\\nLexical closures, introduced by Lisp in the early 1970s, are now,\\njust barely, on the radar screen. Macros, introduced by Lisp in the\\nmid 1960s, are still terra incognita.Obviously, the median language has enormous momentum. I\\'m not\\nproposing that you can fight this powerful force. What I\\'m proposing\\nis exactly the opposite: that, like a practitioner of Aikido, you\\ncan use it against your opponents.If you work for a big company, this may not be easy. You will have\\na hard time convincing the pointy-haired boss to let you build\\nthings in Lisp, when he has just read in the paper that some other\\nlanguage is poised, like Ada was twenty years ago, to take over\\nthe world. But if you work for a startup that doesn\\'t have\\npointy-haired bosses yet, you can, like we did, turn the Blub\\nparadox to your advantage: you can use technology that your\\ncompetitors, glued immovably to the median language, will never be\\nable to match.If you ever do find yourself working for a startup, here\\'s a handy\\ntip for evaluating competitors. Read their job listings. Everything\\nelse on their site may be stock photos or the prose equivalent,\\nbut the job listings have to be specific about what they want, or\\nthey\\'ll get the wrong candidates.During the years we worked on Viaweb I read a lot of job descriptions.\\nA new competitor seemed to emerge out of the woodwork every month\\nor so. The first thing I would do, after checking to see if they\\nhad a live online demo, was look at their job listings. After a\\ncouple years of this I could tell which companies to worry about\\nand which not to. The more of an IT flavor the job descriptions\\nhad, the less dangerous the company was. The safest kind were the\\nones that wanted Oracle experience. You never had to worry about\\nthose. You were also safe if they said they wanted C++ or Java\\ndevelopers. If they wanted Perl or Python programmers, that would\\nbe a bit frightening-- that\\'s starting to sound like a company\\nwhere the technical side, at least, is run by real hackers. If I\\nhad ever seen a job posting looking for Lisp hackers, I would have\\nbeen really worried.\\nNotes[1] Viaweb at first had two parts: the editor, written in Lisp,\\nwhich people used to build their sites, and the ordering system,\\nwritten in C, which handled orders. The first version was mostly\\nLisp, because the ordering system was small. Later we added two\\nmore modules, an image generator written in C, and a back-office\\nmanager written mostly in Perl.In January 2003, Yahoo released a new version of the editor \\nwritten in C++ and Perl. It\\'s hard to say whether the program is no\\nlonger written in Lisp, though, because to translate this program\\ninto C++ they literally had to write a Lisp interpreter: the source\\nfiles of all the page-generating templates are still, as far as I\\nknow, Lisp code. (See Greenspun\\'s Tenth Rule.)[2] Robert Morris says that I didn\\'t need to be secretive, because\\neven if our competitors had known we were using Lisp, they wouldn\\'t\\nhave understood why: \"If they were that smart they\\'d already be\\nprogramming in Lisp.\"[3] All languages are equally powerful in the sense of being Turing\\nequivalent, but that\\'s not the sense of the word programmers care\\nabout. (No one wants to program a Turing machine.) The kind of\\npower programmers care about may not be formally definable, but\\none way to explain it would be to say that it refers to features\\nyou could only get in the less powerful language by writing an\\ninterpreter for the more powerful language in it. If language A\\nhas an operator for removing spaces from strings and language B\\ndoesn\\'t, that probably doesn\\'t make A more powerful, because you\\ncan probably write a subroutine to do it in B. But if A supports,\\nsay, recursion, and B doesn\\'t, that\\'s not likely to be something\\nyou can fix by writing library functions.[4] Note to nerds: or possibly a lattice, narrowing toward the top;\\nit\\'s not the shape that matters here but the idea that there is at\\nleast a partial order.[5] It is a bit misleading to treat macros as a separate feature.\\nIn practice their usefulness is greatly enhanced by other Lisp\\nfeatures like lexical closures and rest parameters.[6] As a result, comparisons of programming languages either take\\nthe form of religious wars or undergraduate textbooks so determinedly\\nneutral that they\\'re really works of anthropology. People who\\nvalue their peace, or want tenure, avoid the topic. But the question\\nis only half a religious one; there is something there worth\\nstudying, especially if you want to design new languages.', 'before.txt': '\\n\\nWant to start a startup? Get funded by\\nY Combinator.\\n\\n\\n\\n\\nOctober 2014(This essay is derived from a guest lecture in Sam Altman\\'s startup class at\\nStanford. It\\'s intended for college students, but much of it is\\napplicable to potential founders at other ages.)One of the advantages of having kids is that when you have to give\\nadvice, you can ask yourself \"what would I tell my own kids?\" My\\nkids are little, but I can imagine what I\\'d tell them about startups\\nif they were in college, and that\\'s what I\\'m going to tell you.Startups are very counterintuitive. I\\'m not sure why. Maybe it\\'s\\njust because knowledge about them hasn\\'t permeated our culture yet.\\nBut whatever the reason, starting a startup is a task where you\\ncan\\'t always trust your instincts.It\\'s like skiing in that way. When you first try skiing and you\\nwant to slow down, your instinct is to lean back. But if you lean\\nback on skis you fly down the hill out of control. So part of\\nlearning to ski is learning to suppress that impulse. Eventually\\nyou get new habits, but at first it takes a conscious effort. At\\nfirst there\\'s a list of things you\\'re trying to remember as you\\nstart down the hill.Startups are as unnatural as skiing, so there\\'s a similar list for\\nstartups. Here I\\'m going to give you the first part of it — the things\\nto remember if you want to prepare yourself to start a startup.\\nCounterintuitiveThe first item on it is the fact I already mentioned: that startups\\nare so weird that if you trust your instincts, you\\'ll make a lot\\nof mistakes. If you know nothing more than this, you may at least\\npause before making them.When I was running Y Combinator I used to joke that our function\\nwas to tell founders things they would ignore. It\\'s really true.\\nBatch after batch, the YC partners warn founders about mistakes\\nthey\\'re about to make, and the founders ignore them, and then come\\nback a year later and say \"I wish we\\'d listened.\"Why do the founders ignore the partners\\' advice? Well, that\\'s the\\nthing about counterintuitive ideas: they contradict your intuitions.\\nThey seem wrong. So of course your first impulse is to disregard\\nthem. And in fact my joking description is not merely the curse\\nof Y Combinator but part of its raison d\\'etre. If founders\\' instincts\\nalready gave them the right answers, they wouldn\\'t need us. You\\nonly need other people to give you advice that surprises you. That\\'s\\nwhy there are a lot of ski instructors and not many running\\ninstructors.\\n[1]You can, however, trust your instincts about people. And in fact\\none of the most common mistakes young founders make is not to\\ndo that enough. They get involved with people who seem impressive,\\nbut about whom they feel some misgivings personally. Later when\\nthings blow up they say \"I knew there was something off about him,\\nbut I ignored it because he seemed so impressive.\"If you\\'re thinking about getting involved with someone — as a\\ncofounder, an employee, an investor, or an acquirer — and you\\nhave misgivings about them, trust your gut. If someone seems\\nslippery, or bogus, or a jerk, don\\'t ignore it.This is one case where it pays to be self-indulgent. Work with\\npeople you genuinely like, and you\\'ve known long enough to be sure.\\nExpertiseThe second counterintuitive point is that it\\'s not that important\\nto know a lot about startups. The way to succeed in a startup is\\nnot to be an expert on startups, but to be an expert on your users\\nand the problem you\\'re solving for them.\\nMark Zuckerberg didn\\'t succeed because he was an expert on startups.\\nHe succeeded despite being a complete noob at startups, because he\\nunderstood his users really well.If you don\\'t know anything about, say, how to raise an angel round,\\ndon\\'t feel bad on that account. That sort of thing you can learn\\nwhen you need to, and forget after you\\'ve done it.In fact, I worry it\\'s not merely unnecessary to learn in great\\ndetail about the mechanics of startups, but possibly somewhat\\ndangerous. If I met an undergrad who knew all about convertible\\nnotes and employee agreements and (God forbid) class FF stock, I\\nwouldn\\'t think \"here is someone who is way ahead of their peers.\"\\nIt would set off alarms. Because another of the characteristic\\nmistakes of young founders is to go through the motions of starting\\na startup. They make up some plausible-sounding idea, raise money\\nat a good valuation, rent a cool office, hire a bunch of people.\\nFrom the outside that seems like what startups do. But the next\\nstep after rent a cool office and hire a bunch of people is: gradually\\nrealize how completely fucked they are, because while imitating all\\nthe outward forms of a startup they have neglected the one thing\\nthat\\'s actually essential: making something people want.\\nGameWe saw this happen so often that we made up a name for it: playing\\nhouse. Eventually I realized why it was happening. The reason\\nyoung founders go through the motions of starting a startup is\\nbecause that\\'s what they\\'ve been trained to do for their whole lives\\nup to that point. Think about what you have to do to get into\\ncollege, for example. Extracurricular activities, check. Even in\\ncollege classes most of the work is as artificial as running laps.I\\'m not attacking the educational system for being this way. There\\nwill always be a certain amount of fakeness in the work you do when\\nyou\\'re being taught something, and if you measure their performance\\nit\\'s inevitable that people will exploit the difference to the point\\nwhere much of what you\\'re measuring is artifacts of the fakeness.I confess I did it myself in college. I found that in a lot of\\nclasses there might only be 20 or 30 ideas that were the right shape\\nto make good exam questions. The way I studied for exams in these\\nclasses was not (except incidentally) to master the material taught\\nin the class, but to make a list of potential exam questions and\\nwork out the answers in advance. When I walked into the final, the\\nmain thing I\\'d be feeling was curiosity about which of my questions\\nwould turn up on the exam. It was like a game.It\\'s not surprising that after being trained for their whole lives\\nto play such games, young founders\\' first impulse on starting a\\nstartup is to try to figure out the tricks for winning at this new\\ngame. Since fundraising appears to be the measure of success for\\nstartups (another classic noob mistake), they always want to know what the\\ntricks are for convincing investors. We tell them the best way to\\nconvince investors is to make a startup\\nthat\\'s actually doing well, meaning growing fast, and then simply\\ntell investors so. Then they want to know what the tricks are for\\ngrowing fast. And we have to tell them the best way to do that is\\nsimply to make something people want.So many of the conversations YC partners have with young founders\\nbegin with the founder asking \"How do we...\" and the partner replying\\n\"Just...\"Why do the founders always make things so complicated? The reason,\\nI realized, is that they\\'re looking for the trick.So this is the third counterintuitive thing to remember about\\nstartups: starting a startup is where gaming the system stops\\nworking. Gaming the system may continue to work if you go to work\\nfor a big company. Depending on how broken the company is, you can\\nsucceed by sucking up to the right people, giving the impression\\nof productivity, and so on. \\n[2]\\nBut that doesn\\'t work with startups.\\nThere is no boss to trick, only users, and all users care about is\\nwhether your product does what they want. Startups are as impersonal\\nas physics. You have to make something people want, and you prosper\\nonly to the extent you do.The dangerous thing is, faking does work to some degree on investors.\\nIf you\\'re super good at sounding like you know what you\\'re talking\\nabout, you can fool investors for at least one and perhaps even two\\nrounds of funding. But it\\'s not in your interest to. The company\\nis ultimately doomed. All you\\'re doing is wasting your own time\\nriding it down.So stop looking for the trick. There are tricks in startups, as\\nthere are in any domain, but they are an order of magnitude less\\nimportant than solving the real problem. A founder who knows nothing\\nabout fundraising but has made something users love will have an\\neasier time raising money than one who knows every trick in the\\nbook but has a flat usage graph. And more importantly, the founder\\nwho has made something users love is the one who will go on to\\nsucceed after raising the money.Though in a sense it\\'s bad news in that you\\'re deprived of one of\\nyour most powerful weapons, I think it\\'s exciting that gaming the\\nsystem stops working when you start a startup. It\\'s exciting that\\nthere even exist parts of the world where you win by doing good\\nwork. Imagine how depressing the world would be if it were all\\nlike school and big companies, where you either have to spend a lot\\nof time on bullshit things or lose to people who do.\\n[3]\\nI would\\nhave been delighted if I\\'d realized in college that there were parts\\nof the real world where gaming the system mattered less than others,\\nand a few where it hardly mattered at all. But there are, and this\\nvariation is one of the most important things to consider when\\nyou\\'re thinking about your future. How do you win in each type of\\nwork, and what would you like to win by doing?\\n[4]\\nAll-ConsumingThat brings us to our fourth counterintuitive point: startups are\\nall-consuming. If you start a startup, it will take over your life\\nto a degree you cannot imagine. And if your startup succeeds, it\\nwill take over your life for a long time: for several years at the\\nvery least, maybe for a decade, maybe for the rest of your working\\nlife. So there is a real opportunity cost here.Larry Page may seem to have an enviable life, but there are aspects\\nof it that are unenviable. Basically at 25 he started running as\\nfast as he could and it must seem to him that he hasn\\'t stopped to\\ncatch his breath since. Every day new shit happens in the Google\\nempire that only the CEO can deal with, and he, as CEO, has to deal\\nwith it. If he goes on vacation for even a week, a whole week\\'s\\nbacklog of shit accumulates. And he has to bear this uncomplainingly,\\npartly because as the company\\'s daddy he can never show fear or\\nweakness, and partly because billionaires get less than zero sympathy\\nif they talk about having difficult lives. Which has the strange\\nside effect that the difficulty of being a successful startup founder\\nis concealed from almost everyone except those who\\'ve done it.Y Combinator has now funded several companies that can be called\\nbig successes, and in every single case the founders say the same\\nthing. It never gets any easier. The nature of the problems change.\\nYou\\'re worrying about construction delays at your London office\\ninstead of the broken air conditioner in your studio apartment.\\nBut the total volume of worry never decreases; if anything it\\nincreases.Starting a successful startup is similar to having kids in that\\nit\\'s like a button you push that changes your life irrevocably.\\nAnd while it\\'s truly wonderful having kids, there are a lot of\\nthings that are easier to do before you have them than after. Many\\nof which will make you a better parent when you do have kids. And\\nsince you can delay pushing the button for a while, most people in\\nrich countries do.Yet when it comes to startups, a lot of people seem to think they\\'re\\nsupposed to start them while they\\'re still in college. Are you\\ncrazy? And what are the universities thinking? They go out of\\ntheir way to ensure their students are well supplied with contraceptives,\\nand yet they\\'re setting up entrepreneurship programs and startup\\nincubators left and right.To be fair, the universities have their hand forced here. A lot\\nof incoming students are interested in startups. Universities are,\\nat least de facto, expected to prepare them for their careers. So\\nstudents who want to start startups hope universities can teach\\nthem about startups. And whether universities can do this or not,\\nthere\\'s some pressure to claim they can, lest they lose applicants\\nto other universities that do.Can universities teach students about startups? Yes and no. They\\ncan teach students about startups, but as I explained before, this\\nis not what you need to know. What you need to learn about are the\\nneeds of your own users, and you can\\'t do that until you actually\\nstart the company.\\n[5]\\nSo starting a startup is intrinsically\\nsomething you can only really learn by doing it. And it\\'s impossible\\nto do that in college, for the reason I just explained: startups\\ntake over your life. You can\\'t start a startup for real as a\\nstudent, because if you start a startup for real you\\'re not a student\\nanymore. You may be nominally a student for a bit, but you won\\'t even\\nbe that for long.\\n[6]Given this dichotomy, which of the two paths should you take? Be\\na real student and not start a startup, or start a real startup and\\nnot be a student? I can answer that one for you. Do not start a\\nstartup in college. How to start a startup is just a subset of a\\nbigger problem you\\'re trying to solve: how to have a good life.\\nAnd though starting a startup can be part of a good life for a lot\\nof ambitious people, age 20 is not the optimal time to do it.\\nStarting a startup is like a brutally fast depth-first search. Most\\npeople should still be searching breadth-first at 20.You can do things in your early 20s that you can\\'t do as well before\\nor after, like plunge deeply into projects on a whim and travel\\nsuper cheaply with no sense of a deadline. For unambitious people,\\nthis sort of thing is the dreaded \"failure to launch,\" but for the\\nambitious ones it can be an incomparably valuable sort of exploration.\\nIf you start a startup at 20 and you\\'re sufficiently successful,\\nyou\\'ll never get to do it.\\n[7]Mark Zuckerberg will never get to bum around a foreign country. He\\ncan do other things most people can\\'t, like charter jets to fly him\\nto foreign countries. But success has taken a lot of the serendipity\\nout of his life. Facebook is running him as much as he\\'s running\\nFacebook. And while it can be very cool to be in the grip of a\\nproject you consider your life\\'s work, there are advantages to\\nserendipity too, especially early in life. Among other things it\\ngives you more options to choose your life\\'s work from.There\\'s not even a tradeoff here. You\\'re not sacrificing anything\\nif you forgo starting a startup at 20, because you\\'re more likely\\nto succeed if you wait. In the unlikely case that you\\'re 20 and\\none of your side projects takes off like Facebook did, you\\'ll face\\na choice of running with it or not, and it may be reasonable to run\\nwith it. But the usual way startups take off is for the founders\\nto make them take off, and it\\'s gratuitously\\nstupid to do that at 20.\\nTryShould you do it at any age? I realize I\\'ve made startups sound\\npretty hard. If I haven\\'t, let me try again: starting a startup\\nis really hard. What if it\\'s too hard? How can you tell if you\\'re\\nup to this challenge?The answer is the fifth counterintuitive point: you can\\'t tell. Your\\nlife so far may have given you some idea what your prospects might\\nbe if you tried to become a mathematician, or a professional football\\nplayer. But unless you\\'ve had a very strange life you haven\\'t done\\nmuch that was like being a startup founder.\\nStarting a startup will change you a lot. So what you\\'re trying\\nto estimate is not just what you are, but what you could grow into,\\nand who can do that?For the past 9 years it was my job to predict whether people would\\nhave what it took to start successful startups. It was easy to\\ntell how smart they were, and most people reading this will be over\\nthat threshold. The hard part was predicting how tough and ambitious they would become. There\\nmay be no one who has more experience at trying to predict that,\\nso I can tell you how much an expert can know about it, and the\\nanswer is: not much. I learned to keep a completely open mind about\\nwhich of the startups in each batch would turn out to be the stars.The founders sometimes think they know. Some arrive feeling sure\\nthey will ace Y Combinator just as they\\'ve aced every one of the (few,\\nartificial, easy) tests they\\'ve faced in life so far. Others arrive\\nwondering how they got in, and hoping YC doesn\\'t discover whatever\\nmistake caused it to accept them. But there is little correlation\\nbetween founders\\' initial attitudes and how well their companies\\ndo.I\\'ve read that the same is true in the military — that the\\nswaggering recruits are no more likely to turn out to be really\\ntough than the quiet ones. And probably for the same reason: that\\nthe tests involved are so different from the ones in their previous\\nlives.If you\\'re absolutely terrified of starting a startup, you probably\\nshouldn\\'t do it. But if you\\'re merely unsure whether you\\'re up to\\nit, the only way to find out is to try. Just not now.\\nIdeasSo if you want to start a startup one day, what should you do in\\ncollege? There are only two things you need initially: an idea and\\ncofounders. And the m.o. for getting both is the same. Which leads\\nto our sixth and last counterintuitive point: that the way to get\\nstartup ideas is not to try to think of startup ideas.I\\'ve written a whole essay on this,\\nso I won\\'t repeat it all here. But the short version is that if\\nyou make a conscious effort to think of startup ideas, the ideas\\nyou come up with will not merely be bad, but bad and plausible-sounding,\\nmeaning you\\'ll waste a lot of time on them before realizing they\\'re\\nbad.The way to come up with good startup ideas is to take a step back.\\nInstead of making a conscious effort to think of startup ideas,\\nturn your mind into the type that startup ideas form in without any\\nconscious effort. In fact, so unconsciously that you don\\'t even\\nrealize at first that they\\'re startup ideas.This is not only possible, it\\'s how Apple, Yahoo, Google, and\\nFacebook all got started. None of these companies were even meant\\nto be companies at first. They were all just side projects. The\\nbest startups almost have to start as side projects, because great\\nideas tend to be such outliers that your conscious mind would reject\\nthem as ideas for companies.Ok, so how do you turn your mind into the type that startup ideas\\nform in unconsciously? (1) Learn a lot about things that matter,\\nthen (2) work on problems that interest you (3) with people you\\nlike and respect. The third part, incidentally, is how you get\\ncofounders at the same time as the idea.The first time I wrote that paragraph, instead of \"learn a lot about\\nthings that matter,\" I wrote \"become good at some technology.\" But\\nthat prescription, though sufficient, is too narrow. What was\\nspecial about Brian Chesky and Joe Gebbia was not that they were\\nexperts in technology. They were good at design, and perhaps even\\nmore importantly, they were good at organizing groups and making\\nprojects happen. So you don\\'t have to work on technology per se,\\nso long as you work on problems demanding enough to stretch you.What kind of problems are those? That is very hard to answer in\\nthe general case. History is full of examples of young people who\\nwere working on important problems that no\\none else at the time thought were important, and in particular\\nthat their parents didn\\'t think were important. On the other hand,\\nhistory is even fuller of examples of parents who thought their\\nkids were wasting their time and who were right. So how do you\\nknow when you\\'re working on real stuff?\\n[8]I know how I know. Real problems are interesting, and I am\\nself-indulgent in the sense that I always want to work on interesting\\nthings, even if no one else cares about them (in fact, especially\\nif no one else cares about them), and find it very hard to make\\nmyself work on boring things, even if they\\'re supposed to be\\nimportant.My life is full of case after case where I worked on something just\\nbecause it seemed interesting, and it turned out later to be useful\\nin some worldly way. Y\\nCombinator itself was something I only did because it seemed\\ninteresting. So I seem to have some sort of internal compass that\\nhelps me out. But I don\\'t know what other people have in their\\nheads. Maybe if I think more about this I can come up with heuristics\\nfor recognizing genuinely interesting problems, but for the moment\\nthe best I can offer is the hopelessly question-begging advice that\\nif you have a taste for genuinely interesting problems, indulging\\nit energetically is the best way to prepare yourself for a startup.\\nAnd indeed, probably also the best way to live.\\n[9]But although I can\\'t explain in the general case what counts as an\\ninteresting problem, I can tell you about a large subset of them.\\nIf you think of technology as something that\\'s spreading like a\\nsort of fractal stain, every moving point on the edge represents\\nan interesting problem. So one guaranteed way to turn your mind\\ninto the type that has good startup ideas is to get yourself to the\\nleading edge of some technology — to cause yourself, as Paul\\nBuchheit put it, to \"live in the future.\" When you reach that point,\\nideas that will seem to other people uncannily prescient will seem\\nobvious to you. You may not realize they\\'re startup ideas, but\\nyou\\'ll know they\\'re something that ought to exist.For example, back at Harvard in the mid 90s a fellow grad student\\nof my friends Robert and Trevor wrote his own voice over IP software.\\nHe didn\\'t mean it to be a startup, and he never tried to turn it\\ninto one. He just wanted to talk to his girlfriend in Taiwan without\\npaying for long distance calls, and since he was an expert on\\nnetworks it seemed obvious to him that the way to do it was turn\\nthe sound into packets and ship it over the Internet. He never did\\nany more with his software than talk to his girlfriend, but this\\nis exactly the way the best startups get started.So strangely enough the optimal thing to do in college if you want\\nto be a successful startup founder is not some sort of new, vocational\\nversion of college focused on \"entrepreneurship.\" It\\'s the classic\\nversion of college as education for its own sake. If you want to\\nstart a startup after college, what you should do in college is\\nlearn powerful things. And if you have genuine intellectual\\ncuriosity, that\\'s what you\\'ll naturally tend to do if you just\\nfollow your own inclinations.\\n[10]The component of entrepreneurship that really matters is domain\\nexpertise. The way to become Larry Page was to become an expert\\non search. And the way to become an expert on search was to be\\ndriven by genuine curiosity, not some ulterior motive.At its best, starting a startup is merely an ulterior motive for\\ncuriosity. And you\\'ll do it best if you introduce the ulterior\\nmotive toward the end of the process.So here is the ultimate advice for young would-be startup founders,\\nboiled down to two words: just learn.\\nNotes[1]\\nSome founders listen more than others, and this tends to be a\\npredictor of success. One of the things I\\nremember about the Airbnbs during YC is how intently they listened.[2]\\nIn fact, this is one of the reasons startups are possible. If\\nbig companies weren\\'t plagued by internal inefficiencies, they\\'d\\nbe proportionately more effective, leaving less room for startups.[3]\\nIn a startup you have to spend a lot of time on schleps, but this sort of work is merely\\nunglamorous, not bogus.[4]\\nWhat should you do if your true calling is gaming the system?\\nManagement consulting.[5]\\nThe company may not be incorporated, but if you start to get\\nsignificant numbers of users, you\\'ve started it, whether you realize\\nit yet or not.[6]\\nIt shouldn\\'t be that surprising that colleges can\\'t teach\\nstudents how to be good startup founders, because they can\\'t teach\\nthem how to be good employees either.The way universities \"teach\" students how to be employees is to\\nhand off the task to companies via internship programs. But you\\ncouldn\\'t do the equivalent thing for startups, because by definition\\nif the students did well they would never come back.[7]\\nCharles Darwin was 22 when he received an invitation to travel\\naboard the HMS Beagle as a naturalist. It was only because he was\\notherwise unoccupied, to a degree that alarmed his family, that he\\ncould accept it. And yet if he hadn\\'t we probably would not know\\nhis name.[8]\\nParents can sometimes be especially conservative in this\\ndepartment. There are some whose definition of important problems\\nincludes only those on the critical path to med school.[9]\\nI did manage to think of a heuristic for detecting whether you\\nhave a taste for interesting ideas: whether you find known boring\\nideas intolerable. Could you endure studying literary theory, or\\nworking in middle management at a large company?[10]\\nIn fact, if your goal is to start a startup, you can stick\\neven more closely to the ideal of a liberal education than past\\ngenerations have. Back when students focused mainly on getting a\\njob after college, they thought at least a little about how the\\ncourses they took might look to an employer. And perhaps even\\nworse, they might shy away from taking a difficult class lest they\\nget a low grade, which would harm their all-important GPA. Good\\nnews: users don\\'t care what your GPA\\nwas. And I\\'ve never heard of investors caring either. Y Combinator\\ncertainly never asks what classes you took in college or what grades\\nyou got in them.\\nThanks to Sam Altman, Paul Buchheit, John Collison, Patrick\\nCollison, Jessica Livingston, Robert Morris, Geoff Ralston, and\\nFred Wilson for reading drafts of this.'}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 2) Create a shared store (dict) for Node/Flow data exchange.\n",
|
|
"# This can be replaced with a DB or other storage.\n",
|
|
"# Design the structure / schema based on the app requirements.\n",
|
|
"shared = {\"data\": {}, \"summary\": {}}\n",
|
|
"\n",
|
|
"# 3) Create a Node that loads data from disk into shared['data'].\n",
|
|
"class LoadData(Node):\n",
|
|
" # For compute-intensive operations, do them in prep().\n",
|
|
" def prep(self, shared):\n",
|
|
" path = \"/content/miniLLMFlow/data/PaulGrahamEssaysLarge\"\n",
|
|
" for filename in os.listdir(path):\n",
|
|
" with open(os.path.join(path, filename), 'r') as f:\n",
|
|
" shared['data'][filename] = f.read()\n",
|
|
" # If LLM was needed, we'd handle it in exec(). Not needed here.\n",
|
|
" # (idempotent so it can be retried if needed)\n",
|
|
" def exec(self,prep_res): pass\n",
|
|
" # post() can update shared again or decide the next node (by return the action).\n",
|
|
" def post(self,shared,prep_res,exec_res): pass\n",
|
|
"\n",
|
|
"load_data = LoadData()\n",
|
|
"# Run the data-loading node once\n",
|
|
"load_data.run(shared)\n",
|
|
"print(shared['data'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "M0Rfq5vEr38N",
|
|
"outputId": "ff2b49a9-d114-4f10-ebed-81273ef10557"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{'addiction.txt': 'Technological progress increases addictiveness in society with both good and bad effects.'}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 4) Create a Node that summarizes a single file using the LLM.\n",
|
|
"class SummarizeFile(Node):\n",
|
|
" def prep(self, shared):\n",
|
|
" # Use self.params (which must remain immutable during prep/exec/post).\n",
|
|
" # Typically, we only store identifying info in params (e.g., filename).\n",
|
|
" content = shared['data'][self.params['filename']]\n",
|
|
" return content\n",
|
|
" def exec(self, prep_res):\n",
|
|
" content = prep_res\n",
|
|
" prompt = f\"{content} Respond a summary of above in 10 words\"\n",
|
|
" summary = call_llm(prompt)\n",
|
|
" return summary\n",
|
|
" def post(self, shared, prep_res, exec_res):\n",
|
|
" shared[\"summary\"][self.params['filename']] = exec_res\n",
|
|
"\n",
|
|
"summarize_file = SummarizeFile()\n",
|
|
"# For testing, we set params directly on the node.\n",
|
|
"# In real usage, you'd set them in a Flow or BatchFlow.\n",
|
|
"summarize_file.set_params({\"filename\":\"addiction.txt\"})\n",
|
|
"summarize_file.run(shared)\n",
|
|
"print(shared['summary'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "m3H8Jboar38N",
|
|
"outputId": "01a19d77-2d07-4a13-9d2c-34a3089f312a"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{'addiction.txt': 'Technological progress increases addictiveness in society with both good and bad effects.', 'before.txt': 'Startups demand instinct, product expertise, commitment, hard work, and learning.'}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 5) If data is large, we can apply a map-reduce pattern:\n",
|
|
"# - MapSummaries(BatchNode) => chunk the file and summarize each chunk\n",
|
|
"# - ReduceSummaries(Node) => combine those chunk-level summaries\n",
|
|
"class MapSummaries(BatchNode):\n",
|
|
" def prep(self, shared):\n",
|
|
" content = shared['data'][self.params['filename']]\n",
|
|
" chunk_size = 10000\n",
|
|
" chunks = [content[i:i+chunk_size] for i in range(0, len(content), chunk_size)]\n",
|
|
" # Must return an iterable (list or generator) for a BatchNode.\n",
|
|
" return chunks\n",
|
|
" def exec(self, prep_res):\n",
|
|
" # Each iteration of prep_res corresponds to a single chunk.\n",
|
|
" chunk = prep_res\n",
|
|
" prompt = f\"{chunk} Respond a summary of above in 10 words\"\n",
|
|
" summary = call_llm(prompt)\n",
|
|
" return summary\n",
|
|
" def post(self, shared, prep_res, exec_res):\n",
|
|
" # exec_res is a list of exec() results (summaries for each chunk).\n",
|
|
" combined_summary = [f\"{i}. {summary}\" for i, summary in enumerate(exec_res)]\n",
|
|
" shared[\"summary\"][self.params['filename']] = combined_summary\n",
|
|
"\n",
|
|
"class ReduceSummaries(Node):\n",
|
|
" def prep(self, shared):\n",
|
|
" # Retrieve the list of chunk summaries from shared storage\n",
|
|
" return shared[\"summary\"][self.params['filename']]\n",
|
|
" def exec(self, prep_res):\n",
|
|
" combined_summary = prep_res\n",
|
|
" prompt = f\"{combined_summary} Respond a summary of above in 10 words\"\n",
|
|
" summary = call_llm(prompt)\n",
|
|
" return summary\n",
|
|
" def post(self, shared, prep_res, exec_res):\n",
|
|
" # Store the combined summary as the final summary for this file.\n",
|
|
" shared[\"summary\"][self.params['filename']] = exec_res\n",
|
|
"\n",
|
|
"map_summaries = MapSummaries()\n",
|
|
"reduce_summaries = ReduceSummaries()\n",
|
|
"# Link map_summaries to reduce_summaries with an action\n",
|
|
"# By default, the action is \"default\" (when post returns None, it takes \"default\" action)\n",
|
|
"# This is the same as map_summaries - \"default\" >> reduce_summaries\n",
|
|
"map_summaries >> reduce_summaries\n",
|
|
"\n",
|
|
"# We don't directly call map_summaries.run(shared),\n",
|
|
"# because that alone would process only the map step without reduce.\n",
|
|
"\n",
|
|
"# 6) Instead, create a Flow that starts from map_summaries (a Node)\n",
|
|
"# and automatically includes reduce_summaries.\n",
|
|
"# Note: A Flow can also start from any other Flow or BatchFlow.\n",
|
|
"\n",
|
|
"\n",
|
|
"file_summary_flow = Flow(start=map_summaries)\n",
|
|
"# When a flow params is set, it will recursively set its params to all nodes in the flow\n",
|
|
"file_summary_flow.set_params({\"filename\":\"before.txt\"})\n",
|
|
"file_summary_flow.run(shared)\n",
|
|
"print(shared['summary'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "EpbJHFnFr38O",
|
|
"outputId": "bc00ff5e-16fd-44a2-eb12-d78d8b6af9b6"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{'addiction.txt': 'Tech advances unintentionally boost growth and spread of addictive behaviors.', 'before.txt': 'Startup success needs user understanding, team collaboration, time, and curiosity.', 'apple.txt': \"Apple's App Store approval processes hinder innovation in handheld development.\", 'aord.txt': 'Founders must determine if their startup is thriving or failing.', 'avg.txt': \"Lisp's power and efficiency facilitated faster development in Viaweb.\"}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 7) Summarize all files using a BatchFlow that reruns file_summary_flow for each file\n",
|
|
"class SummarizeAllFiles(BatchFlow):\n",
|
|
" def prep(self, shared):\n",
|
|
" # Return a list of parameters to apply in each flow iteration.\n",
|
|
" # Each individual param will be merged with this node's own params\n",
|
|
" # Allowing nesting of multi-level BatchFlow.\n",
|
|
" # E.g., first level diretcory, second level file.\n",
|
|
" return [{\"filename\":filename} for filename in shared['data']]\n",
|
|
"\n",
|
|
"summarize_all_files = SummarizeAllFiles(start=file_summary_flow)\n",
|
|
"summarize_all_files.run(shared)\n",
|
|
"print(shared['summary'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/",
|
|
"height": 142
|
|
},
|
|
"id": "mkpIzfpKr38O",
|
|
"outputId": "b0f3e3c1-1a20-424b-e220-e0f31e6e21fd"
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Enter a question: How to find startup idea?\n",
|
|
"Relevant file found: before.txt\n",
|
|
"Answer: To find a startup idea, one should focus on developing expertise and knowledge about things that matter and work on problems that genuinely interest them. Avoid the inclination to actively look for startup ideas. Instead, let the ideas form naturally by immersing oneself in learning and solving problems with likeminded individuals.\n",
|
|
"Enter a question: \n",
|
|
"No question asked\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"application/vnd.google.colaboratory.intrinsic+json": {
|
|
"type": "string"
|
|
},
|
|
"text/plain": [
|
|
"'default'"
|
|
]
|
|
},
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# 8) QA Agent: Find the most relevant file based on summary with actions\n",
|
|
"# if no question is asked:\n",
|
|
"# (a) end: terminate the flow\n",
|
|
"# if question is asked:\n",
|
|
"# if relevant file is found:\n",
|
|
"# (b) answer: move to answer node and read the whole file to answer the question\n",
|
|
"# if no relevant file is found:\n",
|
|
"# (c) retry: retry the process to find the relevant file\n",
|
|
"class FindRelevantFile(Node):\n",
|
|
" def prep(self, shared):\n",
|
|
" question = input(\"Enter a question: \")\n",
|
|
" formatted_list = [f\"- '{filename}': {shared['summary'][filename]}\"\n",
|
|
" for filename in shared['summary']]\n",
|
|
" return question, formatted_list\n",
|
|
" def exec(self, prep_res):\n",
|
|
" question, formatted_list = prep_res\n",
|
|
" if not question:\n",
|
|
" return {\"think\":\"no question\", \"has_relevant\":False}\n",
|
|
" # Provide a structured YAML output that includes:\n",
|
|
" # - The chain of thought\n",
|
|
" # - Whether any relevant file was found\n",
|
|
" # - The most relevant file if found\n",
|
|
" prompt = f\"\"\"Question: {question}\n",
|
|
"Find the most relevant file from:\n",
|
|
"{formatted_list}\n",
|
|
"If no relevant file, explain why\n",
|
|
"Respond in yaml without additional information:\n",
|
|
"think: the question has/has no relevant file ...\n",
|
|
"has_relevant: true/false\n",
|
|
"most_relevant: filename\"\"\"\n",
|
|
" response = call_llm(prompt)\n",
|
|
" import yaml\n",
|
|
" result = yaml.safe_load(response)\n",
|
|
" # Ensure required fields are present\n",
|
|
" assert \"think\" in result\n",
|
|
" assert \"has_relevant\" in result\n",
|
|
" assert \"most_relevant\" in result if result[\"has_relevant\"] else True\n",
|
|
" return result\n",
|
|
" # handle errors by returning a default response in case of exception after retries\n",
|
|
" def process_after_fail(self,shared,prep_res,exc):\n",
|
|
" # if not overridden, the default is to throw the exception\n",
|
|
" return {\"think\":\"error finding the file\", \"has_relevant\":False}\n",
|
|
" def post(self, shared, prep_res, exec_res):\n",
|
|
" question, _ = prep_res\n",
|
|
" # Decide what to do next based on the results\n",
|
|
" if not question:\n",
|
|
" print(f\"No question asked\")\n",
|
|
" return \"end\"\n",
|
|
" if exec_res[\"has_relevant\"]:\n",
|
|
" # Store the question and most relevant file in shared\n",
|
|
" shared[\"question\"] = question\n",
|
|
" shared[\"relevant_file\"] = exec_res['most_relevant']\n",
|
|
" print(f\"Relevant file found: {exec_res['most_relevant']}\")\n",
|
|
" return \"answer\"\n",
|
|
" else:\n",
|
|
" print(f\"No relevant file found: {exec_res['think']}\")\n",
|
|
" return \"retry\"\n",
|
|
"\n",
|
|
"class AnswerQuestion(Node):\n",
|
|
" def prep(self, shared):\n",
|
|
" question = shared['question']\n",
|
|
" relevant_file = shared['relevant_file']\n",
|
|
" # Read the whole file content\n",
|
|
" file_content = shared['data'][relevant_file]\n",
|
|
" return question, file_content\n",
|
|
" def exec(self, prep_res):\n",
|
|
" question, file_content = prep_res\n",
|
|
" prompt = f\"\"\"Question: {question}\n",
|
|
"File: {file_content}\n",
|
|
"Answer the question in 50 words\"\"\"\n",
|
|
" response = call_llm(prompt)\n",
|
|
" return response\n",
|
|
" def post(self, shared, prep_res, exec_res):\n",
|
|
" print(f\"Answer: {exec_res}\")\n",
|
|
"\n",
|
|
"class NoOp(Node):\n",
|
|
" pass\n",
|
|
"\n",
|
|
"# Configure the QA agent with appropriate transitions and retries\n",
|
|
"find_relevant_file = FindRelevantFile(max_retries=3)\n",
|
|
"answer_question = AnswerQuestion()\n",
|
|
"no_op = NoOp()\n",
|
|
"\n",
|
|
"# Connect the nodes based on the actions they return\n",
|
|
"find_relevant_file - \"answer\" >> answer_question >> find_relevant_file\n",
|
|
"find_relevant_file - \"retry\" >> find_relevant_file\n",
|
|
"find_relevant_file - \"end\" >> no_op\n",
|
|
"\n",
|
|
"qa_agent = Flow(start=find_relevant_file)\n",
|
|
"# Example Q: How to find startup idea?\n",
|
|
"qa_agent.run(shared)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"colab": {
|
|
"provenance": []
|
|
},
|
|
"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.9.2"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 0
|
|
}
|