Skip to content

Commit 1a56e69

Browse files
authored
Merge pull request #735 from stanfordnlp/DummyLM-patch
[Phoenix Patch] Move DummyLM to dsp/modules
2 parents ade853a + 9c079fd commit 1a56e69

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

dsp/modules/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .cohere import *
1111
from .colbertv2 import ColBERTv2
1212
from .databricks import *
13+
from .dummy_lm import *
1314
from .google import *
1415
from .googlevertexai import *
1516
from .gpt3 import *

dsp/modules/dummy_lm.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import re
2+
from typing import Union
3+
4+
from dsp.modules import LM
5+
6+
7+
# This testing module was moved in PR #735 to patch Arize Phoenix logging
8+
class DummyLM(LM):
9+
"""Dummy language model for unit testing purposes."""
10+
11+
def __init__(self, answers: Union[list[str], dict[str, str]], follow_examples: bool = False):
12+
"""Initializes the dummy language model.
13+
14+
Parameters:
15+
- answers: A list of strings or a dictionary with string keys and values.
16+
- follow_examples: If True, and the prompt contains an example exactly equal to the prompt,
17+
the dummy model will return the next string in the list for each request.
18+
If a list is provided, the dummy model will return the next string in the list for each request.
19+
If a dictionary is provided, the dummy model will return the value corresponding to the key that matches the prompt.
20+
"""
21+
super().__init__("dummy-model")
22+
self.provider = "dummy"
23+
self.answers = answers
24+
self.follow_examples = follow_examples
25+
26+
def basic_request(self, prompt, n=1, **kwargs) -> dict[str, list[dict[str, str]]]:
27+
"""Generates a dummy response based on the prompt."""
28+
dummy_response = {"choices": []}
29+
for _ in range(n):
30+
answer = None
31+
32+
if self.follow_examples:
33+
prefix = prompt.split("\n")[-1]
34+
_instructions, _format, *examples, _output = prompt.split("\n---\n")
35+
examples_str = "\n".join(examples)
36+
possible_answers = re.findall(prefix + r"\s*(.*)", examples_str)
37+
if possible_answers:
38+
# We take the last answer, as the first one is just from
39+
# the "Follow the following format" section.
40+
answer = possible_answers[-1]
41+
print(f"DummyLM got found previous example for {prefix} with value {answer=}")
42+
else:
43+
print(f"DummyLM couldn't find previous example for {prefix=}")
44+
45+
if answer is None:
46+
if isinstance(self.answers, dict):
47+
answer = next((v for k, v in self.answers.items() if k in prompt), None)
48+
else:
49+
if len(self.answers) > 0:
50+
answer = self.answers[0]
51+
self.answers = self.answers[1:]
52+
53+
if answer is None:
54+
answer = "No more responses"
55+
56+
# Mimic the structure of a real language model response.
57+
dummy_response["choices"].append(
58+
{
59+
"text": answer,
60+
"finish_reason": "simulated completion",
61+
},
62+
)
63+
64+
RED, GREEN, RESET = "\033[91m", "\033[92m", "\033[0m"
65+
print("=== DummyLM ===")
66+
print(prompt, end="")
67+
print(f"{RED}{answer}{RESET}")
68+
print("===")
69+
70+
# Simulate processing and storing the request and response.
71+
history_entry = {
72+
"prompt": prompt,
73+
"response": dummy_response,
74+
"kwargs": kwargs,
75+
"raw_kwargs": kwargs,
76+
}
77+
self.history.append(history_entry)
78+
79+
return dummy_response
80+
81+
def __call__(self, prompt, _only_completed=True, _return_sorted=False, **kwargs):
82+
"""Retrieves dummy completions."""
83+
response = self.basic_request(prompt, **kwargs)
84+
choices = response["choices"]
85+
86+
# Filter choices and return text completions.
87+
return [choice["text"] for choice in choices]
88+
89+
def get_convo(self, index) -> str:
90+
"""Get the prompt + anwer from the ith message."""
91+
return self.history[index]["prompt"] + " " + self.history[index]["response"]["choices"][0]["text"]

0 commit comments

Comments
 (0)