From dbe76cf763d0b3f9fda78a9d1147e103935c7e0f Mon Sep 17 00:00:00 2001 From: platform-endpoints Date: Fri, 17 Jan 2025 18:01:50 +0000 Subject: [PATCH 01/12] Add spec changes Co-authored-by: Daniel <133696562+daniel-cohere@users.noreply.github.com> --- cohere-openapi.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cohere-openapi.yaml b/cohere-openapi.yaml index 886cd2d3c..0297e4ffa 100644 --- a/cohere-openapi.yaml +++ b/cohere-openapi.yaml @@ -22122,6 +22122,15 @@ components: x-fern-audiences: - public minItems: 1 + type: + description: | + The type of citation which indicates what part of the response the citation is for. + type: string + x-fern-audiences: + - public + enum: + - TEXT_CONTENT + - PLAN ChatSearchQuery: description: | The generated search query. Contains the text of the query and a unique identifier for the query. @@ -22689,6 +22698,13 @@ components: mapping: tool: "#/components/schemas/ToolSource" document: "#/components/schemas/DocumentSource" + CitationType: + type: string + enum: + - TEXT_CONTENT + - PLAN + description: | + The type of citation which indicates what part of the response the citation is for. Citation: type: object description: Citation information containing sources and the text cited. @@ -22706,6 +22722,8 @@ components: type: array items: $ref: "#/components/schemas/Source" + type: + $ref: "#/components/schemas/CitationType" AssistantMessage: type: object title: Assistant Message From c33631d24c39c2e31370c8cd39bac937dff86f3f Mon Sep 17 00:00:00 2001 From: Max Shkutnyk Date: Fri, 17 Jan 2025 21:04:59 +0200 Subject: [PATCH 02/12] Reformat code examples for semantic search intro section (#367) Co-authored-by: Max Shkutnyk --- .../deeper-semantic-search.mdx | 83 ++++++++++--------- .../fine-tuning-for-rerank.mdx | 67 ++++++++++----- .../generating-answers.mdx | 11 ++- .../intro-semantic-search/keyword-search.mdx | 25 ++++-- .../multilingual-movie-search.mdx | 2 +- .../intro-semantic-search/reranking-2.mdx | 10 +-- 6 files changed, 119 insertions(+), 79 deletions(-) diff --git a/fern/pages/llm-university/intro-semantic-search/deeper-semantic-search.mdx b/fern/pages/llm-university/intro-semantic-search/deeper-semantic-search.mdx index 935cf4ab1..49770e94d 100644 --- a/fern/pages/llm-university/intro-semantic-search/deeper-semantic-search.mdx +++ b/fern/pages/llm-university/intro-semantic-search/deeper-semantic-search.mdx @@ -30,7 +30,7 @@ As you've seen before, semantic search goes way beyond keyword search. The appli ### 1. Download the Dependencies ```python PYTHON -#title Import libraries (Run this cell to execute required code) {display-mode: "form"} +# title Import libraries (Run this cell to execute required code) {display-mode: "form"} import cohere import numpy as np @@ -43,8 +43,9 @@ import altair as alt from sklearn.metrics.pairwise import cosine_similarity from annoy import AnnoyIndex import warnings -warnings.filterwarnings('ignore') -pd.set_option('display.max_colwidth', None) + +warnings.filterwarnings("ignore") +pd.set_option("display.max_colwidth", None) ``` ### 2. Get the Archive of Questions @@ -83,14 +84,15 @@ To get a thousand embeddings of this length should take a few seconds. ```python PYTHON # Paste your API key here. Remember to not share publicly -api_key = '' +api_key = "" # Create and retrieve a Cohere API key from dashboard.cohere.ai/welcome/register co = cohere.Client(api_key) # Get the embeddings -embeds = co.embed(texts=list(df['text']), - model='embed-english-v2.0').embeddings +embeds = co.embed( + texts=list(df["text"]), model="embed-english-v2.0" +).embeddings ``` ### 4. Build the Index, search Using an Index and Conduct Nearest Neighbour Search @@ -101,12 +103,12 @@ Let's build an index using the library called Date: Fri, 17 Jan 2025 21:11:58 +0200 Subject: [PATCH 03/12] Reformat code examples from LLM University prompt engineering section (#368) Co-authored-by: Max Shkutnyk --- .../constructing-prompts.mdx | 54 +++++++------ .../evaluating-outputs.mdx | 24 ++++-- .../use-case-patterns.mdx | 75 ++++++++++--------- .../validating-outputs.mdx | 40 +++++++--- 4 files changed, 113 insertions(+), 80 deletions(-) diff --git a/fern/pages/llm-university/intro-prompt-engineering/constructing-prompts.mdx b/fern/pages/llm-university/intro-prompt-engineering/constructing-prompts.mdx index 476275bd5..c3a627831 100644 --- a/fern/pages/llm-university/intro-prompt-engineering/constructing-prompts.mdx +++ b/fern/pages/llm-university/intro-prompt-engineering/constructing-prompts.mdx @@ -26,7 +26,9 @@ First, let’s install the Cohere Python SDK, get the Cohere API key, and set up ```python PYTHON import cohere -co = cohere.Client("COHERE_API_KEY") # Get your API key: https://dashboard.cohere.com/api-keys + +# Get your API key: https://dashboard.cohere.com/api-keys +co = cohere.Client("COHERE_API_KEY") ``` Let’s also define a function to take a [prompt](https://txt.cohere.com/generative-ai-part-1/) and a [temperature value](https://txt.cohere.com/generative-ai-part-1/#being-creative-vs-predictable) and then call the [Generate endpoint](/reference/generate?ref=txt.cohere.com), which is how we can access the Command model.​​ Here, we select the model type to be \`command\`. @@ -63,7 +65,6 @@ user_input = "a wireless headphone product named the CO-1T" prompt = f"""Write a creative product description for {user_input}""" generate_text(prompt, temp=0.5) - ``` The model returns the following sample response, which does the job we asked for. @@ -86,14 +87,15 @@ Going back to the previous prompt, the generated product description was great, ```python PYTHON user_input_product = "a wireless headphone product named the CO-1T" user_input_keywords = '"bluetooth", "wireless", "fast charging"' -user_input_customer = "a software developer who works in noisy offices" +user_input_customer = ( + "a software developer who works in noisy offices" +) user_input_describe = "benefits of this product" prompt = f"""Write a creative product description for {user_input_product}, \ with the keywords {user_input_keywords} for {user_input_customer}, and describe {user_input_describe}.""" generate_text(prompt, temp=0.5) - ``` In the example above, we pack the additional details of the prompt in a single paragraph. Alternatively, we can also compose it to be more structured, like so: @@ -101,7 +103,9 @@ In the example above, we pack the additional details of the prompt in a single p ```python PYTHON user_input_product = "a wireless headphone product named the CO-1T" user_input_keywords = '"bluetooth", "wireless", "fast charging"' -user_input_customer = "a software developer who works in noisy offices" +user_input_customer = ( + "a software developer who works in noisy offices" +) user_input_describe = "benefits of this product" prompt = f"""Write a creative product description for {user_input_product}. @@ -110,7 +114,6 @@ Audience: {user_input_customer} Describe: {user_input_describe}""" generate_text(prompt, temp=0.5) - ``` And here’s an example response. This time, the product description is tailored more specifically to our desired target customer, includes the key features that we specified, and sprinkles benefit statements throughout — all coming from the instruction we added to the prompt. @@ -146,11 +149,12 @@ This is a whole topic on its own, but to provide some idea, [this demo](https:// Here’s an example where we ask the model to list the features of the CO-1T wireless headphone without any additional context: ```python PYTHON -user_input ="What are the key features of the CO-1T wireless headphone" +user_input = ( + "What are the key features of the CO-1T wireless headphone" +) prompt = user_input generate_text(prompt, temp=0) - ``` This generates a response that the model makes up since it doesn’t have any information to refer to. @@ -169,13 +173,14 @@ software developers who work around the mayhem of tech startups, these headphone fast charging capacity and wireless Bluetooth connectivity, the CO-1T is the easy breezy way to get through your day without being \ overwhelmed by the chaos of the world.""" -user_input = "What are the key features of the CO-1T wireless headphone" +user_input = ( + "What are the key features of the CO-1T wireless headphone" +) prompt = f"""{context} Given the information above, answer this question: {user_input}""" generate_text(prompt, temp=0) - ``` Now, the model accurately lists the features of the model. @@ -194,14 +199,13 @@ So far, we saw how to get the model to generate responses that follow certain st Here, the task is to extract information from a list of invoices. Instead of providing the information in plain text, we can prompt the model to generate a table that contains all the information required. ```python PYTHON -prompt="""Turn the following information into a table with columns Invoice Number, Merchant Name, and Account Number. +prompt = """Turn the following information into a table with columns Invoice Number, Merchant Name, and Account Number. Bank Invoice: INVOICE #0521 MERCHANT ALLBIRDS ACC XXX3846 Bank Invoice: INVOICE #6781 MERCHANT SHOPPERS ACC XXX9877 Bank Invoice: INVOICE #0777 MERCHANT CN TOWER ACC XXX3846 """ generate_text(prompt, temp=0) - ``` The response will come in the form of a markdown table. @@ -221,14 +225,13 @@ Let me know if you'd like me to make any modifications to this table or provide Another useful format is JSON, which we can modify the prompt as follows. ```python PYTHON -prompt="""Turn the following information into a JSON string with the following keys: Invoice Number, Merchant Name, and Account Number. +prompt = """Turn the following information into a JSON string with the following keys: Invoice Number, Merchant Name, and Account Number. Bank Invoice: INVOICE #0521 MERCHANT ALLBIRDS ACC XXX3846 Bank Invoice: INVOICE #6781 MERCHANT SHOPPERS ACC XXX9877 Bank Invoice: INVOICE #0777 MERCHANT CN TOWER ACC XXX3846 """ generate_text(prompt, temp=0) - ``` This returns the following response. @@ -271,11 +274,10 @@ We’ll use this example request: “Send a message to Alison to ask if she can First, let’s generate a response without giving the model an example. Here’s the prompt: ```python PYTHON -prompt="""Turn the following message to a virtual assistant into the correct action: +prompt = """Turn the following message to a virtual assistant into the correct action: Send a message to Alison to ask if she can pick me up tonight to go to the concert together""" generate_text(prompt, temp=0) - ``` The response we get is not wrong, but it doesn’t follow the style that we need, which is a simple one-line rephrasing of the original request. Instead, it generates an email! @@ -290,7 +292,7 @@ Now, let’s modify the prompt by adding a few examples of how we expect the out ```python PYTHON user_input = "Send a message to Alison to ask if she can pick me up tonight to go to the concert together" -prompt=f"""Turn the following message to a virtual assistant into the correct action: +prompt = f"""Turn the following message to a virtual assistant into the correct action: Message: Ask my aunt if she can go to the JDRF Walk with me October 6th Action: can you go to the jdrf walk with me october 6th @@ -304,7 +306,6 @@ Action: I am sick and will not be in today Message: {user_input}""" generate_text(prompt, temp=0) - ``` This time, the style of the response is exactly how we want it. @@ -323,7 +324,7 @@ This concept is called _chain of thought_ prompting, introduced by [Wei et al.]( First let’s look at a prompt _without_ a chain of thought. It contains one example of a question followed by the answer, without any intermediate calculation step. It also contains the new question we want to answer. ```python PYTHON -prompt=f"""Q: Roger has 5 tennis balls. He buys 2 more cans of tennis balls. Each can has 3 tennis balls. \ +prompt = f"""Q: Roger has 5 tennis balls. He buys 2 more cans of tennis balls. Each can has 3 tennis balls. \ How many tennis balls does he have now? A: The answer is 11. --- @@ -334,7 +335,6 @@ Q: A box has 10 balls and a half of the balls are red balls. How many red balls A:""" generate_text(prompt, temp=0) - ``` We get the following response, which is an incorrect answer (12). And notice that the response gives the answer first, similar to the example shown. @@ -348,7 +348,7 @@ The answer is 12. There are 5 balls that are red and 5 balls that are not red, a Now, let’s repeat that, this time with a chain of thought. Now, the example answer contains a reasoning step, describing the calculation logic to get to the final answer, before giving the final answer. ```python PYTHON -prompt=f"""Q: Roger has 5 tennis balls. He buys 2 more cans of tennis balls. Each can has 3 tennis balls. \ +prompt = f"""Q: Roger has 5 tennis balls. He buys 2 more cans of tennis balls. Each can has 3 tennis balls. \ How many tennis balls does he have now? A: Roger started with 5 balls. 2 cans of 3 tennis balls each is 6 tennis balls. 5 + 6 = 11. \ The answer is 11. @@ -361,7 +361,6 @@ Q: A box has 12 balls and a half of the balls are red balls. How many red balls A:""" generate_text(prompt, temp=0) - ``` And we get the correct answer this time (10), with the response following the style of the example given. @@ -386,10 +385,11 @@ Let’s use an example of generating startup ideas. We can get the model to dire ```python PYTHON user_input = "education" -prompt = f"""Generate a startup idea for this industry: {user_input}""" +prompt = ( + f"""Generate a startup idea for this industry: {user_input}""" +) generate_text(prompt, temp=0.5) - ``` This generates the following response, which is reasonable, but perhaps not exactly what we are looking for. @@ -428,7 +428,6 @@ Startup Idea: Startup Name: """ generate_text(prompt, temp=0.9) - ``` This provides a richer description of the startup idea. @@ -461,7 +460,6 @@ prompt = f"""Describe the ideal {user_input_position}. In particular, describe t pace, skill, and awareness.""" generate_text(prompt, temp=0.9) - ``` And the response is a paragraph that lists down all the characteristics, but also with unnecessary text before that. @@ -491,7 +489,6 @@ Pace:""" response = generate_text(prompt, temp=0.9) print(response) - ``` Here’s an example response, which is much closer to what we are looking for: @@ -520,13 +517,12 @@ The paper proposes adding a prefix that nudges the model to perform a reasoning Here’s an example taken from the paper. First, we look at a prompt without the “Let’s think step by step” prefix. ```python PYTHON -prompt=f"""Q: A juggler can juggle 16 balls. Half of the balls are golf balls, +prompt = f"""Q: A juggler can juggle 16 balls. Half of the balls are golf balls, and half of the golf balls are blue. How many blue golf balls are there? A: The answer (arabic numerals) is""" generate_text(prompt, temp=0) - ``` It gives an incorrect answer. diff --git a/fern/pages/llm-university/intro-prompt-engineering/evaluating-outputs.mdx b/fern/pages/llm-university/intro-prompt-engineering/evaluating-outputs.mdx index b27229816..13ea8ed9e 100644 --- a/fern/pages/llm-university/intro-prompt-engineering/evaluating-outputs.mdx +++ b/fern/pages/llm-university/intro-prompt-engineering/evaluating-outputs.mdx @@ -102,12 +102,14 @@ The example below uses the Command model to perform an A/B testing evaluation fo ```python PYTHON # Add text to evaluate ref_answer = "Because the sound quality is the best out there" -gen_answers = ["Because the audio experience is unrivaled", - "Because the microphone has the best quality"] +gen_answers = [ + "Because the audio experience is unrivaled", + "Because the microphone has the best quality", +] # Run evaluation for gen_answer in gen_answers: - prompt=f"""User review: The CO-1T is a great pair of headphones! The sound quality is the \ + prompt = f"""User review: The CO-1T is a great pair of headphones! The sound quality is the \ best out there, and I can hear every detail of my music. Question: Why is the CO-1T a great headphone? Answer #1: {gen_answers[0]} @@ -116,7 +118,11 @@ for gen_answer in gen_answers: Given the question about the user review, state whether Answer #1 or Answer #2 provides \ the more accurate answer.""" - response = co.generate(prompt=prompt,max_tokens=50, temperature=0).generations[0].text + response = ( + co.generate(prompt=prompt, max_tokens=50, temperature=0) + .generations[0] + .text + ) print(response) ``` @@ -150,6 +156,7 @@ Here is an example using ROUGE: ```python PYTHON from collections import Counter + def rouge_1(reference, candidate): # Turn into unigrams reference_words = reference.split() @@ -158,8 +165,11 @@ def rouge_1(reference, candidate): # Compute the number of overlapping words reference_count = Counter(reference_words) candidate_count = Counter(candidate_words) - overlap = sum(min(candidate_count[w], reference_count[w]) for w in candidate_count) - + overlap = sum( + min(candidate_count[w], reference_count[w]) + for w in candidate_count + ) + # Compute precision, recall, and F1 score recall = overlap / len(reference_words) precision = overlap / len(candidate_words) @@ -169,7 +179,7 @@ def rouge_1(reference, candidate): return {"recall": recall, "precision": precision, "f1": f1} -for idx,gen_answer in enumerate(gen_answers): +for idx, gen_answer in enumerate(gen_answers): result = rouge_1(ref_answer, gen_answer) print(f"Answer #{idx+1}") print(f"Precision: {result['precision']:.2f}") diff --git a/fern/pages/llm-university/intro-prompt-engineering/use-case-patterns.mdx b/fern/pages/llm-university/intro-prompt-engineering/use-case-patterns.mdx index 5cbcab51e..7cfa09a3a 100644 --- a/fern/pages/llm-university/intro-prompt-engineering/use-case-patterns.mdx +++ b/fern/pages/llm-university/intro-prompt-engineering/use-case-patterns.mdx @@ -25,24 +25,24 @@ First, let’s install the Cohere package, get the [Cohere API key](https://dash ! pip install cohere import cohere -co = cohere.Client("COHERE_API_KEY") # Your Cohere API key +co = cohere.Client("COHERE_API_KEY") # Your Cohere API key ``` Let’s also define a function to take a [prompt](https://txt.cohere.com/generative-ai-part-1/) and a [temperature value](https://txt.cohere.com/generative-ai-part-1/#being-creative-vs-predictable) and then call the [Chat endpoint](/reference/chat?ref=txt.cohere.com), which is how we can access the Command model.​​ We set a default temperature value of 0, which nudges the response to be more predictable and less random. This function returns the text response generated by the model. ```python PYTHON def generate_text(prompt, temp=0): - response = co.chat_stream( - message=prompt, - model="command-r", - temperature=temp, - preamble="") - - for event in response: - if event.event_type == "text-generation": - print(event.text, end='') + response = co.chat_stream( + message=prompt, + model="command-r", + temperature=temp, + preamble="", + ) + for event in response: + if event.event_type == "text-generation": + print(event.text, end="") ``` Our examples will revolve around a company’s activities for launching a new wireless headphone product, such as getting the word out, managing customer interactions, and so on. For this, let’s define a text snippet containing the product description. We’ll be utilizing this snippet in several examples throughout this article. @@ -65,7 +65,7 @@ Here we can ask the model to write freeform text, for example, with this prompt: Here’s how we can do that. Let’s say we’re building an application for users to enter some bullet points and get a complete email written. We can set up the prompt in the following way: create a variable for the user to input some text and merge that, together with the product description, into the main prompt. ```python PYTHON -user_input =""" +user_input = """ - announce product launch - create a call to action - mention live chat for support @@ -78,7 +78,6 @@ Create an email about the product above mentioning the following: response = generate_text(prompt, temp=0.5) print(response) - ``` Adding this context helps to guide the model in the direction we want it to go. Here is a sample response: @@ -109,12 +108,11 @@ This use case is about answering a question that a user asks, be it in a single- Question answering can take place in either a closed or open setting. In a closed-book question answering setting, we rely on the model to answer questions based on the general knowledge from which it has been trained. Here’s one example: ```python PYTHON -user_input ="What features should I consider when choosing a wireless headphone" +user_input = "What features should I consider when choosing a wireless headphone" prompt = user_input response = generate_text(prompt, temp=0.5) print(response) - ``` Sample response: @@ -154,13 +152,12 @@ In this setting, we can get the model to refer to specific knowledge bases to he Here, a customer asks a product question. We can append the customer’s question and the product description to the prompt, as follows. ```python PYTHON -user_input ="How do I control the sound levels" +user_input = "How do I control the sound levels" prompt = f"""{product} Answer this question based on the context provided above: {user_input}""" generate_text(prompt, temp=0) - ``` And the model picks up the relevant information from the prompt to provide the correct answer. @@ -187,7 +184,6 @@ Provide a bulleted list of possible ways to troubleshoot so we can advise the cu response = generate_text(prompt, temp=0.3) print(response) - ``` Sample response: @@ -213,13 +209,12 @@ One example is transforming a passage of text into a different form, making it r For example, creating a list of Frequently Asked Questions (FAQs) about wireless headphones is crucial, but it requires some effort to create. We can cut short this process by getting the model to generate a list of FAQs based on the product description, as follows: ```python PYTHON -prompt =f"""Turn the following product description into a list of frequently asked questions (FAQ). +prompt = f"""Turn the following product description into a list of frequently asked questions (FAQ). Product description: {product} """ response = generate_text(prompt, temp=0) print(response) - ``` Sample response: @@ -253,7 +248,7 @@ One popular use case for synthesizing text is summarization. Here we take a long In this example, we create a prompt to summarize a list of customer reviews about the wireless headphone. ```python PYTHON -user_input ="""Customer reviews of the CO-1T wireless headphones: +user_input = """Customer reviews of the CO-1T wireless headphones: "The CO-1T is a great pair of headphones! The design is sleek and modern, and the headphones are \ very comfortable to wear. The sound quality is excellent, and I can hear every detail of my music. \ @@ -277,7 +272,6 @@ prompt = f"""Summarize the following. response = generate_text(prompt, temp=0) print(response) - ``` Example response: @@ -300,7 +294,6 @@ prompt = f"""Create a version of this product description that's tailored toward response = generate_text(prompt, temp=0.5) print(response) - ``` Sample response: @@ -317,18 +310,17 @@ Another extremely useful way of looking at text synthesis is information extract Here is an example of an email that a customer is, unfortunately, asking for a refund for the wireless headphone. We can have the model process this email by getting it to extract information, such as the product name, refund reason, and pick-up address. ```python PYTHON -user_input ="""I am writing to request a refund for a recent CO-1T purchase I made on your platform. \ +user_input = """I am writing to request a refund for a recent CO-1T purchase I made on your platform. \ Unfortunately, the produce has not met my expectations due to its poor battery life. \ Please arrange for the pick-up at this address: to 171 John Street, Toronto ON, M5T 1X2.""" -prompt =f"""Extract the product, refund reason and pick-up address from this email: +prompt = f"""Extract the product, refund reason and pick-up address from this email: {user_input} """ response = generate_text(prompt, temp=0) print(response) - ``` Sample response: @@ -347,7 +339,7 @@ One of the most widely deployed use cases in NLP is text classification. Here, t We can create the prompt as follows. ```python PYTHON -user_input ="The battery drains fast" +user_input = "The battery drains fast" prompt = f"""The following is a user message to a customer support agent. Classify the message into one of the following categories: Order, Support, or Refunds. @@ -357,7 +349,6 @@ Classify the message into one of the following categories: Order, Support, or Re response = generate_text(prompt, temp=0) print(response) - ``` Here’s a sample response where the generative model correctly classifies the text into the right category: @@ -375,15 +366,29 @@ Here’s how we can use the Classify endpoint. It requires a minimum of two exam from cohere import ClassifyExample response = co.classify( - inputs=[user_input], - examples=[ClassifyExample(text="I can\'t connect to the bluetooth", label="Support"), - ClassifyExample(text="Why is max volume so low", label="Support"), - ClassifyExample(text="When will my order arrive", label="Order"), - ClassifyExample(text="How much is the shipping cost", label="Order"), - ClassifyExample(text="What is your refund policy", label="Refunds"), - ClassifyExample(text="How do I return my product", label="Refunds")]) + inputs=[user_input], + examples=[ + ClassifyExample( + text="I can't connect to the bluetooth", label="Support" + ), + ClassifyExample( + text="Why is max volume so low", label="Support" + ), + ClassifyExample( + text="When will my order arrive", label="Order" + ), + ClassifyExample( + text="How much is the shipping cost", label="Order" + ), + ClassifyExample( + text="What is your refund policy", label="Refunds" + ), + ClassifyExample( + text="How do I return my product", label="Refunds" + ), + ], +) print(response.classifications[0].predictions[0]) - ``` Sample response: diff --git a/fern/pages/llm-university/intro-prompt-engineering/validating-outputs.mdx b/fern/pages/llm-university/intro-prompt-engineering/validating-outputs.mdx index 790db251d..c9cb02b11 100644 --- a/fern/pages/llm-university/intro-prompt-engineering/validating-outputs.mdx +++ b/fern/pages/llm-university/intro-prompt-engineering/validating-outputs.mdx @@ -24,7 +24,7 @@ However, one key property of LLMs that’s different from traditional software i Here’s an example. In [Chapter 1](/docs/constructing-prompts), we looked at a text extraction task of turning a list of bank invoices in a text document into a JSON object containing three fields: “Invoice Number,” “Merchant Name,” and “Account Number.” For brevity, we’ll turn it into a shorter version with the document containing just one invoice, as follows. ```python PYTHON -prompt="""Turn the following information into a JSON string with the following keys: Invoice Number, Merchant Name, and Account Number. +prompt = """Turn the following information into a JSON string with the following keys: Invoice Number, Merchant Name, and Account Number. Bank Invoice: INVOICE #0521 MERCHANT ALLBIRDS ACC XXX3846 """ ``` @@ -130,23 +130,45 @@ Next, we define the output schema that defines what the LLM response should look ```python PYTHON class Symptom(BaseModel): - symptom: str = Field(..., description="Symptom that a patient is experiencing") + symptom: str = Field( + ..., description="Symptom that a patient is experiencing" + ) affected_area: str = Field( ..., description="What part of the body the symptom is affecting", - validators=[ValidChoices(["Head", "Face", "Neck", "Chest"], on_fail="reask")] + validators=[ + ValidChoices( + ["Head", "Face", "Neck", "Chest"], on_fail="reask" + ) + ], ) + class CurrentMed(BaseModel): - medication: str = Field(..., description="Name of the medication the patient is taking") - response: str = Field(..., description="How the patient is responding to the medication") + medication: str = Field( + ..., + description="Name of the medication the patient is taking", + ) + response: str = Field( + ..., + description="How the patient is responding to the medication", + ) class PatientInfo(BaseModel): gender: str = Field(..., description="Patient's gender") - age: int = Field(..., description="Patient's age", validators=[ValidRange(0, 100)]) - symptoms: List[Symptom] = Field(..., description="Symptoms that the patient is experiencing") - current_meds: List[CurrentMed] = Field(..., description="Medications that the patient is currently taking") + age: int = Field( + ..., + description="Patient's age", + validators=[ValidRange(0, 100)], + ) + symptoms: List[Symptom] = Field( + ..., description="Symptoms that the patient is experiencing" + ) + current_meds: List[CurrentMed] = Field( + ..., + description="Medications that the patient is currently taking", + ) ``` In the schema, we defined a few “validators,” a Guardrails feature that lets us define the type of validation to perform. One example is `ValidChoices`, useful for situations where we want to enforce that a response can only be within a predefined list of items. In our example, in the `symptom` field, the value can only be one of head, neck, or chest. And if the generated response doesn’t fulfill this criteria, it will be re-prompted. This is shown by the `on_fail` setting that triggers a `reask`. @@ -228,7 +250,7 @@ We’re ready to run an LLM call using the Cohere `Generate` endpoint. For this, response = guard( co.chat, prompt_params={"doctors_notes": doctors_notes}, - model='command-r-plus', + model="command-r-plus", temperature=0, ) From 2efd81645deef973f0a6c679dcdc7b8d4f8046a0 Mon Sep 17 00:00:00 2001 From: Max Shkutnyk Date: Fri, 17 Jan 2025 21:23:00 +0200 Subject: [PATCH 04/12] Reformat code examples for LLM Univeristy Deployments section (#369) Co-authored-by: Max Shkutnyk --- .../deploying-with-aws-sagemaker.mdx | 13 +- .../deploying-with-databutton.mdx | 334 ++++++++++-------- .../deploying-with-fastapi.mdx | 132 +++++-- .../deploying-with-streamlit.mdx | 118 ++++--- 4 files changed, 364 insertions(+), 233 deletions(-) diff --git a/fern/pages/llm-university/intro-deployment/deploying-with-aws-sagemaker.mdx b/fern/pages/llm-university/intro-deployment/deploying-with-aws-sagemaker.mdx index bbd06b4ac..c969952bc 100644 --- a/fern/pages/llm-university/intro-deployment/deploying-with-aws-sagemaker.mdx +++ b/fern/pages/llm-university/intro-deployment/deploying-with-aws-sagemaker.mdx @@ -85,7 +85,9 @@ model_package_map = { region = boto3.Session().region_name if region not in model_package_map.keys(): - raise Exception(f"Current boto3 session region {region} is not supported.") + raise Exception( + f"Current boto3 session region {region} is not supported." + ) model_package_arn = model_package_map[region] ``` @@ -95,7 +97,12 @@ model_package_arn = model_package_map[region] ```python PYTHON co = Client(region_name=region) -co.create_endpoint(arn=model_package_arn, endpoint_name="cohere-gpt-xlarge", instance_type="ml.p4d.24xlarge", n_instances=1) +co.create_endpoint( + arn=model_package_arn, + endpoint_name="cohere-gpt-xlarge", + instance_type="ml.p4d.24xlarge", + n_instances=1, +) # You will get "---------!" as the output. This is expected. ``` @@ -103,7 +110,7 @@ co.create_endpoint(arn=model_package_arn, endpoint_name="cohere-gpt-xlarge", ins ### Step 4: Run Inference on the Endpoint ```python PYTHON -prompt="Write a creative product description for a wireless headphone product named the CO-1T" +prompt = "Write a creative product description for a wireless headphone product named the CO-1T" response = co.generate(prompt=prompt, max_tokens=100, temperature=0.9) diff --git a/fern/pages/llm-university/intro-deployment/deploying-with-databutton.mdx b/fern/pages/llm-university/intro-deployment/deploying-with-databutton.mdx index 10830f30c..549706999 100644 --- a/fern/pages/llm-university/intro-deployment/deploying-with-databutton.mdx +++ b/fern/pages/llm-university/intro-deployment/deploying-with-databutton.mdx @@ -51,34 +51,39 @@ The following are the helper functions mentioned above. ```python PYTHON # Function to generate Cohere embeddings -def embed_text(texts): - embeddings = \[] - for i in range(0, len(texts), 90): - batch = texts[i:i+90] - output = co.embed( +def embed_text(texts): + embeddings = [] + for i in range(0, len(texts), 90): + batch = texts[i : i + 90] + output = co.embed( model="embed-english-v3.0", - input_type="search_document", - texts=batch) - embeddings.extend(output.embeddings) - time.sleep(60) # accounting for Cohere trial API key rate limit + input_type="search_document", + texts=batch, + ) + embeddings.extend(output.embeddings) + time.sleep( + 60 + ) # accounting for Cohere trial API key rate limit return embeddings ``` ```python PYTHON # Function to reduce dimensionality of embeddings using umap -def reduce_dimensionality(embeddings): - reducer = umap.UMAP() - umap_embeddings = reducer.fit_transform(embeddings) + +def reduce_dimensionality(embeddings): + reducer = umap.UMAP() + umap_embeddings = reducer.fit_transform(embeddings) return umap_embeddings[:, 0], umap_embeddings[:, 1] ``` ```python PYTHON # Function to save embeddings into a json file in Databutton data storage -def save_embeddings_to_json(df): - # Create a dictionary where each key is the index of the DataFrame and each value is the corresponding embedding - embeddings_dict = df['embedding'].to_dict() + +def save_embeddings_to_json(df): + # Create a dictionary where each key is the index of the DataFrame and each value is the corresponding embedding + embeddings_dict = df["embedding"].to_dict() ``` ### Step 2: Create a User Interface with Streamlit @@ -99,7 +104,7 @@ The reduced embeddings are now saved as a new file. We can copy the code snippet ```python PYTHON # Call the embeddings data as a DataFrame -df = db.storage.dataframes.get(key=”reduced.csv”) +df = db.storage.dataframes.get(key="reduced.csv") ``` ### Step 3: Cluster Data to Identify Groups @@ -119,13 +124,13 @@ We will create a user interface that provides interactivity at a few crucial poi - **Display and save the results**: The script will display the DataFrame that now includes cluster labels and distances from centroids. If you’re satisfied with the results, you can save this labeled data back into Databutton’s storage for later use. ```python PYTHON -import databutton as db -import streamlit as st -from sklearn.cluster import KMeans -from sklearn.metrics import silhouette_score -import matplotlib.pyplot as plt -import numpy as np -import plotly.express as px +import databutton as db +import streamlit as st +from sklearn.cluster import KMeans +from sklearn.metrics import silhouette_score +import matplotlib.pyplot as plt +import numpy as np +import plotly.express as px from scipy.spatial import distance # 1: Load DataFrame @@ -134,59 +139,82 @@ df = db.storage.dataframes.get(key="reduced.csv") # 2: Extract UMAP coordinates -umapx = df['umap_x'] -umapy = df['umap_y'] +umapx = df["umap_x"] +umapy = df["umap_y"] umap_coords = np.column_stack((umapx, umapy)) # 3: Define a range of potential clusters and compute SSE -clusters = range(2, 10) # You may want to modify this range -sse = \[] -for k in clusters: - kmeans = KMeans(n_clusters=k, random_state=0) - kmeans.fit(umap_coords) +clusters = range(2, 10) # You may want to modify this range +sse = [] +for k in clusters: + kmeans = KMeans(n_clusters=k, random_state=0) + kmeans.fit(umap_coords) sse.append(kmeans.inertia_) # 4: Plot the elbow plot -fig, ax = plt.subplots(figsize=(10, 5)) -plt.plot(clusters, sse, 'bx-') -plt.xlabel('k (number of clusters)') -plt.ylabel('Sum of Squared Errors (SSE)') -plt.title('Elbow Plot For Optimal Number of Clusters') +fig, ax = plt.subplots(figsize=(10, 5)) +plt.plot(clusters, sse, "bx-") +plt.xlabel("k (number of clusters)") +plt.ylabel("Sum of Squared Errors (SSE)") +plt.title("Elbow Plot For Optimal Number of Clusters") st.pyplot(fig) # 5: User selects number of clusters based on elbow plot -n_clusters = st.slider('Number of Clusters', min_value=2, max_value=10, value=2) +n_clusters = st.slider( + "Number of Clusters", min_value=2, max_value=10, value=2 +) # 6: Run KMeans with optimal number of clusters -kmeans_model = KMeans(n_clusters=n_clusters, random_state=0) -df['cluster_labels'] = kmeans_model.fit_predict(umap_coords) +kmeans_model = KMeans(n_clusters=n_clusters, random_state=0) +df["cluster_labels"] = kmeans_model.fit_predict(umap_coords) # 7: Plotting the clusters -fig = px.scatter(df, x='umap_x', y='umap_y', color='cluster_labels', hover_data=['utt']) +fig = px.scatter( + df, + x="umap_x", + y="umap_y", + color="cluster_labels", + hover_data=["utt"], +) st.plotly_chart(fig) # 8: Calculate cluster centers and distances from centroids -centroids = df.groupby('cluster_labels')\[['umap_x', 'umap_y']].mean().reset_index() -def calc_distance(row): - centroid = centroids\[centroids['cluster_labels'] == row['cluster_labels']] - centroid_coords = (centroid['umap_x'].values[0], centroid['umap_y'].values[0]) - row_coords = (row['umap_x'], row['umap_y']) - return distance.euclidean(row_coords, centroid_coords) -df['distance_from_centroid'] = df.apply(calc_distance, axis=1) +centroids = ( + df.groupby("cluster_labels")[["umap_x", "umap_y"]] + .mean() + .reset_index() +) + + +def calc_distance(row): + centroid = centroids[ + centroids["cluster_labels"] == row["cluster_labels"] + ] + centroid_coords = ( + centroid["umap_x"].values[0], + centroid["umap_y"].values[0], + ) + row_coords = (row["umap_x"], row["umap_y"]) + return distance.euclidean(row_coords, centroid_coords) + + +df["distance_from_centroid"] = df.apply(calc_distance, axis=1) # 9: Display and save the results -selected_cluster = st.selectbox('Select a cluster label', df['cluster_labels'].unique()) -temp_df = df\[['utt', 'cluster_labels', 'distance_from_centroid']] -st.write(temp_df\[temp_df['cluster_labels'] == selected_cluster]) +selected_cluster = st.selectbox( + "Select a cluster label", df["cluster_labels"].unique() +) +temp_df = df[["utt", "cluster_labels", "distance_from_centroid"]] +st.write(temp_df[temp_df["cluster_labels"] == selected_cluster]) -if st.button("Save Labelled Data"): +if st.button("Save Labelled Data"): db.storage.dataframes.put(key="cluster.csv", df=df) ``` @@ -240,82 +268,100 @@ We create several helper functions for processing the DataFrame, generating keyw ```python PYTHON # Function to generate a name for each cluster -def generate_label(customer_service_prompt, text_series): - # Initialize Cohere model - COHERE_API_KEY = db.secrets.get(name="COHERE_API_KEY") - co = cohere.Client(COHERE_API_KEY) - text_list = text_series.tolist() - formatted_text_list = "" - for text in text_list: - formatted_text_list += "- " + text + "\\n" - prompt=customer_service_prompt + formatted_text_list - response = co.chat( - model='command-r', - message=prompt, - max_tokens=800, - temperature=0.2, - k=0) + +def generate_label(customer_service_prompt, text_series): + # Initialize Cohere model + COHERE_API_KEY = db.secrets.get(name="COHERE_API_KEY") + co = cohere.Client(COHERE_API_KEY) + text_list = text_series.tolist() + formatted_text_list = "" + for text in text_list: + formatted_text_list += "- " + text + "\\n" + prompt = customer_service_prompt + formatted_text_list + response = co.chat( + model="command-r", + message=prompt, + max_tokens=800, + temperature=0.2, + k=0, + ) return response.text, prompt ``` ```python PYTHON # Function to generate keywords for each cluster -def extract_top_n_words(vectorizer, tfidf_matrix, n=10): - """ - Given a TfidfVectorizer and a TF-IDF matrix, return the `n` words with the highest TF-IDF scores. - """ - # Get the names of the words - #feature_names = vectorizer.get_feature_names_out() - # Sum tfidf frequency of each term through documents - summed_tfidf = np.sum(tfidf_matrix, axis=0) +def extract_top_n_words(vectorizer, tfidf_matrix, n=10): + """ + Given a TfidfVectorizer and a TF-IDF matrix, return the `n` words with the highest TF-IDF scores. + """ + # Get the names of the words + # feature_names = vectorizer.get_feature_names_out() - # Connecting term to its sums frequency - words_freq = [(word, summed_tfidf[0, idx]) for word, idx in vectorizer.vocabulary_.items()] - words_freq = sorted(words_freq, key = lambda x: x[1], reverse=True) + # Sum tfidf frequency of each term through documents + summed_tfidf = np.sum(tfidf_matrix, axis=0) - # Return the n words with highest tfidf - return [word[0] for word in words_freq[:n]] + # Connecting term to its sums frequency + words_freq = [ + (word, summed_tfidf[0, idx]) + for word, idx in vectorizer.vocabulary_.items() + ] + words_freq = sorted(words_freq, key=lambda x: x[1], reverse=True) + + # Return the n words with highest tfidf + return [word[0] for word in words_freq[:n]] ``` ```python PYTHON # Helper function to generate the cluster name and keywords -@st.cache_resource -def generate_keywords_and_label(df, cluster, utterance_prompt): - # Filter the DataFrame for each cluster - df_cluster = df\[df['cluster_labels'] == cluster] - # Generate the TF-IDF matrix - vectorizer = TfidfVectorizer(stop_words='english') - tfidf_matrix = vectorizer.fit_transform(df_cluster['utt']) - # Extract the top N keywords from each cluster - keywords = extract_top_n_words(vectorizer, tfidf_matrix, n=10) +@st.cache_resource +def generate_keywords_and_label(df, cluster, utterance_prompt): + # Filter the DataFrame for each cluster + df_cluster = df[df["cluster_labels"] == cluster] + # Generate the TF-IDF matrix + vectorizer = TfidfVectorizer(stop_words="english") + tfidf_matrix = vectorizer.fit_transform(df_cluster["utt"]) - # Generate a summary label using the AI model - prompt = utterance_prompt + "\nKeywords for messages in this cluster: " + ', '.join(keywords) + "\n" - summary, prompt = generate_label(prompt, df_cluster['utt'].sample(n=5)) + # Extract the top N keywords from each cluster + keywords = extract_top_n_words(vectorizer, tfidf_matrix, n=10) - # Extract cluster name from AI generated label - start = summary.find("Cluster name:") + len("Cluster name:") - end = summary.find("\n", start) - cluster_name = summary[start:end].strip() + # Generate a summary label using the AI model + prompt = ( + utterance_prompt + + "\nKeywords for messages in this cluster: " + + ", ".join(keywords) + + "\n" + ) + summary, prompt = generate_label( + prompt, df_cluster["utt"].sample(n=5) + ) - # Update original DataFrame with generated label and keywords - df.loc[df['cluster_labels'] == cluster, 'label'] = cluster_name - df.loc[df['cluster_labels'] == cluster, 'keywords'] = ', '.join(keywords) + # Extract cluster name from AI generated label + start = summary.find("Cluster name:") + len("Cluster name:") + end = summary.find("\n", start) + cluster_name = summary[start:end].strip() + + # Update original DataFrame with generated label and keywords + df.loc[df["cluster_labels"] == cluster, "label"] = cluster_name + df.loc[df["cluster_labels"] == cluster, "keywords"] = ", ".join( + keywords + ) + + return df, keywords, cluster_name - return df, keywords, cluster_name # Helper function to present cluster data -def present_cluster_data(df, cluster, keywords, label): - df_cluster = df\[df['cluster_labels'] == cluster] - st.markdown(f"**Cluster {cluster}**") - st.markdown(f"**Generated Keywords:** {', '.join(keywords)}") - st.markdown(f"**AI Proposed Label:** {label}") - st.DataFrame(df_cluster[['utt', 'distance_from_centroid']]) + +def present_cluster_data(df, cluster, keywords, label): + df_cluster = df[df["cluster_labels"] == cluster] + st.markdown(f"**Cluster {cluster}**") + st.markdown(f"**Generated Keywords:** {', '.join(keywords)}") + st.markdown(f"**AI Proposed Label:** {label}") + st.DataFrame(df_cluster[["utt", "distance_from_centroid"]]) ``` And finally, putting the steps together for cluster names and keyword generation, as well as adding the user interaction steps, we have the following: @@ -328,12 +374,12 @@ And finally, putting the steps together for cluster names and keyword generation These are reflected in the corresponding code block. ```python PYTHON -from sklearn.feature_extraction.text import TfidfVectorizer -import databutton as db -import streamlit as st -import pandas as pd -import cohere -import numpy as np +from sklearn.feature_extraction.text import TfidfVectorizer +import databutton as db +import streamlit as st +import pandas as pd +import cohere +import numpy as np import time # helper functions... @@ -350,25 +396,29 @@ cluster_labels = {} vectorizer = TfidfVectorizer(stop_words="english") -clusters = df["cluster_labels"].unique() -if ( - st.button("Generate AI Labels", key="labelling", type="primary") - or st.session_state.load_state -): - st.session_state.load_state = True - for cluster in clusters: - df, keywords, label = generate_keywords_and_label(df, cluster, utterance_prompt) - present_cluster_data(df, cluster, keywords, label) - # Add user interaction to rename the label - state_key = f"user_label_{cluster}" - new_label = st.text_input( - f"Enter a new label for cluster {cluster} (leave empty to keep the AI proposed label)", - value=st.session_state.get(state_key, label), - key=state_key, - ) - if new_label != label: - df.loc\[df["cluster_labels"] == cluster, "label"] = new_label - +clusters = df["cluster_labels"].unique() +if ( + st.button("Generate AI Labels", key="labelling", type="primary") + or st.session_state.load_state +): + st.session_state.load_state = True + for cluster in clusters: + df, keywords, label = generate_keywords_and_label( + df, cluster, utterance_prompt + ) + present_cluster_data(df, cluster, keywords, label) + # Add user interaction to rename the label + state_key = f"user_label_{cluster}" + new_label = st.text_input( + f"Enter a new label for cluster {cluster} (leave empty to keep the AI proposed label)", + value=st.session_state.get(state_key, label), + key=state_key, + ) + if new_label != label: + df.loc[df["cluster_labels"] == cluster, "label"] = ( + new_label + ) + # For each cluster, find the utterance that is closest to the centroid for cluster in df["cluster_labels"].unique(): min_distance_idx = df[df["cluster_labels"] == cluster][ @@ -380,27 +430,33 @@ if ( # Create the scatter plot fig = px.scatter( - df, x="umap_x", y="umap_y", color="cluster_labels", hover_data=["utt", "label"] + df, + x="umap_x", + y="umap_y", + color="cluster_labels", + hover_data=["utt", "label"], ) # Add labels to the points that are closest to the centroid in each cluster for i in range(len(df)): if df.iloc[i]["utt"] == df.iloc[i]["closest_centroid_utt"]: fig.add_annotation( - x=df.iloc[i]["umap_x"], y=df.iloc[i]["umap_y"], text=df.iloc[i]["label"] + x=df.iloc[i]["umap_x"], + y=df.iloc[i]["umap_y"], + text=df.iloc[i]["label"], ) # Display the plot st.plotly_chart(fig) -save = st.button("Save changes", type="primary") -if save: - # Reset the input session states after save. Also reset the button state - st.session_state.load_state = False - for key in st.session_state.keys(): - if key.startswith('user_label_'): - del st.session_state[key] - db.storage.dataframes.put(key="labeled_cluster.csv", df=df) +save = st.button("Save changes", type="primary") +if save: + # Reset the input session states after save. Also reset the button state + st.session_state.load_state = False + for key in st.session_state.keys(): + if key.startswith("user_label_"): + del st.session_state[key] + db.storage.dataframes.put(key="labeled_cluster.csv", df=df) st.write("Labelled Data Saved") ``` diff --git a/fern/pages/llm-university/intro-deployment/deploying-with-fastapi.mdx b/fern/pages/llm-university/intro-deployment/deploying-with-fastapi.mdx index 9a28ab5e6..96510f770 100644 --- a/fern/pages/llm-university/intro-deployment/deploying-with-fastapi.mdx +++ b/fern/pages/llm-university/intro-deployment/deploying-with-fastapi.mdx @@ -56,25 +56,51 @@ We feed these examples to the `co.classify()` method via the `examples` argument If you need more information about the endpoint, visit the [Classify endpoint documentation](/reference/classify). ```python PYTHON -examples=[ClassifyExample(text="The order came 5 days early", label="positive"), - ClassifyExample(text="The item exceeded my expectations", label="positive"), - ClassifyExample(text="I ordered more for my friends", label="positive"), - ClassifyExample(text="I would buy this again", label="positive"), - ClassifyExample(text="I would recommend this to others", label="positive"), - ClassifyExample(text="The package was damaged", label="negative"), - ClassifyExample(text="The order is 5 days late", label="negative"), - ClassifyExample(text="The order was incorrect", label="negative"), - ClassifyExample(text="I want to return my item", label="negative"), - ClassifyExample(text="The item's material feels low quality", label="negative"), - ClassifyExample(text="The item was nothing special", label="neutral"), - ClassifyExample(text="I would not buy this again but it wasn't a waste of money", label="neutral"), - ClassifyExample(text="The item was neither amazing or terrible", label="neutral"), - ClassifyExample(text="The item was okay", label="neutral"), - ClassifyExample(text="I have no emotions towards this item", label="neutral")] +examples = [ + ClassifyExample( + text="The order came 5 days early", label="positive" + ), + ClassifyExample( + text="The item exceeded my expectations", label="positive" + ), + ClassifyExample( + text="I ordered more for my friends", label="positive" + ), + ClassifyExample(text="I would buy this again", label="positive"), + ClassifyExample( + text="I would recommend this to others", label="positive" + ), + ClassifyExample(text="The package was damaged", label="negative"), + ClassifyExample( + text="The order is 5 days late", label="negative" + ), + ClassifyExample(text="The order was incorrect", label="negative"), + ClassifyExample( + text="I want to return my item", label="negative" + ), + ClassifyExample( + text="The item's material feels low quality", label="negative" + ), + ClassifyExample( + text="The item was nothing special", label="neutral" + ), + ClassifyExample( + text="I would not buy this again but it wasn't a waste of money", + label="neutral", + ), + ClassifyExample( + text="The item was neither amazing or terrible", + label="neutral", + ), + ClassifyExample(text="The item was okay", label="neutral"), + ClassifyExample( + text="I have no emotions towards this item", label="neutral" + ), +] response = co.classify( - inputs=product_reviews.reviews, - examples=examples) + inputs=product_reviews.reviews, examples=examples +) ``` ### Step 3: Create a FastAPI Endpoint @@ -90,30 +116,66 @@ We take the code to call the Classify endpoint from the previous step and put it ```python PYTHON app = FastAPI() + class ProductReviews(BaseModel): reviews: conlist(str, min_length=1) + @app.post("/prediction") def predict_sentiment(product_reviews: ProductReviews): - examples=[ClassifyExample(text="The order came 5 days early", label="positive"), - ClassifyExample(text="The item exceeded my expectations", label="positive"), - ClassifyExample(text="I ordered more for my friends", label="positive"), - ClassifyExample(text="I would buy this again", label="positive"), - ClassifyExample(text="I would recommend this to others", label="positive"), - ClassifyExample(text="The package was damaged", label="negative"), - ClassifyExample(text="The order is 5 days late", label="negative"), - ClassifyExample(text="The order was incorrect", label="negative"), - ClassifyExample(text="I want to return my item", label="negative"), - ClassifyExample(text="The item's material feels low quality", label="negative"), - ClassifyExample(text="The item was nothing special", label="neutral"), - ClassifyExample(text="I would not buy this again but it wasn't a waste of money", label="neutral"), - ClassifyExample(text="The item was neither amazing or terrible", label="neutral"), - ClassifyExample(text="The item was okay", label="neutral"), - ClassifyExample(text="I have no emotions towards this item", label="neutral")] - + examples = [ + ClassifyExample( + text="The order came 5 days early", label="positive" + ), + ClassifyExample( + text="The item exceeded my expectations", label="positive" + ), + ClassifyExample( + text="I ordered more for my friends", label="positive" + ), + ClassifyExample( + text="I would buy this again", label="positive" + ), + ClassifyExample( + text="I would recommend this to others", label="positive" + ), + ClassifyExample( + text="The package was damaged", label="negative" + ), + ClassifyExample( + text="The order is 5 days late", label="negative" + ), + ClassifyExample( + text="The order was incorrect", label="negative" + ), + ClassifyExample( + text="I want to return my item", label="negative" + ), + ClassifyExample( + text="The item's material feels low quality", + label="negative", + ), + ClassifyExample( + text="The item was nothing special", label="neutral" + ), + ClassifyExample( + text="I would not buy this again but it wasn't a waste of money", + label="neutral", + ), + ClassifyExample( + text="The item was neither amazing or terrible", + label="neutral", + ), + ClassifyExample(text="The item was okay", label="neutral"), + ClassifyExample( + text="I have no emotions towards this item", + label="neutral", + ), + ] + response = co.classify( - inputs=product_reviews.reviews, - examples=examples) + inputs=product_reviews.reviews, examples=examples + ) return response.classifications ``` diff --git a/fern/pages/llm-university/intro-deployment/deploying-with-streamlit.mdx b/fern/pages/llm-university/intro-deployment/deploying-with-streamlit.mdx index 2821cab05..1a31dd54b 100644 --- a/fern/pages/llm-university/intro-deployment/deploying-with-streamlit.mdx +++ b/fern/pages/llm-university/intro-deployment/deploying-with-streamlit.mdx @@ -38,7 +38,7 @@ We then build a function that leverages Cohere’s [Python SDK](/generate-refere ```python PYTHON def generate_idea(industry): - prompt = f""" + prompt = f""" Generate a startup idea given the industry. # Examples @@ -56,14 +56,10 @@ Startup Idea: An online primary school that lets students mix and match their ow Industry: {industry}""" - # Call the Cohere Chat endpoint - response = co.chat( - model='command-r', - message=prompt, - preamble="") - - return response.text.replace("Startup Idea: ", "") + # Call the Cohere Chat endpoint + response = co.chat(model="command-r", message=prompt, preamble="") + return response.text.replace("Startup Idea: ", "") ``` Doing a quick test, entering “_Public Transportation_” returns the following startup idea: “_A small electronic device that notifies users when they have to get off the train or bus_”. Looking good so far. @@ -76,7 +72,7 @@ We create another function that takes in a startup idea as the input and returns ```python PYTHON def generate_name(idea): - prompt= f""" + prompt = f""" Generate a startup name and name given the startup idea. # Examples @@ -94,14 +90,10 @@ Startup Name: Prime Age Startup Idea: {idea}""" - # Call the Cohere Chat endpoint - response = co.chat( - model='command-r', - message=prompt, - preamble="") - - return response.text.replace("Startup Name: ", "") + # Call the Cohere Chat endpoint + response = co.chat(model="command-r", message=prompt, preamble="") + return response.text.replace("Startup Name: ", "") ``` Doing a quick test, entering the public transportation startup idea we got earlier returns the following startup name - “_Beepro_”. Not bad. @@ -119,14 +111,13 @@ st.title("🚀 Startup Idea Generator") form = st.form(key="user_settings") with form: - industry_input = st.text_input("Industry", key = "industry_input") + industry_input = st.text_input("Industry", key="industry_input") generate_button = form.form_submit_button("Generate Idea") if generate_button: startup_idea = generate_idea(industry_input) startup_name = generate_name(startup_idea) st.markdown("##### " + startup_name) st.write(startup_idea) - ``` It uses a number of features from the [Streamlit API](https://docs.streamlit.io/library/api-reference?ref=txt.cohere.com), as follows: @@ -162,14 +153,14 @@ For this, we’ll also use `st.slider()` to let the users control the `temperatu ```python PYTHON def generate_idea(industry, temperature): -... - response = co.chat( - model='command-r', - message=prompt, - temperature=temperature, - preamble="") -... - + # ... + response = co.chat( + model="command-r", + message=prompt, + temperature=temperature, + preamble="", + ) + # ... ``` Let’s also add a couple more things. First, we’ll use `st.progress()` to show a progress bar as the idea generation takes place. Second, we’ll add a check to the `Industry` user input to make it a required field. @@ -181,37 +172,52 @@ st.title("🚀 Startup Idea Generator") form = st.form(key="user_settings") with form: -# User input - Industry name -industry_input = st.text_input("Industry", key = "industry_input") - -# Create a two-column view -col1, col2 = st.columns(2) - -with col1: - # User input - The number of ideas to generate - num_input = st.slider("Number of ideas", value = 3, key = "num_input", min_value=1, max_value=10) - -with col2: - # User input - The 'temperature' value representing the level of creativity - creativity_input = st.slider("Creativity", value = 0.5, key = "creativity_input", min_value=0.1, max_value=0.9) - -# Submit button to start generating ideas -generate_button = form.form_submit_button("Generate Idea") - -if generate_button: - if industry_input == "": - st.error("Industry field cannot be blank") - else: - my_bar = st.progress(0.05) - st.subheader("Startup Ideas") - for i in range(num_input): - st.markdown("""---""") - startup_idea = generate_idea(industry_input,creativity_input) - startup_name = generate_name(startup_idea,creativity_input) - st.markdown("##### " + startup_name) - st.write(startup_idea) - my_bar.progress((i+1)/num_input) + # User input - Industry name + industry_input = st.text_input("Industry", key="industry_input") + + # Create a two-column view + col1, col2 = st.columns(2) + + with col1: + # User input - The number of ideas to generate + num_input = st.slider( + "Number of ideas", + value=3, + key="num_input", + min_value=1, + max_value=10, + ) + + with col2: + # User input - The 'temperature' value representing the level of creativity + creativity_input = st.slider( + "Creativity", + value=0.5, + key="creativity_input", + min_value=0.1, + max_value=0.9, + ) + + # Submit button to start generating ideas + generate_button = form.form_submit_button("Generate Idea") + if generate_button: + if industry_input == "": + st.error("Industry field cannot be blank") + else: + my_bar = st.progress(0.05) + st.subheader("Startup Ideas") + for i in range(num_input): + st.markdown("""---""") + startup_idea = generate_idea( + industry_input, creativity_input + ) + startup_name = generate_name( + startup_idea, creativity_input + ) + st.markdown("##### " + startup_name) + st.write(startup_idea) + my_bar.progress((i + 1) / num_input) ``` And with that, the final front-end now looks like the following. From 5e17307e8f877a9f025beecf73005bf398a1bd98 Mon Sep 17 00:00:00 2001 From: Max Shkutnyk Date: Fri, 17 Jan 2025 21:30:17 +0200 Subject: [PATCH 05/12] reformat code examples for integrations section (#370) Co-authored-by: Max Shkutnyk --- .../chat-on-langchain.mdx | 127 ++++++++------ .../embed-on-langchain.mdx | 50 +++--- .../rerank-on-langchain.mdx | 42 +++-- .../tools-on-langchain.mdx | 148 +++++++++++------ .../integrations/elasticsearch-and-cohere.mdx | 44 ++--- .../integrations/haystack-and-cohere.mdx | 156 +++++++++++++----- .../integrations/redis-and-cohere.mdx | 94 ++++++++--- fern/pages/integrations/llamaindex.mdx | 52 +++--- 8 files changed, 476 insertions(+), 237 deletions(-) diff --git a/fern/pages/integrations/cohere-and-langchain/chat-on-langchain.mdx b/fern/pages/integrations/cohere-and-langchain/chat-on-langchain.mdx index affc78f77..e51357cd0 100644 --- a/fern/pages/integrations/cohere-and-langchain/chat-on-langchain.mdx +++ b/fern/pages/integrations/cohere-and-langchain/chat-on-langchain.mdx @@ -25,8 +25,9 @@ from langchain_cohere import ChatCohere from langchain_core.messages import AIMessage, HumanMessage # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) # Send a chat message without chat history current_message = [HumanMessage(content="knock knock")] @@ -36,7 +37,8 @@ print(llm.invoke(current_message)) current_message_and_history = [ HumanMessage(content="knock knock"), AIMessage(content="Who's there?"), - HumanMessage(content="Tank") ] + HumanMessage(content="Tank"), +] print(llm.invoke(current_message_and_history)) ``` @@ -50,9 +52,13 @@ For example, using an internet search tool to get essay writing advice from Cohe ```python PYTHON from langchain_cohere import ChatCohere -from langchain_cohere.react_multi_hop.agent import create_cohere_react_agent +from langchain_cohere.react_multi_hop.agent import ( + create_cohere_react_agent, +) from langchain.agents import AgentExecutor -from langchain_community.tools.tavily_search import TavilySearchResults +from langchain_community.tools.tavily_search import ( + TavilySearchResults, +) from langchain_core.prompts import ChatPromptTemplate # Internet search tool - you can use any tool, and there are lots of community tools in LangChain. @@ -61,8 +67,9 @@ os.environ["TAVILY_API_KEY"] = "TAVILY_API_KEY" internet_search = TavilySearchResults() # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) # Create an agent agent = create_cohere_react_agent( @@ -72,7 +79,9 @@ agent = create_cohere_react_agent( ) # Create an agent executor -agent_executor = AgentExecutor(agent=agent, tools=[internet_search], verbose=True) +agent_executor = AgentExecutor( + agent=agent, tools=[internet_search], verbose=True +) # Generate a response response = agent_executor.invoke( @@ -103,8 +112,9 @@ from langchain_cohere import ChatCohere # User query we will use for the generation user_query = "What is cohere?" # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) # Create the Cohere rag retriever using the chat model rag = CohereRagRetriever(llm=llm, connectors=[]) # Create the wikipedia retriever @@ -139,16 +149,22 @@ from langchain_cohere import ChatCohere from langchain_core.documents import Document # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) # Create the Cohere rag retriever using the chat model rag = CohereRagRetriever(llm=llm, connectors=[]) docs = rag.invoke( "Does LangChain support cohere RAG?", documents=[ - Document(page_content="LangChain supports cohere RAG!", metadata={"id": "id-1"}), - Document(page_content="The sky is blue!", metadata={"id": "id-2"}), + Document( + page_content="LangChain supports cohere RAG!", + metadata={"id": "id-1"}, + ), + Document( + page_content="The sky is blue!", metadata={"id": "id-2"} + ), ], ) @@ -163,7 +179,7 @@ answer = docs[-1].page_content print("Answer:") print(answer) # Print the final citations -citations = docs[-1].metadata['citations'] +citations = docs[-1].metadata["citations"] print("Citations:") print(citations) ``` @@ -180,8 +196,9 @@ from langchain_cohere import ChatCohere from langchain_core.documents import Document # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) # Create the Cohere rag retriever using the chat model with the web search connector rag = CohereRagRetriever(llm=llm, connectors=[{"id": "web-search"}]) @@ -197,7 +214,7 @@ answer = docs[-1].page_content print("Answer:") print(answer) # Print the final citations -citations = docs[-1].metadata['citations'] +citations = docs[-1].metadata["citations"] print("Citations:") print(citations) ``` @@ -210,21 +227,26 @@ Note: this feature is currently in beta. from langchain_cohere import ChatCohere from langchain_core.documents import Document from langchain_core.prompts import ChatPromptTemplate -from langchain.chains.combine_documents import create_stuff_documents_chain +from langchain.chains.combine_documents import ( + create_stuff_documents_chain, +) prompt = ChatPromptTemplate.from_messages( [("human", "What are everyone's favorite colors:\n\n{context}")] ) # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) chain = create_stuff_documents_chain(llm, prompt) docs = [ Document(page_content="Jesse loves red but not yellow"), - Document(page_content = "Jamal loves green but not as much as he loves orange") + Document( + page_content="Jamal loves green but not as much as he loves orange" + ), ] chain.invoke({"context": docs}) @@ -239,25 +261,34 @@ You can specify the `response_format` parameter to indicate that you want the re from langchain_cohere import ChatCohere # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") - -res = llm.invoke("John is five years old", response_format={ - "type": "json_object", - "schema": { - "title": "Person", - "description": "Identifies the age and name of a person", - "type": "object", - "properties": { - "name": { "type": "string", "description": "Name of the person" }, - "age": { "type": "number", "description": "Age of the person" }, +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) + +res = llm.invoke( + "John is five years old", + response_format={ + "type": "json_object", + "schema": { + "title": "Person", + "description": "Identifies the age and name of a person", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the person", + }, + "age": { + "type": "number", + "description": "Age of the person", }, - "required": [ - "name", - "age", - ], - } - } + }, + "required": [ + "name", + "age", + ], + }, + }, ) print(res) @@ -276,9 +307,11 @@ loader = WebBaseLoader("https://docs.cohere.com/docs/cohere-toolkit") docs = loader.load() # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024", - temperature=0) +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", + model="command-r-plus-08-2024", + temperature=0, +) chain = load_summarize_chain(llm, chain_type="stuff") @@ -290,7 +323,9 @@ chain.invoke({"input_documents": docs}) You can use LangChain with privately deployed Cohere models. To use it, specify your model deployment URL in the `base_url` parameter. ```python PYTHON -llm = ChatCohere(base_url=, - cohere_api_key="COHERE_API_KEY", - model="MODEL_NAME") +llm = ChatCohere( + base_url="", + cohere_api_key="COHERE_API_KEY", + model="MODEL_NAME", +) ``` \ No newline at end of file diff --git a/fern/pages/integrations/cohere-and-langchain/embed-on-langchain.mdx b/fern/pages/integrations/cohere-and-langchain/embed-on-langchain.mdx index 5d6e045f5..b136b8769 100644 --- a/fern/pages/integrations/cohere-and-langchain/embed-on-langchain.mdx +++ b/fern/pages/integrations/cohere-and-langchain/embed-on-langchain.mdx @@ -25,8 +25,9 @@ To use [Cohere's Embeddings](/docs/embeddings) with LangChain, create a [CohereE from langchain_cohere import CohereEmbeddings # Define the Cohere embedding model -embeddings = CohereEmbeddings(cohere_api_key="COHERE_API_KEY", - model="embed-english-v3.0") +embeddings = CohereEmbeddings( + cohere_api_key="COHERE_API_KEY", model="embed-english-v3.0" +) # Embed a document text = "This is a test document." @@ -34,28 +35,37 @@ query_result = embeddings.embed_query(text) print(query_result[:5], "...") doc_result = embeddings.embed_documents([text]) print(doc_result[0][:5], "...") - ``` To use these embeddings with Cohere's RAG functionality, you will need to use one of the vector DBs [from this list](https://python.langchain.com/docs/integrations/vectorstores). In this example we use chroma, so in order to run it you will need to install chroma using `pip install chromadb`. ```python PYTHON -from langchain_cohere import ChatCohere, CohereEmbeddings, CohereRerank, CohereRagRetriever +from langchain_cohere import ( + ChatCohere, + CohereEmbeddings, + CohereRerank, + CohereRagRetriever, +) from langchain.text_splitter import CharacterTextSplitter from langchain_community.vectorstores import Chroma from langchain_community.document_loaders import WebBaseLoader -user_query = "what is Cohere Toolkit?" +user_query = "what is Cohere Toolkit?" -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024", - temperature=0) +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", + model="command-r-plus-08-2024", + temperature=0, +) -embeddings = CohereEmbeddings(cohere_api_key="COHERE_API_KEY", - model="embed-english-v3.0") +embeddings = CohereEmbeddings( + cohere_api_key="COHERE_API_KEY", model="embed-english-v3.0" +) # Load text files and split into chunks, you can also use data gathered elsewhere in your application -raw_documents = WebBaseLoader("https://docs.cohere.com/docs/cohere-toolkit").load() +raw_documents = WebBaseLoader( + "https://docs.cohere.com/docs/cohere-toolkit" +).load() text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0) documents = text_splitter.split_documents(raw_documents) @@ -63,7 +73,7 @@ documents = text_splitter.split_documents(raw_documents) db = Chroma.from_documents(documents, embeddings) input_docs = db.as_retriever().invoke(user_query) -# Create the cohere rag retriever using the chat model +# Create the cohere rag retriever using the chat model rag = CohereRagRetriever(llm=llm) docs = rag.invoke( user_query, @@ -75,12 +85,12 @@ for doc in docs[:-1]: print(doc.metadata) print("\n\n" + doc.page_content) print("\n\n" + "-" * 30 + "\n\n") -# Print the final generation +# Print the final generation answer = docs[-1].page_content print("Answer:") print(answer) -# Print the final citations -citations = docs[-1].metadata['citations'] +# Print the final citations +citations = docs[-1].metadata["citations"] print("Citations:") print(citations) ``` @@ -106,7 +116,7 @@ from langchain_aws import BedrockEmbeddings embeddings = BedrockEmbeddings( credentials_profile_name="{PROFILE-NAME}", region_name="us-east-1", - model_id="cohere.embed-english-v3" + model_id="cohere.embed-english-v3", ) embeddings.embed_query("This is a content of the document") @@ -116,7 +126,9 @@ embeddings.embed_query("This is a content of the document") You can use LangChain with privately deployed Cohere models. To use it, specify your model deployment URL in the `base_url` parameter. ```python PYTHON -llm = CohereEmbeddings(base_url=, - cohere_api_key="COHERE_API_KEY", - model="MODEL_NAME") +llm = CohereEmbeddings( + base_url="", + cohere_api_key="COHERE_API_KEY", + model="MODEL_NAME", +) ``` \ No newline at end of file diff --git a/fern/pages/integrations/cohere-and-langchain/rerank-on-langchain.mdx b/fern/pages/integrations/cohere-and-langchain/rerank-on-langchain.mdx index 9dfd7e463..9d4bcdd1f 100644 --- a/fern/pages/integrations/cohere-and-langchain/rerank-on-langchain.mdx +++ b/fern/pages/integrations/cohere-and-langchain/rerank-on-langchain.mdx @@ -33,33 +33,41 @@ from langchain_community.document_loaders import TextLoader from langchain_community.vectorstores import Chroma from langchain_community.document_loaders import WebBaseLoader -user_query = "what is Cohere Toolkit?" +user_query = "what is Cohere Toolkit?" # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) # Define the Cohere embedding model -embeddings = CohereEmbeddings(cohere_api_key="COHERE_API_KEY", - model="embed-english-light-v3.0") +embeddings = CohereEmbeddings( + cohere_api_key="COHERE_API_KEY", model="embed-english-light-v3.0" +) # Load text files and split into chunks, you can also use data gathered elsewhere in your application -raw_documents = WebBaseLoader("https://docs.cohere.com/docs/cohere-toolkit").load() -text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) +raw_documents = WebBaseLoader( + "https://docs.cohere.com/docs/cohere-toolkit" +).load() +text_splitter = CharacterTextSplitter( + chunk_size=1000, chunk_overlap=0 +) documents = text_splitter.split_documents(raw_documents) # Create a vector store from the documents db = Chroma.from_documents(documents, embeddings) # Create Cohere's reranker with the vector DB using Cohere's embeddings as the base retriever -reranker = CohereRerank(cohere_api_key="COHERE_API_KEY", - model="rerank-english-v3.0") +reranker = CohereRerank( + cohere_api_key="COHERE_API_KEY", model="rerank-english-v3.0" +) compression_retriever = ContextualCompressionRetriever( - base_compressor=reranker, - base_retriever=db.as_retriever() + base_compressor=reranker, base_retriever=db.as_retriever() +) +compressed_docs = compression_retriever.get_relevant_documents( + user_query ) -compressed_docs = compression_retriever.get_relevant_documents(user_query) # Print the relevant documents from using the embeddings and reranker print(compressed_docs) @@ -80,7 +88,7 @@ answer = docs[-1].page_content print("Answer:") print(answer) # Print the final citations -citations = docs[-1].metadata['citations'] +citations = docs[-1].metadata["citations"] print("Citations:") print(citations) ``` @@ -90,7 +98,9 @@ print(citations) You can use LangChain with privately deployed Cohere models. To use it, specify your model deployment URL in the `base_url` parameter. ```python PYTHON -llm = CohereRerank(base_url=, - cohere_api_key="COHERE_API_KEY", - model="MODEL_NAME") +llm = CohereRerank( + base_url="", + cohere_api_key="COHERE_API_KEY", + model="MODEL_NAME", +) ``` \ No newline at end of file diff --git a/fern/pages/integrations/cohere-and-langchain/tools-on-langchain.mdx b/fern/pages/integrations/cohere-and-langchain/tools-on-langchain.mdx index 5feecee13..3c1a3b42e 100644 --- a/fern/pages/integrations/cohere-and-langchain/tools-on-langchain.mdx +++ b/fern/pages/integrations/cohere-and-langchain/tools-on-langchain.mdx @@ -22,27 +22,38 @@ Multi-step is enabled by default. Here's an example of using it to put together ```python PYTHON from langchain.agents import AgentExecutor -from langchain_cohere.react_multi_hop.agent import create_cohere_react_agent +from langchain_cohere.react_multi_hop.agent import ( + create_cohere_react_agent, +) from langchain_core.prompts import ChatPromptTemplate from langchain_cohere import ChatCohere -from langchain_community.tools.tavily_search import TavilySearchResults +from langchain_community.tools.tavily_search import ( + TavilySearchResults, +) from pydantic import BaseModel, Field -os.environ["TAVILY_API_KEY"] ="TAVILY_API_KEY" +os.environ["TAVILY_API_KEY"] = "TAVILY_API_KEY" internet_search = TavilySearchResults() internet_search.name = "internet_search" internet_search.description = "Returns a list of relevant document snippets for a textual query retrieved from the internet." + class TavilySearchInput(BaseModel): - query: str = Field(description="Query to search the internet with") + query: str = Field( + description="Query to search the internet with" + ) + + internet_search.args_schema = TavilySearchInput # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024", - temperature=0) +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", + model="command-r-plus-08-2024", + temperature=0, +) # Preamble preamble = """ You are an expert who answers the user's question with the most relevant datasource. You are equipped with an internet search tool and a special vectorstore of information about how to write good essays. @@ -58,14 +69,18 @@ agent = create_cohere_react_agent( prompt=prompt, ) -agent_executor = AgentExecutor(agent=agent, tools=[internet_search], verbose=True) +agent_executor = AgentExecutor( + agent=agent, tools=[internet_search], verbose=True +) -response = agent_executor.invoke({ - "input": "Who is the mayor of the capital of Ontario", - "preamble": preamble, -}) +response = agent_executor.invoke( + { + "input": "Who is the mayor of the capital of Ontario", + "preamble": preamble, + } +) -print(response['output']) +print(response["output"]) ``` ## Single-Step Tool Use @@ -77,18 +92,27 @@ from langchain_cohere import ChatCohere from langchain_core.messages import HumanMessage from pydantic import BaseModel, Field + # Data model class web_search(BaseModel): """ The internet. Use web_search for questions that are related to anything else than agents, prompt engineering, and adversarial attacks. """ - query: str = Field(description="The query to use when searching the internet.") + + query: str = Field( + description="The query to use when searching the internet." + ) + class vectorstore(BaseModel): """ A vectorstore containing documents related to agents, prompt engineering, and adversarial attacks. Use the vectorstore for questions on these topics. """ - query: str = Field(description="The query to use when searching the vectorstore.") + + query: str = Field( + description="The query to use when searching the vectorstore." + ) + # Preamble preamble = """You are an expert at routing a user question to a vectorstore or web search. @@ -97,22 +121,27 @@ Use the vectorstore for questions on these topics. Otherwise, use web-search.""" # LLM with tool use and preamble # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) -llm_with_tools = llm.bind_tools(tools=[web_search, vectorstore], preamble=preamble) +llm_with_tools = llm.bind_tools( + tools=[web_search, vectorstore], preamble=preamble +) -messages = [HumanMessage("Who will the Bears draft first in the NFL draft?")] +messages = [ + HumanMessage("Who will the Bears draft first in the NFL draft?") +] response = llm_with_tools.invoke(messages, force_single_step=True) -print(response.response_metadata['tool_calls']) +print(response.response_metadata["tool_calls"]) messages = [HumanMessage("What are the types of agent memory?")] response = llm_with_tools.invoke(messages, force_single_step=True) -print(response.response_metadata['tool_calls']) +print(response.response_metadata["tool_calls"]) messages = [HumanMessage("Hi, How are you?")] response = llm_with_tools.invoke(messages, force_single_step=True) -print('tool_calls' in response.response_metadata) +print("tool_calls" in response.response_metadata) ``` ## SQL Agent @@ -136,13 +165,17 @@ print(db.get_usable_table_names()) db.run("SELECT * FROM Artist LIMIT 10;") # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024", - temperature=0) +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", + model="command-r-plus-08-2024", + temperature=0, +) agent_executor = create_sql_agent(llm, db=db, verbose=True) -resp = agent_executor.invoke("Show me the first 5 rows of the Album table.") +resp = agent_executor.invoke( + "Show me the first 5 rows of the Album table." +) print(resp) ``` @@ -153,17 +186,21 @@ LangChain's CSV Agent abstraction enables building agents that can interact with from langchain_cohere import ChatCohere, create_csv_agent # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024", - temperature=0) +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", + model="command-r-plus-08-2024", + temperature=0, +) agent_executor = create_csv_agent( llm, - "titanic.csv" # https://github.com/langchain-ai/langchain/blob/master/templates/csv-agent/titanic.csv + "titanic.csv", # https://github.com/langchain-ai/langchain/blob/master/templates/csv-agent/titanic.csv ) -resp = agent_executor.invoke({"input":"How many people were on the titanic?"}) -print(resp.get("output")) +resp = agent_executor.invoke( + {"input": "How many people were on the titanic?"} +) +print(resp.get("output")) ``` ## Streaming for Tool Calling @@ -174,6 +211,7 @@ When tools are called in a streaming context, message chunks will be populated w from langchain_core.tools import tool from langchain_cohere import ChatCohere + @tool def add(a: int, b: int) -> int: """Adds a and b.""" @@ -185,12 +223,15 @@ def multiply(a: int, b: int) -> int: """Multiplies a and b.""" return a * b + tools = [add, multiply] # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024", - temperature=0) +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", + model="command-r-plus-08-2024", + temperature=0, +) llm_with_tools = llm.bind_tools(tools) @@ -216,20 +257,25 @@ from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langchain_cohere import ChatCohere + # Create a state graph class State(TypedDict): messages: Annotated[list, add_messages] + graph_builder = StateGraph(State) # Define the Cohere LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) + # Add nodes def chatbot(state: State): return {"messages": [llm.invoke(state["messages"])]} + graph_builder.add_node("chatbot", chatbot) graph_builder.add_edge(START, "chatbot") graph_builder.add_edge("chatbot", END) @@ -240,7 +286,7 @@ graph = graph_builder.compile() # Run the chatbot while True: user_input = input("User: ") - print("User: "+ user_input) + print("User: " + user_input) if user_input.lower() in ["quit", "exit", "q"]: print("Goodbye!") break @@ -253,7 +299,9 @@ while True: To handle queries our chatbot can't answer "from memory", we'll integrate a web search tool. Our bot can use this tool to find relevant information and provide better responses. ```python PYTHON -from langchain_community.tools.tavily_search import TavilySearchResults +from langchain_community.tools.tavily_search import ( + TavilySearchResults, +) from langchain_cohere import ChatCohere from langgraph.graph import StateGraph, START from langgraph.graph.message import add_messages @@ -277,8 +325,9 @@ class State(TypedDict): graph_builder = StateGraph(State) # Define the LLM -llm = ChatCohere(cohere_api_key="COHERE_API_KEY", - model="command-r-plus-08-2024") +llm = ChatCohere( + cohere_api_key="COHERE_API_KEY", model="command-r-plus-08-2024" +) # Bind the tools to the LLM llm_with_tools = llm.bind_tools(tools) @@ -291,6 +340,7 @@ def chatbot(state: State): graph_builder.add_node("chatbot", chatbot) + class BasicToolNode: """A node that runs the tools requested in the last AIMessage.""" @@ -304,9 +354,9 @@ class BasicToolNode: raise ValueError("No message found in input") outputs = [] for tool_call in message.tool_calls: - tool_result = self.tools_by_name[tool_call["name"]].invoke( - tool_call["args"] - ) + tool_result = self.tools_by_name[ + tool_call["name"] + ].invoke(tool_call["args"]) outputs.append( ToolMessage( content=json.dumps(tool_result), @@ -320,6 +370,7 @@ class BasicToolNode: tool_node = BasicToolNode(tools=[tool]) graph_builder.add_node("tools", tool_node) + def route_tools( state: State, ) -> Literal["tools", "__end__"]: @@ -332,8 +383,13 @@ def route_tools( elif messages := state.get("messages", []): ai_message = messages[-1] else: - raise ValueError(f"No messages found in input state to tool_edge: {state}") - if hasattr(ai_message, "tool_calls") and len(ai_message.tool_calls) > 0: + raise ValueError( + f"No messages found in input state to tool_edge: {state}" + ) + if ( + hasattr(ai_message, "tool_calls") + and len(ai_message.tool_calls) > 0 + ): return "tools" return "__end__" diff --git a/fern/pages/integrations/integrations/elasticsearch-and-cohere.mdx b/fern/pages/integrations/integrations/elasticsearch-and-cohere.mdx index fe77aeb8a..11ac8c1e4 100644 --- a/fern/pages/integrations/integrations/elasticsearch-and-cohere.mdx +++ b/fern/pages/integrations/integrations/elasticsearch-and-cohere.mdx @@ -85,11 +85,12 @@ When creating your Elastic Serverless API key make sure to turn on Control secur ```python PYTHON ELASTICSEARCH_ENDPOINT = getpass("Elastic Endpoint: ") -ELASTIC_API_KEY = getpass("Elastic encoded API key: ") # Use the encoded API key +ELASTIC_API_KEY = getpass( + "Elastic encoded API key: " +) # Use the encoded API key client = Elasticsearch( - ELASTICSEARCH_ENDPOINT, - api_key=ELASTIC_API_KEY + ELASTICSEARCH_ENDPOINT, api_key=ELASTIC_API_KEY ) # Confirm the client has connected @@ -109,7 +110,9 @@ We will create an inference endpoint that uses `embed-english-v3.0` and `int8` o ```python PYTHON COHERE_API_KEY = getpass("Enter Cohere API key: ") # Delete the inference model if it already exists -client.options(ignore_status=[404]).inference.delete(inference_id="cohere_embeddings") +client.options(ignore_status=[404]).inference.delete( + inference_id="cohere_embeddings" +) client.inference.put( task_type="text_embedding", @@ -120,7 +123,7 @@ client.inference.put( "api_key": COHERE_API_KEY, "model_id": "embed-english-v3.0", "embedding_type": "int8", - "similarity": "cosine" + "similarity": "cosine", }, "task_settings": {}, }, @@ -141,14 +144,16 @@ The mapping of the destination index – the index that contains the embeddings Let's create an index named cohere-wiki-embeddings with the mappings we need ```python PYTHON -client.indices.delete(index="cohere-wiki-embeddings", ignore_unavailable=True) +client.indices.delete( + index="cohere-wiki-embeddings", ignore_unavailable=True +) client.indices.create( index="cohere-wiki-embeddings", mappings={ "properties": { "text_semantic": { "type": "semantic_text", - "inference_id": "cohere_embeddings" + "inference_id": "cohere_embeddings", }, "text": {"type": "text", "copy_to": "text_semantic"}, "wiki_id": {"type": "integer"}, @@ -157,7 +162,7 @@ client.indices.create( "langs": {"type": "integer"}, "title": {"type": "text"}, "paragraph_id": {"type": "integer"}, - "id": {"type": "integer"} + "id": {"type": "integer"}, } }, ) @@ -184,17 +189,18 @@ url = "https://raw.githubusercontent.com/cohere-ai/cohere-developer-experience/m response = requests.get(url) # Load the response data into a JSON object -jsonl_data = response.content.decode('utf-8').splitlines() +jsonl_data = response.content.decode("utf-8").splitlines() # Prepare the documents to be indexed documents = [] for line in jsonl_data: data_dict = json.loads(line) - documents.append({ - "_index": "cohere-wiki-embeddings", - "_source": data_dict, + documents.append( + { + "_index": "cohere-wiki-embeddings", + "_source": data_dict, } - ) + ) # Use the bulk endpoint to index helpers.bulk(client, documents) @@ -385,21 +391,21 @@ Next, we can easily get a grounded generation with citations from the Cohere Cha response = co.chat( message=query, documents=ranked_documents, - model='command-r-plus-08-2024' + model="command-r-plus-08-2024", ) source_documents = [] for citation in response.citations: - for document_id in citation.document_ids: - if document_id not in source_documents: - source_documents.append(document_id) + for document_id in citation.document_ids: + if document_id not in source_documents: + source_documents.append(document_id) print(f"Query: {query}") print(f"Response: {response.text}") print("Sources:") for document in response.documents: - if document['id'] in source_documents: - print(f"{document['title']}: {document['text']}") + if document["id"] in source_documents: + print(f"{document['title']}: {document['text']}") ``` And there you have it! A quick and easy implementation of hybrid search and RAG with Cohere and Elastic. diff --git a/fern/pages/integrations/integrations/haystack-and-cohere.mdx b/fern/pages/integrations/integrations/haystack-and-cohere.mdx index b5fdfd541..0e70b831c 100644 --- a/fern/pages/integrations/integrations/haystack-and-cohere.mdx +++ b/fern/pages/integrations/integrations/haystack-and-cohere.mdx @@ -39,7 +39,9 @@ In the example below, you will need to add your Cohere API key. We suggest using from haystack import Pipeline from haystack.components.builders import DynamicChatPromptBuilder from haystack.dataclasses import ChatMessage -from haystack_integrations.components.generators.cohere import CohereChatGenerator +from haystack_integrations.components.generators.cohere import ( + CohereChatGenerator, +) from haystack.utils import Secret import os @@ -47,24 +49,52 @@ COHERE_API_KEY = os.environ.get("COHERE_API_KEY") pipe = Pipeline() pipe.add_component("prompt_builder", DynamicChatPromptBuilder()) -pipe.add_component("llm", CohereChatGenerator(Secret.from_token(COHERE_API_KEY))) +pipe.add_component( + "llm", CohereChatGenerator(Secret.from_token(COHERE_API_KEY)) +) pipe.connect("prompt_builder", "llm") location = "Berlin" -system_message = ChatMessage.from_system("You are an assistant giving out valuable information to language learners.") -messages = [system_message, ChatMessage.from_user("Tell me about {{location}}")] - -res = pipe.run(data={"prompt_builder": {"template_variables": {"location": location}, "prompt_source": messages}}) +system_message = ChatMessage.from_system( + "You are an assistant giving out valuable information to language learners." +) +messages = [ + system_message, + ChatMessage.from_user("Tell me about {{location}}"), +] + +res = pipe.run( + data={ + "prompt_builder": { + "template_variables": {"location": location}, + "prompt_source": messages, + } + } +) print(res) ``` You can pass additional dynamic variables to the LLM, like so: ```python PYTHON -messages = [system_message, ChatMessage.from_user("What's the weather forecast for {{location}} in the next {{day_count}} days?")] - -res = pipe.run(data={"prompt_builder": {"template_variables": {"location": location, "day_count": "5"}, - "prompt_source": messages}}) +messages = [ + system_message, + ChatMessage.from_user( + "What's the weather forecast for {{location}} in the next {{day_count}} days?" + ), +] + +res = pipe.run( + data={ + "prompt_builder": { + "template_variables": { + "location": location, + "day_count": "5", + }, + "prompt_source": messages, + } + } +) print(res) ``` @@ -83,11 +113,15 @@ from haystack.components.converters import HTMLToDocument from haystack.dataclasses import ChatMessage from haystack.utils import Secret -from haystack_integrations.components.generators.cohere import CohereChatGenerator +from haystack_integrations.components.generators.cohere import ( + CohereChatGenerator, +) fetcher = LinkContentFetcher() converter = HTMLToDocument() -prompt_builder = DynamicChatPromptBuilder(runtime_variables=["documents"]) +prompt_builder = DynamicChatPromptBuilder( + runtime_variables=["documents"] +) llm = CohereChatGenerator(Secret.from_token(COHERE_API_KEY)) message_template = """Answer the following question based on the contents of the article: {{query}}\n @@ -102,7 +136,9 @@ rag_pipeline.add_component("prompt_builder", prompt_builder) rag_pipeline.add_component("llm", llm) rag_pipeline.connect("fetcher.streams", "converter.sources") -rag_pipeline.connect("converter.documents", "prompt_builder.documents") +rag_pipeline.connect( + "converter.documents", "prompt_builder.documents" +) rag_pipeline.connect("prompt_builder.prompt", "llm.messages") question = "What are the capabilities of Cohere?" @@ -110,8 +146,10 @@ question = "What are the capabilities of Cohere?" result = rag_pipeline.run( { "fetcher": {"urls": ["/reference/about"]}, - "prompt_builder": {"template_variables": {"query": question}, "prompt_source": messages}, - + "prompt_builder": { + "template_variables": {"query": question}, + "prompt_source": messages, + }, "llm": {"generation_kwargs": {"max_tokens": 165}}, }, ) @@ -129,20 +167,28 @@ Although these examples use an `InMemoryDocumentStore` to keep things simple, Ha ```python PYTHON from haystack import Pipeline -from haystack.components.retrievers.in_memory import InMemoryBM25Retriever +from haystack.components.retrievers.in_memory import ( + InMemoryBM25Retriever, +) from haystack.components.builders.prompt_builder import PromptBuilder from haystack.document_stores.in_memory import InMemoryDocumentStore -from haystack_integrations.components.generators.cohere import CohereGenerator +from haystack_integrations.components.generators.cohere import ( + CohereGenerator, +) from haystack import Document from haystack.utils import Secret import os + COHERE_API_KEY = os.environ.get("COHERE_API_KEY") docstore = InMemoryDocumentStore() -docstore.write_documents([ - Document(content="Rome is the capital of Italy"), - Document(content="Paris is the capital of France")]) +docstore.write_documents( + [ + Document(content="Rome is the capital of Italy"), + Document(content="Paris is the capital of France"), + ] +) query = "What is the capital of France?" @@ -158,20 +204,22 @@ Question: {{ query }}? """ pipe = Pipeline() -pipe.add_component("retriever", InMemoryBM25Retriever(document_store=docstore)) +pipe.add_component( + "retriever", InMemoryBM25Retriever(document_store=docstore) +) pipe.add_component("prompt_builder", PromptBuilder(template=template)) -pipe.add_component("llm", CohereGenerator(Secret.from_token(COHERE_API_KEY))) +pipe.add_component( + "llm", CohereGenerator(Secret.from_token(COHERE_API_KEY)) +) pipe.connect("retriever", "prompt_builder.documents") pipe.connect("prompt_builder", "llm") -res=pipe.run({ - "prompt_builder": { - "query": query - }, - "retriever": { - "query": query +res = pipe.run( + { + "prompt_builder": {"query": query}, + "retriever": {"query": query}, } -}) +) print(res) # {'llm': {'replies': [' Paris is the capital of France. It is known for its history, culture, and many iconic landmarks, such as the Eiffel Tower and Notre-Dame Cathedral. '], 'meta': [{'finish_reason': 'COMPLETE'}]}} @@ -190,28 +238,37 @@ from haystack import Pipeline from haystack import Document from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack.components.writers import DocumentWriter -from haystack_integrations.components.embedders.cohere import CohereDocumentEmbedder +from haystack_integrations.components.embedders.cohere import ( + CohereDocumentEmbedder, +) from haystack.utils import Secret import os COHERE_API_KEY = os.environ.get("COHERE_API_KEY") token = Secret.from_token(COHERE_API_KEY) -document_store = InMemoryDocumentStore(embedding_similarity_function="cosine") +document_store = InMemoryDocumentStore( + embedding_similarity_function="cosine" +) -documents = [Document(content="My name is Wolfgang and I live in Berlin"), - Document(content="I saw a black horse running"), - Document(content="Germany has many big cities")] +documents = [ + Document(content="My name is Wolfgang and I live in Berlin"), + Document(content="I saw a black horse running"), + Document(content="Germany has many big cities"), +] indexing_pipeline = Pipeline() -indexing_pipeline.add_component("embedder", CohereDocumentEmbedder(token)) -indexing_pipeline.add_component("writer", DocumentWriter(document_store=document_store)) +indexing_pipeline.add_component( + "embedder", CohereDocumentEmbedder(token) +) +indexing_pipeline.add_component( + "writer", DocumentWriter(document_store=document_store) +) indexing_pipeline.connect("embedder", "writer") indexing_pipeline.run({"embedder": {"documents": documents}}) print(document_store.filter_documents()) # [Document(id=..., content: 'My name is Wolfgang and I live in Berlin', embedding: vector of size 4096), Document(id=..., content: 'Germany has many big cities', embedding: vector of size 4096)] - ``` #### Retrieving Documents with Haystack and Cohere Embeddings @@ -220,19 +277,30 @@ After the indexing pipeline has added the embeddings to the document store, you ```python PYTHON from haystack import Pipeline -from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever -from haystack_integrations.components.embedders.cohere import CohereTextEmbedder +from haystack.components.retrievers.in_memory import ( + InMemoryEmbeddingRetriever, +) +from haystack_integrations.components.embedders.cohere import ( + CohereTextEmbedder, +) query_pipeline = Pipeline() -query_pipeline.add_component("text_embedder", CohereTextEmbedder(token)) -query_pipeline.add_component("retriever", InMemoryEmbeddingRetriever(document_store=document_store)) -query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") +query_pipeline.add_component( + "text_embedder", CohereTextEmbedder(token) +) +query_pipeline.add_component( + "retriever", + InMemoryEmbeddingRetriever(document_store=document_store), +) +query_pipeline.connect( + "text_embedder.embedding", "retriever.query_embedding" +) query = "Who lives in Berlin?" -result = query_pipeline.run({"text_embedder":{"text": query}}) +result = query_pipeline.run({"text_embedder": {"text": query}}) -print(result['retriever']['documents'][0]) +print(result["retriever"]["documents"][0]) # Document(id=..., text: 'My name is Wolfgang and I live in Berlin') ``` diff --git a/fern/pages/integrations/integrations/redis-and-cohere.mdx b/fern/pages/integrations/integrations/redis-and-cohere.mdx index 64ffb70b8..cda132056 100644 --- a/fern/pages/integrations/integrations/redis-and-cohere.mdx +++ b/fern/pages/integrations/integrations/redis-and-cohere.mdx @@ -110,7 +110,7 @@ For this guide, we will be using the Cohere `embed-english-v3.0 model` which has ```python PYTHON # create a vectorizer -api_key='{Insert your cohere API Key}' +api_key = "{Insert your cohere API Key}" cohere_vectorizer = CohereTextVectorizer( model="embed-english-v3.0", @@ -188,20 +188,22 @@ You can also visit: [http://localhost:8001/redis-stack/browser](http://localhost ```python PYTHON # read in your documents -jsonl_file_path='data/redis_guide_data.jsonl' +jsonl_file_path = "data/redis_guide_data.jsonl" -corpus=[] -text_to_embed=[] +corpus = [] +text_to_embed = [] -with jsonlines.open(jsonl_file_path, mode='r') as reader: +with jsonlines.open(jsonl_file_path, mode="r") as reader: for line in reader: corpus.append(line) # we want to store the embeddings of the field called `text` - text_to_embed.append(line['text']) + text_to_embed.append(line["text"]) # call embed_many which returns an array # hash data structures get serialized as a string and thus we store the embeddings in hashes as a byte string (handled by numpy) -res=cohere_vectorizer.embed_many(text_to_embed, input_type='search_document', as_buffer=True) +res = cohere_vectorizer.embed_many( + text_to_embed, input_type="search_document", as_buffer=True +) ``` We will be loading a subset of data which contains paragraphs from wikipedia - the data lives in a `jsonl` and we will need to parse it to get the text field which is what we are embedding. To do this, we load the file and read it line-by-line, creating a corpus object and a text_to_embed object. We then pass the text_to_embed object into `co.embed_many` which takes in an list of strings. @@ -210,16 +212,20 @@ We will be loading a subset of data which contains paragraphs from wikipedia - t ```python PYTHON # contruct the data payload to be uploaded to your index -data = [{"url": row['url'], - "title": row['title'], - "text": row['text'], - "wiki_id": row['wiki_id'], - "paragraph_id": row['paragraph_id'], - "id":row['id'], - "views":row['views'], - "langs":row['langs'], - "embedding":v} - for row, v in zip(corpus, res)] +data = [ + { + "url": row["url"], + "title": row["title"], + "text": row["text"], + "wiki_id": row["wiki_id"], + "paragraph_id": row["paragraph_id"], + "id": row["id"], + "views": row["views"], + "langs": row["langs"], + "embedding": v, + } + for row, v in zip(corpus, res) +] # load the data into your index index.load(data) @@ -233,20 +239,35 @@ At this point, your Redis DB is ready for semantic search! ```python PYTHON # use the Cohere vectorizer again to create a query embedding -query_embedding = cohere_vectorizer.embed("What did Microsoft release in 2015?", input_type='search_query',as_buffer=True) +query_embedding = cohere_vectorizer.embed( + "What did Microsoft release in 2015?", + input_type="search_query", + as_buffer=True, +) query = VectorQuery( vector=query_embedding, vector_field_name="embedding", - return_fields=["url","wiki_id","paragraph_id","id","views","langs","title","text",], - num_results=5 + return_fields=[ + "url", + "wiki_id", + "paragraph_id", + "id", + "views", + "langs", + "title", + "text", + ], + num_results=5, ) results = index.query(query) for doc in results: - print(f"Title:{doc['title']}\nText:{doc['text']}\nDistance {doc['vector_distance']}\n\n") + print( + f"Title:{doc['title']}\nText:{doc['text']}\nDistance {doc['vector_distance']}\n\n" + ) ``` Use the `VectorQuery` class to construct a query object - here you can specify the fields you’d like Redis to return as well as the number of results (i.e. for this example we set it to `5`). @@ -265,7 +286,9 @@ query.set_filter(tag_filter) results = index.query(query) for doc in results: - print(f"Title:{doc['title']}\nText:{doc['text']}\nDistance {doc['vector_distance']}\n") + print( + f"Title:{doc['title']}\nText:{doc['text']}\nDistance {doc['vector_distance']}\n" + ) ``` One feature of Redis is the ability to add [filtering](https://www.redisvl.com/api/query.html) to your queries on the fly. Here we are constructing a `tag filter` on the column `title` which was initialized in our schema with `type=tag`. @@ -274,24 +297,41 @@ One feature of Redis is the ability to add [filtering](https://www.redisvl.com/a ```python PYTHON # define a tag match on the title, text match on the text field, and numeric filter on the views field -filter_data=(Tag('title')=='Elizabeth II') & (Text("text")% "born") & (Num("views")>4500) +filter_data = ( + (Tag("title") == "Elizabeth II") + & (Text("text") % "born") + & (Num("views") > 4500) +) -query_embedding = co.embed("When was she born?", input_type='search_query',as_buffer=True) +query_embedding = co.embed( + "When was she born?", input_type="search_query", as_buffer=True +) # reinitialize the query with the filter expression query = VectorQuery( vector=query_embedding, vector_field_name="embedding", - return_fields=["url","wiki_id","paragraph_id","id","views","langs","title","text",], + return_fields=[ + "url", + "wiki_id", + "paragraph_id", + "id", + "views", + "langs", + "title", + "text", + ], num_results=5, - filter_expression=filter_data + filter_expression=filter_data, ) results = index.query(query) print(results) for doc in results: - print(f"Title:{doc['title']}\nText:{doc['text']}\nDistance {doc['vector_distance']}\nView {doc['views']}") + print( + f"Title:{doc['title']}\nText:{doc['text']}\nDistance {doc['vector_distance']}\nView {doc['views']}" + ) ``` Another feature of Redis is the ability to initialize a query with a set of filters called a [filter expression](https://www.redisvl.com/user_guide/hybrid_queries_02.html). A filter expression allows for the you to combine a set of filters over an arbitrary set of fields at query time. diff --git a/fern/pages/integrations/llamaindex.mdx b/fern/pages/integrations/llamaindex.mdx index 8ee80f411..d717550d9 100644 --- a/fern/pages/integrations/llamaindex.mdx +++ b/fern/pages/integrations/llamaindex.mdx @@ -30,10 +30,11 @@ To use Cohere's chat functionality with LlamaIndex create a [Cohere model object from llama_index.llms.cohere import Cohere from llama_index.core.llms import ChatMessage -cohere_model = Cohere(api_key="COHERE_API_KEY", - model="command-r-plus") +cohere_model = Cohere( + api_key="COHERE_API_KEY", model="command-r-plus" +) -message = ChatMessage(role="user", content= "What is 2 + 3?") +message = ChatMessage(role="user", content="What is 2 + 3?") response = cohere_model.chat([message]) print(response) @@ -49,7 +50,7 @@ from llama_index.embeddings.cohere import CohereEmbedding embed_model = CohereEmbedding( api_key="COHERE_API_KEY", model_name="embed-english-v3.0", - input_type="search_document", # Use search_query for queries, search_document for documents + input_type="search_document", # Use search_query for queries, search_document for documents ) # Generate Embeddings @@ -66,18 +67,20 @@ To use Cohere's rerank functionality with LlamaIndex create a [ Cohere Rerank ob ```python PYTHON from llama_index.postprocessor.cohere_rerank import CohereRerank -from llama_index.readers.web import SimpleWebPageReader # first, run `pip install llama-index-readers-web` +from llama_index.readers.web import ( + SimpleWebPageReader, +) # first, run `pip install llama-index-readers-web` # create index (we are using an example page from Cohere's docs) documents = SimpleWebPageReader(html_to_text=True).load_data( ["https://docs.cohere.com/v2/docs/prompt-tuner"] -) # you can replace this with any other reader or documents +) # you can replace this with any other reader or documents index = VectorStoreIndex.from_documents(documents=documents) # create reranker -cohere_rerank = CohereRerank(api_key="COHERE_API_KEY", - model="rerank-english-v3.0", - top_n=2) +cohere_rerank = CohereRerank( + api_key="COHERE_API_KEY", model="rerank-english-v3.0", top_n=2 +) # query the index query_engine = index.as_query_engine( @@ -96,6 +99,7 @@ print(response) # To view the source documents from llama_index.core.response.pprint_utils import pprint_response + pprint_response(response, show_source=True) ``` @@ -109,7 +113,9 @@ from llama_index.embeddings.cohere import CohereEmbedding from llama_index.postprocessor.cohere_rerank import CohereRerank from llama_index.core import Settings from llama_index.core import VectorStoreIndex -from llama_index.readers.web import SimpleWebPageReader # first, run `pip install llama-index-readers-web` +from llama_index.readers.web import ( + SimpleWebPageReader, +) # first, run `pip install llama-index-readers-web` # Create the embedding model embed_model = CohereEmbedding( @@ -119,23 +125,26 @@ embed_model = CohereEmbedding( ) # Create the service context with the cohere model for generation and embedding model -Settings.llm = Cohere(api_key="COHERE_API_KEY", - model="command-r-plus") +Settings.llm = Cohere( + api_key="COHERE_API_KEY", model="command-r-plus" +) Settings.embed_model = embed_model # create index (we are using an example page from Cohere's docs) documents = SimpleWebPageReader(html_to_text=True).load_data( ["https://docs.cohere.com/v2/docs/prompt-tuner"] -) # you can replace this with any other reader or documents +) # you can replace this with any other reader or documents index = VectorStoreIndex.from_documents(documents=documents) -# Create a cohere reranker -cohere_rerank = CohereRerank(api_key="COHERE_API_KEY", - model="rerank-english-v3.0", - top_n=2) +# Create a cohere reranker +cohere_rerank = CohereRerank( + api_key="COHERE_API_KEY", model="rerank-english-v3.0", top_n=2 +) # Create the query engine -query_engine = index.as_query_engine(node_postprocessors=[cohere_rerank]) +query_engine = index.as_query_engine( + node_postprocessors=[cohere_rerank] +) # Generate the response response = query_engine.query("What is Cohere Prompt Tuner?") @@ -151,22 +160,25 @@ from llama_index.llms.cohere import Cohere from llama_index.core.tools import FunctionTool from llama_index.core.agent import FunctionCallingAgent + # Define tools def multiply(a: int, b: int) -> int: """Multiple two integers and returns the result integer""" return a * b + multiply_tool = FunctionTool.from_defaults(fn=multiply) + def add(a: int, b: int) -> int: """Add two integers and returns the result integer""" return a + b + add_tool = FunctionTool.from_defaults(fn=add) # Define LLM -llm = Cohere(api_key="COHERE_API_KEY", - model="command-r-plus") +llm = Cohere(api_key="COHERE_API_KEY", model="command-r-plus") # Create agent agent = FunctionCallingAgent.from_tools( From 0b1c7a6e16cfd3523f4e3f30645c2533a0966118 Mon Sep 17 00:00:00 2001 From: Max Shkutnyk Date: Mon, 20 Jan 2025 18:24:01 +0200 Subject: [PATCH 06/12] Update titles for changelogs to have length between 30 and 60 characters for seo improvements (#371) Co-authored-by: Max Shkutnyk --- .../pages/changelog/2022-02-22-larger-representation-models.mdx | 2 +- fern/pages/changelog/2022-03-08-classification-endpoint.mdx | 2 +- fern/pages/changelog/2022-04-25-new-extremely-large-model.mdx | 2 +- .../pages/changelog/2022-07-07-model-parameter-now-optional.mdx | 2 +- fern/pages/changelog/2022-08-05-introducing-moderate-beta.mdx | 2 +- fern/pages/changelog/2022-11-07-new-look-for-docs.mdx | 2 +- fern/pages/changelog/2023-04-26-model-names-are-changing.mdx | 2 +- .../pages/changelog/2023-06-28-release-notes-june-28th-2023.mdx | 2 +- .../changelog/2023-08-05-release-notes-august-4th-2023.mdx | 2 +- fern/pages/changelog/2024-03-20-python-sdk-v500.mdx | 2 +- ...and-r-retrieval-augmented-generation-at-production-scale.mdx | 2 +- fern/pages/changelog/2024-04-03-python-sdk-v520-release.mdx | 2 +- fern/pages/changelog/2024-04-09-advanced-retrieval-launch.mdx | 2 +- .../changelog/2024-06-10-release-notes-for-june-10th-2024.mdx | 2 +- fern/pages/changelog/2024-09-26-refresh-models-on-azure.mdx | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/fern/pages/changelog/2022-02-22-larger-representation-models.mdx b/fern/pages/changelog/2022-02-22-larger-representation-models.mdx index df550124c..b3c795315 100644 --- a/fern/pages/changelog/2022-02-22-larger-representation-models.mdx +++ b/fern/pages/changelog/2022-02-22-larger-representation-models.mdx @@ -1,5 +1,5 @@ --- -title: Larger Representation Models +title: Larger Cohere Representation Models slug: changelog/larger-representation-models type: added createdAt: 'Tue Feb 22 2022 19:05:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2022-03-08-classification-endpoint.mdx b/fern/pages/changelog/2022-03-08-classification-endpoint.mdx index 38f7ef6e8..0e2709959 100644 --- a/fern/pages/changelog/2022-03-08-classification-endpoint.mdx +++ b/fern/pages/changelog/2022-03-08-classification-endpoint.mdx @@ -1,5 +1,5 @@ --- -title: Classification Endpoint +title: Introducing Classification Endpoint slug: changelog/classification-endpoint type: added createdAt: 'Tue Mar 08 2022 18:58:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2022-04-25-new-extremely-large-model.mdx b/fern/pages/changelog/2022-04-25-new-extremely-large-model.mdx index a5c67e25c..f034bac5c 100644 --- a/fern/pages/changelog/2022-04-25-new-extremely-large-model.mdx +++ b/fern/pages/changelog/2022-04-25-new-extremely-large-model.mdx @@ -1,5 +1,5 @@ --- -title: New Extremely Large Model! +title: New and Improved Extremely Large Model! slug: changelog/new-extremely-large-model type: added createdAt: 'Mon Apr 25 2022 17:48:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2022-07-07-model-parameter-now-optional.mdx b/fern/pages/changelog/2022-07-07-model-parameter-now-optional.mdx index 57a8dfc06..c50e42e3e 100644 --- a/fern/pages/changelog/2022-07-07-model-parameter-now-optional.mdx +++ b/fern/pages/changelog/2022-07-07-model-parameter-now-optional.mdx @@ -1,5 +1,5 @@ --- -title: Model parameter now optional. +title: The `model` Parameter Becomes Optional. slug: changelog/model-parameter-now-optional type: improved createdAt: 'Thu Jul 07 2022 17:47:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2022-08-05-introducing-moderate-beta.mdx b/fern/pages/changelog/2022-08-05-introducing-moderate-beta.mdx index 8ea2e9239..96718a1e3 100644 --- a/fern/pages/changelog/2022-08-05-introducing-moderate-beta.mdx +++ b/fern/pages/changelog/2022-08-05-introducing-moderate-beta.mdx @@ -1,5 +1,5 @@ --- -title: Introducing Moderate (Beta)! +title: Introducing Moderate Tool (Beta)! slug: changelog/introducing-moderate-beta type: added createdAt: 'Fri Aug 05 2022 17:46:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2022-11-07-new-look-for-docs.mdx b/fern/pages/changelog/2022-11-07-new-look-for-docs.mdx index d4c63b0d8..dfc1534da 100644 --- a/fern/pages/changelog/2022-11-07-new-look-for-docs.mdx +++ b/fern/pages/changelog/2022-11-07-new-look-for-docs.mdx @@ -1,5 +1,5 @@ --- -title: New Look For Docs! +title: New Look For Cohere Documentation! slug: changelog/new-look-for-docs type: improved createdAt: 'Mon Nov 07 2022 21:44:01 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2023-04-26-model-names-are-changing.mdx b/fern/pages/changelog/2023-04-26-model-names-are-changing.mdx index 3d8b9bc1e..ad887ab24 100644 --- a/fern/pages/changelog/2023-04-26-model-names-are-changing.mdx +++ b/fern/pages/changelog/2023-04-26-model-names-are-changing.mdx @@ -1,5 +1,5 @@ --- -title: Model Names Are Changing! +title: Cohere Model Names Are Changing! slug: changelog/model-names-are-changing type: improved createdAt: 'Wed Apr 26 2023 19:44:46 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2023-06-28-release-notes-june-28th-2023.mdx b/fern/pages/changelog/2023-06-28-release-notes-june-28th-2023.mdx index 6ea051be3..1a3121a64 100644 --- a/fern/pages/changelog/2023-06-28-release-notes-june-28th-2023.mdx +++ b/fern/pages/changelog/2023-06-28-release-notes-june-28th-2023.mdx @@ -1,5 +1,5 @@ --- -title: Release Notes June 28th 2023 +title: Release Notes June 28th 2023 (Changelog) slug: changelog/release-notes-june-28th-2023 type: added createdAt: 'Wed Jun 28 2023 15:50:46 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2023-08-05-release-notes-august-4th-2023.mdx b/fern/pages/changelog/2023-08-05-release-notes-august-4th-2023.mdx index 69583f3e4..063535976 100644 --- a/fern/pages/changelog/2023-08-05-release-notes-august-4th-2023.mdx +++ b/fern/pages/changelog/2023-08-05-release-notes-august-4th-2023.mdx @@ -1,5 +1,5 @@ --- -title: Release Notes August 8th 2023 +title: Release Notes August 8th 2023 (Changelog) slug: changelog/release-notes-august-4th-2023 type: '' createdAt: 'Sat Aug 05 2023 01:24:15 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2024-03-20-python-sdk-v500.mdx b/fern/pages/changelog/2024-03-20-python-sdk-v500.mdx index 36810dc3d..04d92f337 100644 --- a/fern/pages/changelog/2024-03-20-python-sdk-v500.mdx +++ b/fern/pages/changelog/2024-03-20-python-sdk-v500.mdx @@ -1,5 +1,5 @@ --- -title: Python SDK v5.0.0 +title: Cohere Python SDK v5.0.0 release slug: changelog/python-sdk-v500 type: '' createdAt: 'Wed Mar 20 2024 18:37:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2024-03-24-command-r-retrieval-augmented-generation-at-production-scale.mdx b/fern/pages/changelog/2024-03-24-command-r-retrieval-augmented-generation-at-production-scale.mdx index 366ae2313..42b00a819 100644 --- a/fern/pages/changelog/2024-03-24-command-r-retrieval-augmented-generation-at-production-scale.mdx +++ b/fern/pages/changelog/2024-03-24-command-r-retrieval-augmented-generation-at-production-scale.mdx @@ -1,5 +1,5 @@ --- -title: "Command R: Retrieval-Augmented Generation at Production Scale" +title: "Command R: Retrieval-Augmented Generation at Scale" slug: "changelog/command-r-retrieval-augmented-generation-at-production-scale" type: "" createdAt: "Sun Mar 24 2024 18:44:00 GMT+0000 (Coordinated Universal Time)" diff --git a/fern/pages/changelog/2024-04-03-python-sdk-v520-release.mdx b/fern/pages/changelog/2024-04-03-python-sdk-v520-release.mdx index 5c308d7f1..b019f2f9c 100644 --- a/fern/pages/changelog/2024-04-03-python-sdk-v520-release.mdx +++ b/fern/pages/changelog/2024-04-03-python-sdk-v520-release.mdx @@ -1,5 +1,5 @@ --- -title: Python SDK v5.2.0 release +title: Cohere Python SDK v5.2.0 release slug: changelog/python-sdk-v520-release type: '' createdAt: 'Wed Apr 03 2024 18:53:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2024-04-09-advanced-retrieval-launch.mdx b/fern/pages/changelog/2024-04-09-advanced-retrieval-launch.mdx index 1734cd2f7..3c8278316 100644 --- a/fern/pages/changelog/2024-04-09-advanced-retrieval-launch.mdx +++ b/fern/pages/changelog/2024-04-09-advanced-retrieval-launch.mdx @@ -1,5 +1,5 @@ --- -title: Advanced Retrieval Launch +title: Advanced Retrieval Launch release slug: changelog/advanced-retrieval-launch type: '' createdAt: 'Tue Apr 09 2024 02:53:14 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2024-06-10-release-notes-for-june-10th-2024.mdx b/fern/pages/changelog/2024-06-10-release-notes-for-june-10th-2024.mdx index 095e40786..e027aca0b 100644 --- a/fern/pages/changelog/2024-06-10-release-notes-for-june-10th-2024.mdx +++ b/fern/pages/changelog/2024-06-10-release-notes-for-june-10th-2024.mdx @@ -1,5 +1,5 @@ --- -title: 'Release Notes for June 10th 2024: Updates to Tool Use, SDKs, Billing' +title: 'Release Notes for June 10th 2024' slug: changelog/release-notes-for-june-10th-2024 type: '' createdAt: 'Mon Jun 10 2024 16:06:00 GMT+0000 (Coordinated Universal Time)' diff --git a/fern/pages/changelog/2024-09-26-refresh-models-on-azure.mdx b/fern/pages/changelog/2024-09-26-refresh-models-on-azure.mdx index adae46399..337b4e0f2 100644 --- a/fern/pages/changelog/2024-09-26-refresh-models-on-azure.mdx +++ b/fern/pages/changelog/2024-09-26-refresh-models-on-azure.mdx @@ -1,5 +1,5 @@ --- -title: "The refreshed Command R and Command R+ models are now on Azure" +title: "Refreshed Command R and R+ models now on Azure" slug: "changelog/refresh-models-on-azure" createdAt: "Thurs Sept 24 2024" hidden: false From e521a831ec8842213be8590af7f2d4a385165c2d Mon Sep 17 00:00:00 2001 From: platform-endpoints Date: Mon, 20 Jan 2025 21:21:24 +0000 Subject: [PATCH 07/12] Add spec changes Co-authored-by: Daniel <133696562+daniel-cohere@users.noreply.github.com> --- cohere-openapi.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cohere-openapi.yaml b/cohere-openapi.yaml index 0297e4ffa..cfb17e34a 100644 --- a/cohere-openapi.yaml +++ b/cohere-openapi.yaml @@ -22880,6 +22880,9 @@ components: function: type: object description: The function to be executed. + required: + - name + - parameters properties: name: type: string From f371606eb6c59321e1d04dd1d5b4147e49732901 Mon Sep 17 00:00:00 2001 From: Fern Support <126544928+fern-support@users.noreply.github.com> Date: Tue, 21 Jan 2025 09:08:33 -0500 Subject: [PATCH 08/12] suggested styling update (#366) Signed-off-by: Fern Support <126544928+fern-support@users.noreply.github.com> --- fern/assets/input.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fern/assets/input.css b/fern/assets/input.css index c92ee00d3..b12851aef 100644 --- a/fern/assets/input.css +++ b/fern/assets/input.css @@ -641,3 +641,7 @@ button[class^="Sidebar-link-buttonWrapper"] { .code-block-line-content span[style*="color: rgb(194, 195, 197)"] { color: rgb(155, 156, 158) !important; } + +:is(.dark) .simple-card-container { + --divider-border-color: #2c2c2c; +} From a0705e0ac3b06b554aa19ff25ad5e4e3046dcb7e Mon Sep 17 00:00:00 2001 From: cohere-advait Date: Tue, 21 Jan 2025 09:19:11 -0500 Subject: [PATCH 09/12] [bugfix] Add missing comma in creating-and-deploying-a-connector.mdx (#130) Add missing comma to Example Response JSON after "url" key. Signed-off-by: cohere-advait --- .../connectors/creating-and-deploying-a-connector.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fern/pages/text-generation/connectors/creating-and-deploying-a-connector.mdx b/fern/pages/text-generation/connectors/creating-and-deploying-a-connector.mdx index 6d700442b..51578dd59 100644 --- a/fern/pages/text-generation/connectors/creating-and-deploying-a-connector.mdx +++ b/fern/pages/text-generation/connectors/creating-and-deploying-a-connector.mdx @@ -80,7 +80,7 @@ The response from the connector should be a JSON object with a list of documents "id": "expense_doc_1", "title": "Expense Policies for external travel", "text": "You can expense any work-related...", - "url": "https://internal-site.com/expensing" + "url": "https://internal-site.com/expensing", "created_at": "2023-11-25T20:09:31Z", }, { From d55016655253c2f47aebda75377072bb87f02fec Mon Sep 17 00:00:00 2001 From: billytrend-cohere <144115527+billytrend-cohere@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:22:17 +0000 Subject: [PATCH 10/12] Add 500 error (#190) --- fern/pages/cohere-api/errors.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fern/pages/cohere-api/errors.mdx b/fern/pages/cohere-api/errors.mdx index 30d4da40f..525df5996 100644 --- a/fern/pages/cohere-api/errors.mdx +++ b/fern/pages/cohere-api/errors.mdx @@ -154,3 +154,7 @@ To resolve this error, consult [the API spec](https://docs.cohere.com/reference/ |failed to get rerank inference: request cancelled| |request cancelled by user| + +## 500 - Server Error + +500 responses are sent when there is an unexpected internal server error. To resolve these errors, please contact support via [email](mailto:support@cohere.com) or [discord](https://discord.gg/XW44jPfYJu) with details about your request and use case. From 1bb414960242c65e20cf68c484dab00ff922adce Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Tue, 21 Jan 2025 09:28:36 -0500 Subject: [PATCH 11/12] Remove font color on fern-mdx-link (#94) Signed-off-by: Andrew Jiang From 0fd2ec7405d9046298ee3da18f81b177a76d7317 Mon Sep 17 00:00:00 2001 From: Max Shkutnyk Date: Tue, 21 Jan 2025 16:56:29 +0200 Subject: [PATCH 12/12] Update page titles to fit seo requirements (#374) Co-authored-by: Max Shkutnyk --- fern/pages/v2/tutorials/agentic-rag.mdx | 2 +- .../v2/tutorials/agentic-rag/generating-parallel-queries.mdx | 2 +- .../v2/tutorials/agentic-rag/performing-tasks-sequentially.mdx | 2 +- fern/pages/v2/tutorials/build-things-with-cohere.mdx | 2 +- .../build-things-with-cohere/building-an-agent-with-cohere.mdx | 2 +- .../v2/tutorials/build-things-with-cohere/rag-with-cohere.mdx | 2 +- .../build-things-with-cohere/reranking-with-cohere.mdx | 2 +- .../build-things-with-cohere/semantic-search-with-cohere.mdx | 2 +- fern/pages/v2/tutorials/cookbooks.mdx | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fern/pages/v2/tutorials/agentic-rag.mdx b/fern/pages/v2/tutorials/agentic-rag.mdx index ddeeda538..2c90be019 100644 --- a/fern/pages/v2/tutorials/agentic-rag.mdx +++ b/fern/pages/v2/tutorials/agentic-rag.mdx @@ -1,5 +1,5 @@ --- -title: Agentic RAG +title: Building Agentic RAG with Cohere slug: /v2/docs/agentic-rag description: "Hands-on tutorials on building agentic RAG applications with Cohere" diff --git a/fern/pages/v2/tutorials/agentic-rag/generating-parallel-queries.mdx b/fern/pages/v2/tutorials/agentic-rag/generating-parallel-queries.mdx index f1fe7f0c2..bb0eaa71a 100644 --- a/fern/pages/v2/tutorials/agentic-rag/generating-parallel-queries.mdx +++ b/fern/pages/v2/tutorials/agentic-rag/generating-parallel-queries.mdx @@ -1,5 +1,5 @@ --- -title: Generating Parallel Queries +title: Generate Parallel Queries for Better RAG Retrieval slug: /v2/docs/generating-parallel-queries description: "Build an agentic RAG system that can expand a user query into a more optimized set of queries for retrieval." diff --git a/fern/pages/v2/tutorials/agentic-rag/performing-tasks-sequentially.mdx b/fern/pages/v2/tutorials/agentic-rag/performing-tasks-sequentially.mdx index 1306869fd..1686f8f1a 100644 --- a/fern/pages/v2/tutorials/agentic-rag/performing-tasks-sequentially.mdx +++ b/fern/pages/v2/tutorials/agentic-rag/performing-tasks-sequentially.mdx @@ -1,5 +1,5 @@ --- -title: Performing Tasks Sequentially +title: "Performing Tasks Sequentially with Cohere's RAG" slug: /v2/docs/performing-tasks-sequentially description: "Build an agentic RAG system that can handle user queries that require tasks to be performed in a sequence." diff --git a/fern/pages/v2/tutorials/build-things-with-cohere.mdx b/fern/pages/v2/tutorials/build-things-with-cohere.mdx index a37e84fda..4027e6a31 100644 --- a/fern/pages/v2/tutorials/build-things-with-cohere.mdx +++ b/fern/pages/v2/tutorials/build-things-with-cohere.mdx @@ -1,5 +1,5 @@ --- -title: Build Things with Cohere! +title: Build an Onboarding Assistant with Cohere! slug: /v2/docs/build-things-with-cohere description: "This page describes how to build an onboarding assistant with Cohere's large language models." diff --git a/fern/pages/v2/tutorials/build-things-with-cohere/building-an-agent-with-cohere.mdx b/fern/pages/v2/tutorials/build-things-with-cohere/building-an-agent-with-cohere.mdx index c20b1cbb7..78f2aa14e 100644 --- a/fern/pages/v2/tutorials/build-things-with-cohere/building-an-agent-with-cohere.mdx +++ b/fern/pages/v2/tutorials/build-things-with-cohere/building-an-agent-with-cohere.mdx @@ -1,5 +1,5 @@ --- -title: Building an Agent with Cohere +title: Building a Generative AI Agent with Cohere slug: /v2/docs/building-an-agent-with-cohere description: "This page describes building a generative-AI powered agent with Cohere." diff --git a/fern/pages/v2/tutorials/build-things-with-cohere/rag-with-cohere.mdx b/fern/pages/v2/tutorials/build-things-with-cohere/rag-with-cohere.mdx index 1924a3a6c..b32cd46c5 100644 --- a/fern/pages/v2/tutorials/build-things-with-cohere/rag-with-cohere.mdx +++ b/fern/pages/v2/tutorials/build-things-with-cohere/rag-with-cohere.mdx @@ -1,5 +1,5 @@ --- -title: RAG with Cohere +title: Building RAG models with Cohere slug: /v2/docs/rag-with-cohere description: "This page walks through building a retrieval-augmented generation model with Cohere." diff --git a/fern/pages/v2/tutorials/build-things-with-cohere/reranking-with-cohere.mdx b/fern/pages/v2/tutorials/build-things-with-cohere/reranking-with-cohere.mdx index b062b71ec..7de0ced5b 100644 --- a/fern/pages/v2/tutorials/build-things-with-cohere/reranking-with-cohere.mdx +++ b/fern/pages/v2/tutorials/build-things-with-cohere/reranking-with-cohere.mdx @@ -1,5 +1,5 @@ --- -title: Reranking with Cohere +title: Master Reranking with Cohere Models slug: /v2/docs/reranking-with-cohere description: "This page contains a tutorial on using Cohere's ReRank models." diff --git a/fern/pages/v2/tutorials/build-things-with-cohere/semantic-search-with-cohere.mdx b/fern/pages/v2/tutorials/build-things-with-cohere/semantic-search-with-cohere.mdx index 4450afad7..d87a2a528 100644 --- a/fern/pages/v2/tutorials/build-things-with-cohere/semantic-search-with-cohere.mdx +++ b/fern/pages/v2/tutorials/build-things-with-cohere/semantic-search-with-cohere.mdx @@ -1,5 +1,5 @@ --- -title: Semantic Search with Cohere +title: Semantic Search with Cohere Models slug: /v2/docs/semantic-search-with-cohere description: "This is a tutorial describing how to leverage Cohere's models for semantic search." diff --git a/fern/pages/v2/tutorials/cookbooks.mdx b/fern/pages/v2/tutorials/cookbooks.mdx index 770b0352a..4ee052db9 100644 --- a/fern/pages/v2/tutorials/cookbooks.mdx +++ b/fern/pages/v2/tutorials/cookbooks.mdx @@ -1,5 +1,5 @@ --- -title: Cookbooks Overview +title: "Cohere Cookbooks: Build AI Agents and Solutions" slug: v2/docs/cookbooks hidden: false description: >-