Skip to content

Commit 73a2099

Browse files
authored
Merge pull request stanfordnlp#3 from stanfordnlp/main
update
2 parents fa0b861 + 9c1fff9 commit 73a2099

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1180
-191
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ Or open our intro notebook in Google Colab: [<img align="center" src="https://co
7272

7373
By default, DSPy installs the latest `openai` from pip. However, if you install old version before OpenAI changed their API `openai~=0.28.1`, the library will use that just fine. Both are supported.
7474

75-
For the optional (alphabetically sorted) [Chromadb](https://github.com/chroma-core/chroma), [Qdrant](https://github.com/qdrant/qdrant), [Marqo](https://github.com/marqo-ai/marqo), Pinecone, [Weaviate](https://github.com/weaviate/weaviate),
75+
For the optional (alphabetically sorted) [Chromadb](https://github.com/chroma-core/chroma), [Qdrant](https://github.com/qdrant/qdrant), [Marqo](https://github.com/marqo-ai/marqo), Pinecone, [Snowflake](https://github.com/snowflakedb/snowpark-python) [Weaviate](https://github.com/weaviate/weaviate),
7676
or [Milvus](https://github.com/milvus-io/milvus) retrieval integration(s), include the extra(s) below:
7777

7878
```
79-
pip install dspy-ai[chromadb] # or [qdrant] or [marqo] or [mongodb] or [pinecone] or [weaviate] or [milvus]
79+
pip install dspy-ai[chromadb] # or [qdrant] or [marqo] or [mongodb] or [pinecone] or [snowflake] or [weaviate] or [milvus]
8080
```
8181

8282
## 2) Documentation
@@ -101,7 +101,7 @@ The DSPy documentation is divided into **tutorials** (step-by-step illustration
101101

102102
- [DSPy talk at ScaleByTheBay Nov 2023](https://www.youtube.com/watch?v=Dt3H2ninoeY).
103103
- [DSPy webinar with MLOps Learners](https://www.youtube.com/watch?v=im7bCLW2aM4), a bit longer with Q&A.
104-
- Hands-on Overviews of DSPy by the community: [DSPy Explained! by Connor Shorten](https://www.youtube.com/watch?v=41EfOY0Ldkc), [DSPy explained by code_your_own_ai](https://www.youtube.com/watch?v=ycfnKPxBMck), [DSPy Crash Course by AI Bites](https://youtu.be/5-zgASQKkKQ?si=3gnmVouT5_rpk_nu)
104+
- Hands-on Overviews of DSPy by the community: [DSPy Explained! by Connor Shorten](https://www.youtube.com/watch?v=41EfOY0Ldkc), [DSPy explained by code_your_own_ai](https://www.youtube.com/watch?v=ycfnKPxBMck), [DSPy Crash Course by AI Bites](https://youtu.be/5-zgASQKkKQ?si=3gnmVouT5_rpk_nu), [DSPy Paper Explained by Unify](https://youtu.be/kFB8kFchCH4?si=FuM6L5H5lweanckz)
105105
- Interviews: [Weaviate Podcast in-person](https://www.youtube.com/watch?v=CDung1LnLbY), and you can find 6-7 other remote podcasts on YouTube from a few different perspectives/audiences.
106106
- **Tracing in DSPy** with Arize Phoenix: [Tutorial for tracing your prompts and the steps of your DSPy programs](https://colab.research.google.com/github/Arize-ai/phoenix/blob/main/tutorials/tracing/dspy_tracing_tutorial.ipynb)
107107
- [DSPy: Not Your Average Prompt Engineering](https://jina.ai/news/dspy-not-your-average-prompt-engineering), why it's crucial for future prompt engineering, and yet why it is challenging for prompt engineers to learn.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
sidebar_position: 10
3+
---
4+
5+
# dspy.CloudflareAI
6+
7+
### Usage
8+
9+
```python
10+
lm = dspy.CloudflareAI(model="@hf/meta-llama/meta-llama-3-8b-instruct")
11+
```
12+
13+
### Constructor
14+
15+
The constructor initializes the base class `LM` and verifies the `api_key` and `account_id` for using Cloudflare AI API.
16+
The following environment variables are expected to be set or passed as arguments:
17+
18+
- `CLOUDFLARE_ACCOUNT_ID`: Account ID for Cloudflare.
19+
- `CLOUDFLARE_API_KEY`: API key for Cloudflare.
20+
21+
```python
22+
class CloudflareAI(LM):
23+
def __init__(
24+
self,
25+
model: str = "@hf/meta-llama/meta-llama-3-8b-instruct",
26+
account_id: Optional[str] = None,
27+
api_key: Optional[str] = None,
28+
system_prompt: Optional[str] = None,
29+
**kwargs,
30+
):
31+
```
32+
33+
**Parameters:**
34+
35+
- `model` (_str_): Model hosted on Cloudflare. Defaults to `@hf/meta-llama/meta-llama-3-8b-instruct`.
36+
- `account_id` (_Optional[str]_, _optional_): Account ID for Cloudflare. Defaults to None. Reads from environment variable `CLOUDFLARE_ACCOUNT_ID`.
37+
- `api_key` (_Optional[str]_, _optional_): API key for Cloudflare. Defaults to None. Reads from environment variable `CLOUDFLARE_API_KEY`.
38+
- `system_prompt` (_Optional[str]_, _optional_): System prompt to use for generation.
39+
40+
### Methods
41+
42+
Refer to [`dspy.OpenAI`](https://dspy-docs.vercel.app/api/language_model_clients/OpenAI) documentation.

docs/api/language_model_clients/Groq.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ lm = dspy.GROQ(model='mixtral-8x7b-32768', api_key ="gsk_***" )
1212

1313
### Constructor
1414

15-
The constructor initializes the base class `LM` and verifies the provided arguments like the `api_key` for GROQ api retriver. The `kwargs` attribute is initialized with default values for relevant text generation parameters needed for communicating with the GPT API, such as `temperature`, `max_tokens`, `top_p`, `frequency_penalty`, `presence_penalty`, and `n`.
15+
The constructor initializes the base class `LM` and verifies the provided arguments like the `api_key` for GROQ api retriver. The `kwargs` attribute is initialized with default values for relevant text generation parameters needed for communicating with the GROQ API, such as `temperature`, `max_tokens`, `top_p`, `frequency_penalty`, `presence_penalty`, and `n`.
1616

1717
```python
1818
class GroqLM(LM):
@@ -42,10 +42,10 @@ Internally, the method handles the specifics of preparing the request prompt and
4242
After generation, the generated content look like `choice["message"]["content"]`.
4343

4444
**Parameters:**
45-
- `prompt` (_str_): Prompt to send to OpenAI.
45+
- `prompt` (_str_): Prompt to send to GROQ.
4646
- `only_completed` (_bool_, _optional_): Flag to return only completed responses and ignore completion due to length. Defaults to True.
4747
- `return_sorted` (_bool_, _optional_): Flag to sort the completion choices using the returned averaged log-probabilities. Defaults to False.
4848
- `**kwargs`: Additional keyword arguments for completion request.
4949

5050
**Returns:**
51-
- `List[Dict[str, Any]]`: List of completion choices.
51+
- `List[Dict[str, Any]]`: List of completion choices.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
sidebar_position:
3+
---
4+
5+
# dspy.Snowflake
6+
7+
### Usage
8+
9+
```python
10+
import dspy
11+
import os
12+
13+
connection_parameters = {
14+
15+
"account": os.getenv('SNOWFLAKE_ACCOUNT'),
16+
"user": os.getenv('SNOWFLAKE_USER'),
17+
"password": os.getenv('SNOWFLAKE_PASSWORD'),
18+
"role": os.getenv('SNOWFLAKE_ROLE'),
19+
"warehouse": os.getenv('SNOWFLAKE_WAREHOUSE'),
20+
"database": os.getenv('SNOWFLAKE_DATABASE'),
21+
"schema": os.getenv('SNOWFLAKE_SCHEMA')}
22+
23+
lm = dspy.Snowflake(model="mixtral-8x7b",credentials=connection_parameters)
24+
```
25+
26+
### Constructor
27+
28+
The constructor inherits from the base class `LM` and verifies the `credentials` for using Snowflake API.
29+
30+
```python
31+
class Snowflake(LM):
32+
def __init__(
33+
self,
34+
model,
35+
credentials,
36+
**kwargs):
37+
```
38+
39+
**Parameters:**
40+
- `model` (_str_): model hosted by [Snowflake Cortex](https://docs.snowflake.com/en/user-guide/snowflake-cortex/llm-functions#availability).
41+
- `credentials` (_dict_): connection parameters required to initialize a [snowflake snowpark session](https://docs.snowflake.com/en/developer-guide/snowpark/reference/python/latest/api/snowflake.snowpark.Session)
42+
43+
### Methods
44+
45+
Refer to [`dspy.Snowflake`](https://dspy-docs.vercel.app/api/language_model_clients/Snowflake) documentation.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
sidebar_position:
3+
---
4+
5+
# retrieve.SnowflakeRM
6+
7+
### Constructor
8+
9+
Initialize an instance of the `SnowflakeRM` class, with the option to use `e5-base-v2` or `snowflake-arctic-embed-m` embeddings or any other Snowflake Cortex supported embeddings model.
10+
11+
```python
12+
SnowflakeRM(
13+
snowflake_table_name: str,
14+
snowflake_credentials: dict,
15+
k: int = 3,
16+
embeddings_field: str,
17+
embeddings_text_field:str,
18+
embeddings_model: str = "e5-base-v2",
19+
)
20+
```
21+
22+
**Parameters:**
23+
24+
- `snowflake_table_name (str)`: The name of the Snowflake table containing embeddings.
25+
- `snowflake_credentials (dict)`: The connection parameters needed to initialize a Snowflake Snowpark Session.
26+
- `k (int, optional)`: The number of top passages to retrieve. Defaults to 3.
27+
- `embeddings_field (str)`: The name of the column in the Snowflake table containing the embeddings.
28+
- `embeddings_text_field (str)`: The name of the column in the Snowflake table containing the passages.
29+
- `embeddings_model (str)`: The model to be used to convert text to embeddings
30+
31+
### Methods
32+
33+
#### `forward(self, query_or_queries: Union[str, List[str]], k: Optional[int] = None) -> dspy.Prediction`
34+
35+
Search the Snowflake table for the top `k` passages matching the given query or queries, using embeddings generated via the default `e5-base-v2` model or the specified `embedding_model`.
36+
37+
**Parameters:**
38+
39+
- `query_or_queries` (_Union[str, List[str]]_): The query or list of queries to search for.
40+
- `k` (_Optional[int]_, _optional_): The number of results to retrieve. If not specified, defaults to the value set during initialization.
41+
42+
**Returns:**
43+
44+
- `dspy.Prediction`: Contains the retrieved passages, each represented as a `dotdict` with schema `[{"id": str, "score": float, "long_text": str, "metadatas": dict }]`
45+
46+
### Quickstart
47+
48+
To support passage retrieval, it assumes that a Snowflake table has been created and populated with the passages in a column `embeddings_text_field` and the embeddings in another column `embeddings_field`
49+
50+
SnowflakeRM uses `e5-base-v2` embeddings model by default or any Snowflake Cortex supported embeddings model.
51+
52+
#### Default OpenAI Embeddings
53+
54+
```python
55+
from dspy.retrieve.snowflake_rm import SnowflakeRM
56+
import os
57+
58+
connection_parameters = {
59+
60+
"account": os.getenv('SNOWFLAKE_ACCOUNT'),
61+
"user": os.getenv('SNOWFLAKE_USER'),
62+
"password": os.getenv('SNOWFLAKE_PASSWORD'),
63+
"role": os.getenv('SNOWFLAKE_ROLE'),
64+
"warehouse": os.getenv('SNOWFLAKE_WAREHOUSE'),
65+
"database": os.getenv('SNOWFLAKE_DATABASE'),
66+
"schema": os.getenv('SNOWFLAKE_SCHEMA')}
67+
68+
retriever_model = SnowflakeRM(
69+
snowflake_table_name="<YOUR_SNOWFLAKE_TABLE_NAME>",
70+
snowflake_credentials=connection_parameters,
71+
embeddings_field="<YOUR_EMBEDDINGS_COLUMN_NAME>",
72+
embeddings_text_field= "<YOUR_PASSAGE_COLUMN_NAME>"
73+
)
74+
75+
results = retriever_model("Explore the meaning of life", k=5)
76+
77+
for result in results:
78+
print("Document:", result.long_text, "\n")
79+
```

docs/docs/building-blocks/6-optimizers.md

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,40 +27,54 @@ DSPy programs consist of multiple calls to LMs, stacked together as [DSPy module
2727

2828
Given a metric, DSPy can optimize all of these three with multi-stage optimization algorithms. These can combine gradient descent (for LM weights) and discrete LM-driven optimization, i.e. for crafting/updating instructions and for creating/validating demonstrations. DSPy Demonstrations are like few-shot examples, but they're far more powerful. They can be created from scratch, given your program, and their creation and selection can be optimized in many effective ways.
2929

30-
In many cases, we found that compiling leads to better prompts than humans write. Not because DSPy optimizers are more creative than humans, but simply because they can try more things, much more systematically, and tune the metrics directly.
30+
In many cases, we found that compiling leads to better prompts than human writing. Not because DSPy optimizers are more creative than humans, but simply because they can try more things, much more systematically, and tune the metrics directly.
3131

3232

3333
## What DSPy Optimizers are currently available?
3434

35+
<!-- The following diagram was generated by: -->
36+
<!-- 1. Running symilar on the teleprompter module to extract the python hierarchy as a Graphviz dot file -->
37+
<!-- 2. Hand-editing the resulting dot file to remove classes that are not teleprompters/optimizers (e.g., classes for data structures manipulated by optimizers). -->
38+
<!-- 3. Using dot to compile the `.dot` file into a PNG -->
39+
<!-- Robert Goldman [2024/05/11:rpg] -->
40+
41+
[Subclasses of Teleprompter](figures/teleprompter-classes.png)
42+
3543
All of these can be accessed via `from dspy.teleprompt import *`.
3644

3745
#### Automatic Few-Shot Learning
3846

39-
1. **`LabeledFewShot`**: Simply constructs few-shot examples from provided labeled Q/A pairs.
47+
These optimizers extend the signature by automatically generating and including **optimized** examples within the prompt sent to the model, implementing few-shot learning.
48+
49+
1. **`LabeledFewShot`**: Simply constructs few-shot examples (demos) from provided labeled input and output data points. Requires `k` (number of examples for the prompt) and `trainset` to randomly select `k` examples from.
50+
51+
2. **`BootstrapFewShot`**: Uses a `teacher` module (which defaults to your program) to generate complete demonstrations for every stage of your program, along with labeled examples in `trainset`. Parameters include `max_labeled_demos` (the number of demonstrations randomly selected from the `trainset`) and `max_bootstrapped_demos` (the number of additional examples generated by the `teacher`). The bootstrapping process employs the metric to validate demonstrations, including only those that pass the metric in the "compiled" prompt. Advanced: Supports using a `teacher` program that is a *different* DSPy program that has compatible structure, for harder tasks.
4052

41-
2. **`BootstrapFewShot`**: Uses your program to self-generate complete demonstrations for every stage of your program. Will simply use the generated demonstrations (if they pass the metric) without any further optimization. Advanced: Supports using a teacher program (a different DSPy program that has compatible structure) and a teacher LM, for harder tasks.
53+
3. **`BootstrapFewShotWithRandomSearch`**: Applies `BootstrapFewShot` several times with random search over generated demonstrations, and selects the best program over the optimization. Parameters mirror those of `BootstrapFewShot`, with the addition of `num_candidate_programs`, which specifies the number of random programs evaluated over the optimization, including candidates of the uncompiled program, `LabeledFewShot` optimized program, `BootstrapFewShot` compiled program with unshuffled examples and `num_candidate_programs` of `BootstrapFewShot` compiled programs with randomized example sets.
4254

43-
3. **`BootstrapFewShotWithRandomSearch`**: Applies `BootstrapFewShot` several times with random search over generated demonstrations, and selects the best program.
55+
4. **`BootstrapFewShotWithOptuna`**: Applies `BootstrapFewShot` with Optuna optimization across demonstration sets, running trials to maximize evaluation metrics and selecting the best demonstrations.
4456

45-
4. **`BootstrapFewShotWithOptuna`**: Applies `BootstrapFewShot` through Optuna hyperparameter optimization across demonstration sets, running trials to maximize evaluation metrics.
57+
5. **`KNNFewShot`**. Selects demonstrations through k-Nearest Neighbors algorithm to pick a diverse set of examples from different clusters. Vectorizes the examples, and then clusters them, using cluster centers with `BootstrapFewShot` for bootstrapping/selection process. This will be useful when there's a lot of data over random spaces: using KNN helps optimize the `trainset` for `BootstrapFewShot`. See [this notebook](https://github.com/stanfordnlp/dspy/blob/main/examples/knn.ipynb) for an example.
4658

4759

4860
#### Automatic Instruction Optimization
4961

50-
4. **`COPRO`**: Generates and refines new instructions for each step, and optimizes them with coordinate ascent.
62+
These optimizers produce optimal instructions for the prompt and, in the case of MIPRO also optimize the set of few-shot demonstrations.
5163

52-
5. **`MIPRO`**: Generates instructions and few-shot examples in each step. The instruction generation is data-aware and demonstration-aware. Uses Bayesian Optimization to effectively search over the space of generation instructions/demonstrations across your modules.
64+
6. **`COPRO`**: Generates and refines new instructions for each step, and optimizes them with coordinate ascent (hill-climbing using the metric function and the `trainset`). Parameters include `depth` which is the number of iterations of prompt improvement the optimizer runs over.
65+
66+
7. **`MIPRO`**: Generates instructions *and* few-shot examples in each step. The instruction generation is data-aware and demonstration-aware. Uses Bayesian Optimization to effectively search over the space of generation instructions/demonstrations across your modules.
5367

5468

5569
#### Automatic Finetuning
5670

71+
This optimizer is used to fine-tune the underlying LLM(s).
72+
5773
6. **`BootstrapFinetune`**: Distills a prompt-based DSPy program into weight updates (for smaller LMs). The output is a DSPy program that has the same steps, but where each step is conducted by a finetuned model instead of a prompted LM.
5874

5975

6076
#### Program Transformations
6177

62-
7. **`KNNFewShot`**. Selects demonstrations through k-Nearest Neighbors algorithm integrating `BootstrapFewShot` for bootstrapping/selection process.
63-
6478
8. **`Ensemble`**: Ensembles a set of DSPy programs and either uses the full set or randomly samples a subset into a single program.
6579

6680

@@ -90,7 +104,7 @@ from dspy.teleprompt import BootstrapFewShotWithRandomSearch
90104

91105
# Set up the optimizer: we want to "bootstrap" (i.e., self-generate) 8-shot examples of your program's steps.
92106
# The optimizer will repeat this 10 times (plus some initial attempts) before selecting its best attempt on the devset.
93-
config = dict(max_bootstrapped_demos=3, max_labeled_demos=3, num_candidate_programs=10, num_threads=4)
107+
config = dict(max_bootstrapped_demos=4, max_labeled_demos=4, num_candidate_programs=10, num_threads=4)
94108

95109
teleprompter = BootstrapFewShotWithRandomSearch(metric=YOUR_METRIC_HERE, **config)
96110
optimized_program = teleprompter.compile(YOUR_PROGRAM_HERE, trainset=YOUR_TRAINSET_HERE)
@@ -115,4 +129,4 @@ To load a program from a file, you can instantiate an object from that class and
115129
```python
116130
loaded_program = YOUR_PROGRAM_CLASS()
117131
loaded_program.load(path=YOUR_SAVE_PATH)
118-
```
132+
```
204 KB
Loading

dsp/modules/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .azure_openai import AzureOpenAI
88
from .cache_utils import *
99
from .clarifai import *
10+
from .cloudflare import *
1011
from .cohere import *
1112
from .colbertv2 import ColBERTv2
1213
from .databricks import *
@@ -22,4 +23,6 @@
2223
from .pyserini import *
2324
from .sbert import *
2425
from .sentence_vectorizer import *
26+
from .snowflake import *
2527
from .watsonx import *
28+

dsp/modules/anthropic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def __init__(
6262
}
6363
self.kwargs["model"] = model
6464
self.history: list[dict[str, Any]] = []
65-
self.client = Anthropic(api_key=api_key)
65+
self.client = Anthropic(api_key=api_key, base_url=api_base)
6666

6767
def log_usage(self, response):
6868
"""Log the total tokens from the Anthropic API response."""

dsp/modules/aws_providers.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,31 @@
33
from abc import ABC, abstractmethod
44
from typing import Any, Optional
55

6+
import backoff
7+
8+
try:
9+
import boto3
10+
from botocore.exceptions import ClientError
11+
ERRORS = (ClientError,)
12+
13+
except ImportError:
14+
ERRORS = (Exception,)
15+
16+
17+
def backoff_hdlr(details):
18+
"""Handler from https://pypi.org/project/backoff/."""
19+
print(
20+
"Backing off {wait:0.1f} seconds after {tries} tries "
21+
"calling function {target} with kwargs "
22+
"{kwargs}".format(**details),
23+
)
24+
25+
26+
def giveup_hdlr(details):
27+
"""Wrapper function that decides when to give up on retry."""
28+
if "max retries" in details.args[0]:
29+
return False
30+
return True
631

732
class AWSProvider(ABC):
833
"""This abstract class adds support for AWS model providers such as Bedrock and SageMaker.
@@ -52,6 +77,14 @@ def get_provider_name(self) -> str:
5277
return self.__class__.__name__
5378

5479
@abstractmethod
80+
@backoff.on_exception(
81+
backoff.expo,
82+
ERRORS,
83+
max_time=1000,
84+
max_tries=8,
85+
on_backoff=backoff_hdlr,
86+
giveup=giveup_hdlr,
87+
)
5588
def call_model(self, model_id: str, body: str) -> str:
5689
"""Call the model and return the response."""
5790

@@ -119,6 +152,14 @@ def __init__(
119152
"""
120153
super().__init__(region_name, "runtime.sagemaker", profile_name)
121154

155+
@backoff.on_exception(
156+
backoff.expo,
157+
ERRORS,
158+
max_time=1000,
159+
max_tries=8,
160+
on_backoff=backoff_hdlr,
161+
giveup=giveup_hdlr,
162+
)
122163
def call_model(self, model_id: str, body: str) -> str:
123164
return self.predictor.invoke_endpoint(
124165
EndpointName=model_id,

0 commit comments

Comments
 (0)