From 65f0500591c778c7cdfd581dcc32b67bd7b008a5 Mon Sep 17 00:00:00 2001 From: jgomes168 <168474583+jgomes168@users.noreply.github.com> Date: Wed, 24 Jul 2024 17:43:53 -0700 Subject: [PATCH] Remove python notebook (#5) Co-authored-by: Julia Gomes --- arize_hallucination_evaluator.ipynb | 660 ---------------------------- 1 file changed, 660 deletions(-) delete mode 100644 arize_hallucination_evaluator.ipynb diff --git a/arize_hallucination_evaluator.ipynb b/arize_hallucination_evaluator.ipynb deleted file mode 100644 index 6ed471e..0000000 --- a/arize_hallucination_evaluator.ipynb +++ /dev/null @@ -1,660 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "VtCMklxtp-yz" - }, - "source": [ - "# ArizeDatasetEmbeddings Guard\n", - "In this demo, we are going to set up and use a Guard that blocks the LLM from responding from attempted jailbreaks. We will do this using the `ArizeDatasetEmbeddings` Guard from Arize AI. This Guard works in the following way:\n", - "* The Guard computes embeddings for chunks associated with a set of few shot examples of \"bad\" user prompts or LLM messages (we recommend using 10 different prompts)\n", - "* When the the Guard is applied to a user or LLM message, the Guard computes the embedding for the input message and checks if any of the few shot \"train\" examples in the dataset are close to the message in embedded space\n", - "* If the cosine distance between the input message and any of the chunks is within the user-specified threshold (default setting is 0.2), then the Guard intercepts the LLM call.\n", - "\n", - "In this demo, we use the `ArizeDatasetEmbeddings` Guard in two ways, first on a dataset of jailbreak prompts, then subsequently on a dataset of PII prompts. In both cases, we apply the Guard to user input messages, rather than LLM output messages (although we could take either approach). If the Guard flags a jailbreak attempt or PII in the user message, we simply throw an `Exception`. Alternatively, in practice the user can specify a default LLM response that can be used when the Guard is triggered.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "vAuY_sNgr4OQ" - }, - "source": [ - "# Install Dependencies\n", - "Various installations are required for OTL, LlamaIndex and Open AI." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "HY97cJFAk7Sc", - "outputId": "c0f2c732-bd9b-4433-8c03-df457b1e7cc0" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "馃攽 Enter your OpenAI API key: 路路路路路路路路路路\n" - ] - } - ], - "source": [ - "!pip install -qq 'openinference-instrumentation-llama-index>=0.1.6' 'openinference-instrumentation-llama-index>=0.1.6' llama-index-llms-openai opentelemetry-exporter-otlp llama-index>=0.10.3 \"llama-index-callbacks-arize-phoenix>=0.1.2\" arize-otel\n", - "\n", - "import os\n", - "from getpass import getpass\n", - "\n", - "openai_api_key = getpass(\"馃攽 Enter your OpenAI API key: \")\n", - "os.environ[\"OPENAI_API_KEY\"] = openai_api_key" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "OZvseSFHsD7M" - }, - "source": [ - "# Initialize Arize Phoenix\n", - "Set up OTL tracer for the `LlamaIndexInstrumentor`." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "VCDUdapRrqpd", - "outputId": "c9819008-8cc2-4628-981f-41295026ca49" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "馃攽 Enter your Arize space key in the space settings page of the Arize UI: 路路路路路路路路路路\n", - "馃攽 Enter your Arize API key in the space settings page of the Arize UI: 路路路路路路路路路路\n" - ] - }, - { - "output_type": "stream", - "name": "stderr", - "text": [ - "WARNING:opentelemetry.trace:Overriding of current TracerProvider is not allowed\n" - ] - }, - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Overriding of current TracerProvider is not allowed\n" - ] - }, - { - "output_type": "stream", - "name": "stderr", - "text": [ - "WARNING:opentelemetry.instrumentation.instrumentor:Attempting to instrument while already instrumented\n" - ] - }, - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Attempting to instrument while already instrumented\n" - ] - } - ], - "source": [ - "from openinference.instrumentation.llama_index import LlamaIndexInstrumentor\n", - "from arize_otel import register_otel, Endpoints\n", - "\n", - "# Setup OTEL via our convenience function\n", - "register_otel(\n", - " endpoints = Endpoints.ARIZE,\n", - " space_key = getpass(\"馃攽 Enter your Arize space key in the space settings page of the Arize UI: \"),\n", - " api_key = getpass(\"馃攽 Enter your Arize API key in the space settings page of the Arize UI: \"),\n", - " model_id = \"test-guard-july10-6:07pm\", # name this to whatever you would like\n", - ")\n", - "LlamaIndexInstrumentor().instrument()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "0z-3-Reas5TW" - }, - "source": [ - "# Instrument Guardrails AI\n", - "Install and instrument Guardrails AI. Import `ArizeDatasetEmbeddings` Guard." - ] - }, - { - "cell_type": "code", - "source": [ - "!pip install -qq guardrails-ai litellm" - ], - "metadata": { - "collapsed": true, - "id": "Q8nwDMRXfmjy" - }, - "execution_count": 16, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "import os\n", - "from typing import Any, Callable, Dict, Optional, Union, Type\n", - "from warnings import warn\n", - "from enum import Enum\n", - "from abc import ABC, abstractmethod\n", - "\n", - "from guardrails.validator_base import (\n", - " FailResult,\n", - " PassResult,\n", - " ValidationResult,\n", - " Validator,\n", - " register_validator,\n", - ")\n", - "from guardrails.stores.context import get_call_kwarg\n", - "from litellm import completion, get_llm_provider\n", - "\n", - "\n", - "class ArizeRagEvalPromptBase(ABC):\n", - " def __init__(self, prompt_name, **kwargs) -> None:\n", - " self.prompt_name = prompt_name\n", - "\n", - " @abstractmethod\n", - " def generate_prompt(self, user_input_message: str, reference_text: str, llm_response: str) -> str:\n", - " pass\n", - "\n", - "\n", - "class ContextRelevancyPrompt(ArizeRagEvalPromptBase):\n", - " def generate_prompt(self, user_input_message: str, reference_text: str, llm_response: str) -> str:\n", - " return f\"\"\"\n", - " You are comparing a reference text to a question and trying to determine if the reference text\n", - " contains information relevant to answering the question. Here is the data:\n", - " [BEGIN DATA]\n", - " ************\n", - " [Question]: {user_input_message}\n", - " ************\n", - " [Reference text]: {reference_text}\n", - " ************\n", - " [END DATA]\n", - " Compare the Question above to the Reference text. You must determine whether the Reference text\n", - " contains information that can answer the Question. Please focus on whether the very specific\n", - " question can be answered by the information in the Reference text.\n", - " Your response must be single word, either \"relevant\" or \"unrelated\",\n", - " and should not contain any text or characters aside from that word.\n", - " \"unrelated\" means that the reference text does not contain an answer to the Question.\n", - " \"relevant\" means the reference text contains an answer to the Question.\"\"\"\n", - "\n", - "\n", - "class HallucinationPrompt(ArizeRagEvalPromptBase):\n", - " def generate_prompt(self, user_input_message: str, reference_text: str, llm_response: str) -> str:\n", - " return f\"\"\"\n", - " In this task, you will be presented with a query, a reference text and an answer. The answer is\n", - " generated to the question based on the reference text. The answer may contain false information. You\n", - " must use the reference text to determine if the answer to the question contains false information,\n", - " if the answer is a hallucination of facts. Your objective is to determine whether the answer text\n", - " contains factual information and is not a hallucination. A 'hallucination' refers to\n", - " an answer that is not based on the reference text or assumes information that is not available in\n", - " the reference text. Your response should be a single word: either \"factual\" or \"hallucinated\", and\n", - " it should not include any other text or characters. \"hallucinated\" indicates that the answer\n", - " provides factually inaccurate information to the query based on the reference text. \"factual\"\n", - " indicates that the answer to the question is correct relative to the reference text, and does not\n", - " contain made up information. Please read the query and reference text carefully before determining\n", - " your response.\n", - "\n", - " [BEGIN DATA]\n", - " ************\n", - " [Query]: {user_input_message}\n", - " ************\n", - " [Reference text]: {reference_text}\n", - " ************\n", - " [Answer]: {llm_response}\n", - " ************\n", - " [END DATA]\n", - "\n", - " Is the answer above factual or hallucinated based on the query and reference text?\n", - " \"\"\"\n", - "\n", - "\n", - "class QACorrectnessPrompt(ArizeRagEvalPromptBase):\n", - " def generate_prompt(self, user_input_message: str, reference_text: str, llm_response: str) -> str:\n", - " return f\"\"\"\n", - " You are given a question, an answer and reference text. You must determine whether the\n", - " given answer correctly answers the question based on the reference text. Here is the data:\n", - " [BEGIN DATA]\n", - " ************\n", - " [Question]: {user_input_message}\n", - " ************\n", - " [Reference]: {reference_text}\n", - " ************\n", - " [Answer]: {llm_response}\n", - " [END DATA]\n", - " Your response must be a single word, either \"correct\" or \"incorrect\",\n", - " and should not contain any text or characters aside from that word.\n", - " \"correct\" means that the question is correctly and fully answered by the answer.\n", - " \"incorrect\" means that the question is not correctly or only partially answered by the\n", - " answer.\n", - " \"\"\"\n", - "\n", - "\n", - "@register_validator(name=\"arize/llm_rag_evaluator\", data_type=\"string\")\n", - "class LlmRagEvaluator(Validator):\n", - " \"\"\"This class validates an output generated by a LiteLLM (LLM) model by prompting another LLM model to evaluate the output.\n", - "\n", - " **Key Properties**\n", - "\n", - " | Property | Description |\n", - " | ----------------------------- | --------------------------------- |\n", - " | Name for `format` attribute | `arize/relevancy_evaluator` |\n", - " | Supported data types | `string` |\n", - " | Programmatic fix | N/A |\n", - "\n", - " Args:\n", - " llm_callable (str, optional): The name of the LiteLLM model to use for validation. Defaults to \"gpt-3.5-turbo\".\n", - " on_fail (Callable, optional): A function to be called when validation fails. Defaults to None.\n", - " \"\"\"\n", - "\n", - " def __init__(\n", - " self,\n", - " eval_llm_prompt_generator: Type[ArizeRagEvalPromptBase],\n", - " llm_evaluator_fail_response: str,\n", - " llm_evaluator_pass_response: str,\n", - " llm_callable: str = \"gpt-3.5-turbo\", # str for litellm model name\n", - " on_fail: Optional[Callable] = None,\n", - " **kwargs,\n", - " ):\n", - " super().__init__(on_fail, llm_callable=llm_callable, **kwargs)\n", - " self.llm_evaluator_prompt_generator = eval_llm_prompt_generator\n", - " self.llm_callable = llm_callable\n", - " self.fail_response = llm_evaluator_fail_response\n", - " self.pass_response = llm_evaluator_pass_response\n", - "\n", - " def get_llm_response(self, prompt: str) -> str:\n", - " \"\"\"Gets the response from the LLM.\n", - "\n", - " Args:\n", - " prompt (str): The prompt to send to the LLM.\n", - "\n", - " Returns:\n", - " str: The response from the LLM.\n", - " \"\"\"\n", - " # 0. Create messages\n", - " messages = [{\"content\": prompt, \"role\": \"user\"}]\n", - "\n", - " # 0b. Setup auth kwargs if the model is from OpenAI\n", - " kwargs = {}\n", - " _model, provider, *_rest = get_llm_provider(self.llm_callable)\n", - " if provider == \"openai\":\n", - " kwargs[\"api_key\"] = get_call_kwarg(\"api_key\") or os.environ.get(\"OPENAI_API_KEY\")\n", - "\n", - " # 1. Get LLM response\n", - " # Strip whitespace and convert to lowercase\n", - " try:\n", - " response = completion(model=self.llm_callable, messages=messages, **kwargs)\n", - " response = response.choices[0].message.content # type: ignore\n", - " response = response.strip().lower()\n", - " except Exception as e:\n", - " raise RuntimeError(f\"Error getting response from the LLM: {e}\") from e\n", - "\n", - " # 3. Return the response\n", - " return response\n", - "\n", - " def validate(self, value: Any, metadata: Dict) -> ValidationResult:\n", - " \"\"\"\n", - " Validates is based on the relevance of the reference text to the original question.\n", - "\n", - " Args:\n", - " value (Any): The value to validate. It must contain 'original_prompt' and 'reference_text' keys.\n", - " metadata (Dict): The metadata for the validation. This is not used in the current implementation.\n", - "\n", - " Returns:\n", - " ValidationResult: The result of the validation. It can be a PassResult if the reference\n", - " text is relevant to the original question, or a FailResult otherwise.\n", - " \"\"\"\n", - " # 1. Get the question and arg from the value\n", - " user_input_message = metadata.get(\"user_message\")\n", - " if user_input_message is None:\n", - " raise RuntimeError(\n", - " \"original_prompt missing from value. \"\n", - " \"Please provide the original prompt.\"\n", - " )\n", - "\n", - " reference_text = metadata.get(\"context\")\n", - " if reference_text is None:\n", - " raise RuntimeError(\n", - " \"'reference_text' missing from value. \"\n", - " \"Please provide the reference text.\"\n", - " )\n", - "\n", - " # 2. Setup the prompt\n", - " prompt = self.llm_evaluator_prompt_generator.generate_prompt(user_input_message=user_input_message, reference_text=reference_text, llm_response=value)\n", - " print(f\"evaluator prompt: {prompt}\")\n", - "\n", - " # 3. Get the LLM response\n", - " llm_response = self.get_llm_response(prompt)\n", - " print(f\"llm evaluator response: {llm_response}\")\n", - "\n", - " # 4. Check the LLM response and return the result\n", - " if llm_response == self.fail_response:\n", - " return FailResult(error_message=f\"The LLM says {self.fail_response}. The validation failed.\")\n", - "\n", - " if llm_response == self.pass_response:\n", - " return PassResult()\n", - "\n", - " return FailResult(\n", - " error_message=\"The LLM returned an invalid answer. Failing the validation...\"\n", - " )" - ], - "metadata": { - "id": "WIdK2paCf828" - }, - "execution_count": 95, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "At02szHOtKqy" - }, - "source": [ - "# Instantiate ArizeDatasetEmbeddings Guard\n", - "We're going to use a public dataset to instantiate the ArizeDatasetEmbeddings Guard with 10 few shot example jailbreak prompts. For details on the dataset, please refer to the following resources:\n", - "* Research Paper on Arxiv: https://arxiv.org/pdf/2308.03825\n", - "* Repository containing the dataset and other benchmarks: https://github.com/verazuo/jailbreak_llms\n", - "* Website associated with original research paper: https://jailbreak-llms.xinyueshen.me/\n", - "* URL link to original dataset: https://github.com/verazuo/jailbreak_llms/tree/main/data\n", - "\n", - "Note that we could Guard against any type of dataset by passing in the argument `sources={my_sources}`. By default, the `ArizeDatasetEmbeddings` Guard will load the jailbreak prompts above, hence the warning below: \"A source dataset was not provided, so using default sources of Jailbreak prompts from Arize.\"" - ] - }, - { - "cell_type": "code", - "execution_count": 96, - "metadata": { - "id": "E5GV4hwGUxxB" - }, - "outputs": [], - "source": [ - "from guardrails import Guard\n", - "guard = Guard().use(LlmRagEvaluator, eval_llm_prompt_generator=HallucinationPrompt(prompt_name=\"hallucination_evaluator\"), llm_evaluator_fail_response=\"hallucinated\", llm_evaluator_pass_response=\"factual\", on_fail=\"exception\")\n", - "guard._disable_tracer = True" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "metadata": { - "id": "MpwPFAtDsrcf" - }, - "outputs": [], - "source": [ - "import openai\n", - "from typing import Optional, List, Mapping, Any\n", - "\n", - "from llama_index.core import SimpleDirectoryReader, SummaryIndex\n", - "from llama_index.core.callbacks import CallbackManager\n", - "from llama_index.core.llms import (\n", - " CustomLLM,\n", - " CompletionResponse,\n", - " CompletionResponseGen,\n", - " LLMMetadata,\n", - ")\n", - "from llama_index.core.llms.callbacks import llm_completion_callback\n", - "from llama_index.core import Settings\n", - "\n", - "from llama_index.llms.openai import OpenAI\n", - "\n", - "def monkey_completion(prompt, **kwargs):\n", - " _, _, context_component_of_prompt = prompt.partition(\"Context information is below.\")\n", - " _, _, query_component_of_prompt = prompt.partition(\"Query: \")\n", - " return guard(\n", - " llm_api=openai.chat.completions.create,\n", - " prompt=prompt,\n", - " model=\"gpt-3.5-turbo\",\n", - " max_tokens=1024,\n", - " temperature=0.5,\n", - " metadata={\n", - " \"user_message\": query_component_of_prompt,\n", - " \"context\": context_component_of_prompt,\n", - " }\n", - " )\n", - "\n", - "outerOpenAI = OpenAI()\n", - "\n", - "class GuardedLLM(CustomLLM):\n", - " context_window: int = 3900\n", - " num_output: int = 256\n", - " model_name: str = \"custom\"\n", - " dummy_response: str = \"My response\"\n", - " openai_llm: Any = None\n", - "\n", - " @property\n", - " def metadata(self) -> LLMMetadata:\n", - " \"\"\"Get LLM metadata.\"\"\"\n", - " return outerOpenAI.metadata\n", - "\n", - " @llm_completion_callback()\n", - " def complete(self, prompt: str, **kwargs: Any) -> CompletionResponse:\n", - " validated_response = monkey_completion(prompt, **kwargs)\n", - " return CompletionResponse(text=validated_response.raw_llm_output)\n", - "\n", - " @llm_completion_callback()\n", - " def stream_complete(\n", - " self, prompt: str, **kwargs: Any\n", - " ) -> CompletionResponseGen:\n", - " response = \"\"\n", - " for token in self.dummy_response:\n", - " response += token\n", - " yield CompletionResponse(text=response, delta=token)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "u2nKIt4duKAU" - }, - "source": [ - "# Set Up RAG Application\n", - "Create a LlamaIndex VectorStore to create a classic RAG application over Paul Graham essays." - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "p-g6O8tvsxKd", - "outputId": "ca40296d-8006-4a95-e43e-19da88050e88" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - " % Total % Received % Xferd Average Speed Time Time Time Current\n", - " Dload Upload Total Spent Left Speed\n", - "\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r100 75042 100 75042 0 0 667k 0 --:--:-- --:--:-- --:--:-- 672k\n" - ] - } - ], - "source": [ - "!mkdir -p 'data/paul_graham/'\n", - "!curl 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' > 'data/paul_graham/paul_graham_essay.txt'\n", - "import logging\n", - "import sys\n", - "\n", - "logging.basicConfig(stream=sys.stdout, level=logging.INFO)\n", - "logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))\n", - "\n", - "from llama_index.core import VectorStoreIndex, SimpleDirectoryReader\n", - "# load documents\n", - "documents = SimpleDirectoryReader(\"./data/paul_graham/\").load_data()\n", - "index = VectorStoreIndex.from_documents(documents, chunk_size=512)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "iOJW44aRpMYE" - }, - "source": [ - "# Run Guard on Jailbreak Prompts from Public Dataset\n", - "\n", - "Below, we're only going to run the `ArizeDatasetEmbeddings` Guard on a single jailbreak prompt and a single \"regular\" prompt (which looks similar to a jailbreak). These examples come from the same dataset above.\n", - "\n", - "Although we are only running the Guard on two examples in this notebook, we have also benchmarked the Guard on the full dataset and found the following results:\n", - "* True Positives: 86.43% of 656 jailbreak prompts failed the JailbreakEmbeddings guard.\n", - "* False Negatives: 13.57% of 656 jailbreak prompts passed the JailbreakEmbeddings guard.\n", - "* False Positives: 13.95% of 2000 regular prompts failed the JailbreakEmbeddings guard.\n", - "* True Negatives: 86.05% of 2000 regular prompts passed the JailbreakEmbeddings guard.\n", - "* 1.41 median latency for end-to-end LLM call on GPT-3.5\n", - "* 2.91 mean latency for end-to-end LLM call on GPT-3.5" - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "d1Rzk87ZwDo8", - "outputId": "84c2abb6-6e5f-4d64-9958-d59675a31afe" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "evaluator prompt: \n", - " In this task, you will be presented with a query, a reference text and an answer. The answer is\n", - " generated to the question based on the reference text. The answer may contain false information. You\n", - " must use the reference text to determine if the answer to the question contains false information,\n", - " if the answer is a hallucination of facts. Your objective is to determine whether the answer text\n", - " contains factual information and is not a hallucination. A 'hallucination' refers to\n", - " an answer that is not based on the reference text or assumes information that is not available in\n", - " the reference text. Your response should be a single word: either \"factual\" or \"hallucinated\", and\n", - " it should not include any other text or characters. \"hallucinated\" indicates that the answer\n", - " provides factually inaccurate information to the query based on the reference text. \"factual\"\n", - " indicates that the answer to the question is correct relative to the reference text, and does not\n", - " contain made up information. Please read the query and reference text carefully before determining\n", - " your response.\n", - "\n", - " [BEGIN DATA]\n", - " ************\n", - " [Query]: What are the 3 ingredients to great work?\n", - "Answer: \n", - "assistant: \n", - " ************\n", - " [Reference text]: \n", - "---------------------\n", - "file_path: /content/data/paul_graham/paul_graham_essay.txt\n", - "\n", - "It's not that unprestigious types of work are good per se. But when you find yourself drawn to some kind of work despite its current lack of prestige, it's a sign both that there's something real to be discovered there, and that you have the right kind of motives. Impure motives are a big danger for the ambitious. If anything is going to lead you astray, it will be the desire to impress people. So while working on things that aren't prestigious doesn't guarantee you're on the right track, it at least guarantees you're not on the most common type of wrong one.\n", - "\n", - "Over the next several years I wrote lots of essays about all kinds of different topics. O'Reilly reprinted a collection of them as a book, called Hackers & Painters after one of the essays in it. I also worked on spam filters, and did some more painting. I used to have dinners for a group of friends every thursday night, which taught me how to cook for groups. And I bought another building in Cambridge, a former candy factory (and later, twas said, porn studio), to use as an office.\n", - "\n", - "One night in October 2003 there was a big party at my house. It was a clever idea of my friend Maria Daniels, who was one of the thursday diners. Three separate hosts would all invite their friends to one party. So for every guest, two thirds of the other guests would be people they didn't know but would probably like. One of the guests was someone I didn't know but would turn out to like a lot: a woman called Jessica Livingston. A couple days later I asked her out.\n", - "\n", - "Jessica was in charge of marketing at a Boston investment bank. This bank thought it understood startups, but over the next year, as she met friends of mine from the startup world, she was surprised how different reality was. And how colorful their stories were. So she decided to compile a book of interviews with startup founders.\n", - "\n", - "When the bank had financial problems and she had to fire half her staff, she started looking for a new job. In early 2005 she interviewed for a marketing job at a Boston VC firm. It took them weeks to make up their minds, and during this time I started telling her about all the things that needed to be fixed about venture capital. They should make a larger number of smaller investments instead of a handful of giant ones, they should be funding younger, more technical founders instead of MBAs, they should let the founders remain as CEO, and so on.\n", - "\n", - "One of my tricks for writing essays had always been to give talks. The prospect of having to stand up in front of a group of people and tell them something that won't waste their time is a great spur to the imagination. When the Harvard Computer Society, the undergrad computer club, asked me to give a talk, I decided I would tell them how to start a startup. Maybe they'd be able to avoid the worst of the mistakes we'd made.\n", - "\n", - "So I gave this talk, in the course of which I told them that the best sources of seed funding were successful startup founders, because then they'd be sources of advice too. Whereupon it seemed they were all looking expectantly at me. Horrified at the prospect of having my inbox flooded by business plans (if I'd only known), I blurted out \"But not me!\" and went on with the talk. But afterward it occurred to me that I should really stop procrastinating about angel investing. I'd been meaning to since Yahoo bought us, and now it was 7 years later and I still hadn't done one angel investment.\n", - "\n", - "Meanwhile I had been scheming with Robert and Trevor about projects we could work on together. I missed working with them, and it seemed like there had to be something we could collaborate on.\n", - "\n", - "As Jessica and I were walking home from dinner on March 11, at the corner of Garden and Walker streets, these three threads converged. Screw the VCs who were taking so long to make up their minds. We'd start our own investment firm and actually implement the ideas we'd been talking about. I'd fund it, and Jessica could quit her job and work for it, and we'd get Robert and Trevor as partners too. [13]\n", - "\n", - "Once again, ignorance worked in our favor. We had no idea how to be angel investors, and in Boston in 2005 there were no Ron Conways to learn from. So we just made what seemed like the obvious choices, and some of the things we did turned out to be novel.\n", - "\n", - "There are multiple components to Y Combinator, and we didn't figure them all out at once. The part we got first was to be an angel firm.\n", - "\n", - "file_path: /content/data/paul_graham/paul_graham_essay.txt\n", - "\n", - "Much to my surprise, the time I spent working on this stuff was not wasted after all. After we started Y Combinator, I would often encounter startups working on parts of this new architecture, and it was very useful to have spent so much time thinking about it and even trying to write some of it.\n", - "\n", - "The subset I would build as an open source project was the new Lisp, whose parentheses I now wouldn't even have to hide. A lot of Lisp hackers dream of building a new Lisp, partly because one of the distinctive features of the language is that it has dialects, and partly, I think, because we have in our minds a Platonic form of Lisp that all existing dialects fall short of. I certainly did. So at the end of the summer Dan and I switched to working on this new dialect of Lisp, which I called Arc, in a house I bought in Cambridge.\n", - "\n", - "The following spring, lightning struck. I was invited to give a talk at a Lisp conference, so I gave one about how we'd used Lisp at Viaweb. Afterward I put a postscript file of this talk online, on paulgraham.com, which I'd created years before using Viaweb but had never used for anything. In one day it got 30,000 page views. What on earth had happened? The referring urls showed that someone had posted it on Slashdot. [10]\n", - "\n", - "Wow, I thought, there's an audience. If I write something and put it on the web, anyone can read it. That may seem obvious now, but it was surprising then. In the print era there was a narrow channel to readers, guarded by fierce monsters known as editors. The only way to get an audience for anything you wrote was to get it published as a book, or in a newspaper or magazine. Now anyone could publish anything.\n", - "\n", - "This had been possible in principle since 1993, but not many people had realized it yet. I had been intimately involved with building the infrastructure of the web for most of that time, and a writer as well, and it had taken me 8 years to realize it. Even then it took me several years to understand the implications. It meant there would be a whole new generation of essays. [11]\n", - "\n", - "In the print era, the channel for publishing essays had been vanishingly small. Except for a few officially anointed thinkers who went to the right parties in New York, the only people allowed to publish essays were specialists writing about their specialties. There were so many essays that had never been written, because there had been no way to publish them. Now they could be, and I was going to write them. [12]\n", - "\n", - "I've worked on several different things, but to the extent there was a turning point where I figured out what to work on, it was when I started publishing essays online. From then on I knew that whatever else I did, I'd always write essays too.\n", - "\n", - "I knew that online essays would be a marginal medium at first. Socially they'd seem more like rants posted by nutjobs on their GeoCities sites than the genteel and beautifully typeset compositions published in The New Yorker. But by this point I knew enough to find that encouraging instead of discouraging.\n", - "\n", - "One of the most conspicuous patterns I've noticed in my life is how well it has worked, for me at least, to work on things that weren't prestigious. Still life has always been the least prestigious form of painting. Viaweb and Y Combinator both seemed lame when we started them. I still get the glassy eye from strangers when they ask what I'm writing, and I explain that it's an essay I'm going to publish on my web site. Even Lisp, though prestigious intellectually in something like the way Latin is, also seems about as hip.\n", - "\n", - "It's not that unprestigious types of work are good per se. But when you find yourself drawn to some kind of work despite its current lack of prestige, it's a sign both that there's something real to be discovered there, and that you have the right kind of motives. Impure motives are a big danger for the ambitious. If anything is going to lead you astray, it will be the desire to impress people. So while working on things that aren't prestigious doesn't guarantee you're on the right track, it at least guarantees you're not on the most common type of wrong one.\n", - "\n", - "Over the next several years I wrote lots of essays about all kinds of different topics. O'Reilly reprinted a collection of them as a book, called Hackers & Painters after one of the essays in it. I also worked on spam filters, and did some more painting.\n", - "---------------------\n", - "Given the context information and not prior knowledge, answer the query.\n", - "Query: What are the 3 ingredients to great work?\n", - "Answer: \n", - "assistant: \n", - " ************\n", - " [Answer]: Passion, authenticity, and purity of motives.\n", - " ************\n", - " [END DATA]\n", - "\n", - " Is the answer above factual or hallucinated based on the query and reference text?\n", - " \n", - "llm evaluator response: hallucinated\n", - "Validation failed for field with errors: The LLM says hallucinated. The validation failed.\n" - ] - } - ], - "source": [ - "from guardrails.errors import ValidationError\n", - "\n", - "query_engine = index.as_query_engine(\n", - " llm=GuardedLLM(),\n", - ")\n", - "\n", - "# Take jailbreak prompt from public dataset https://github.com/verazuo/jailbreak_llms/blob/main/data/prompts/jailbreak_prompts_2023_05_07.csv\n", - "sample_jailbreak_prompt = \"\"\"What are the 3 ingredients to great work?\"\"\"\n", - "\n", - "try:\n", - " response = query_engine.query(sample_jailbreak_prompt)\n", - "except ValidationError as e:\n", - " print(e)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file