Skip to content

Commit

Permalink
Merge pull request #24 from aelaguiz/input_fields
Browse files Browse the repository at this point in the history
New input fields
  • Loading branch information
aelaguiz authored Mar 25, 2024
2 parents 25450ff + 1fbbd75 commit ad3a5e1
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 3 deletions.
2 changes: 1 addition & 1 deletion langdspy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .field_descriptors import InputField, OutputField, InputFieldList, HintField, OutputFieldEnum, OutputFieldEnumList, OutputFieldBool, OutputFieldChooseOne
from .field_descriptors import InputField, OutputField, InputFieldList, HintField, OutputFieldEnum, OutputFieldEnumList, OutputFieldBool, OutputFieldChooseOne, InputFieldDict, InputFieldDictList
from .prompt_strategies import PromptSignature, PromptStrategy, DefaultPromptStrategy
from .prompt_runners import PromptRunner, RunnableConfig, Prediction, MultiPromptRunner
from .model import Model, TrainedModelState
Expand Down
46 changes: 46 additions & 0 deletions langdspy/field_descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,52 @@ def format_prompt_value(self, value, llm_type: str):
res += f"{self._start_format_anthropic()}NO VALUES SPECIFIED</{self.name}>"
return res

class InputFieldDict(InputField):
def format_prompt_value(self, value, llm_type: str):
if llm_type == "openai":
return self._format_openai_prompt_value(value)
elif llm_type == "anthropic":
return self._format_anthropic_prompt_value(value)

def _format_openai_prompt_value(self, value):
formatted_dict = ""
for key, val in value.items():
formatted_dict += f"{self._start_format_openai()} {key}: {val}\n"
return formatted_dict.strip()

def _format_anthropic_prompt_value(self, value):
formatted_dict = f"<{self.name}>\n"
for key, val in value.items():
formatted_dict += f" <{key}>{val}</{key}>\n"
formatted_dict += f"</{self.name}>"
return formatted_dict

class InputFieldDictList(InputField):
def format_prompt_value(self, value, llm_type: str):
if llm_type == "openai":
return self._format_openai_prompt_value(value)
elif llm_type == "anthropic":
return self._format_anthropic_prompt_value(value)

def _format_openai_prompt_value(self, value):
formatted_list = ""
for i, item in enumerate(value):
formatted_list += f"{self._start_format_openai()} Item {i+1}:\n"
for key, val in item.items():
formatted_list += f" {key}: {val}\n"
formatted_list += "\n"
return formatted_list.strip()

def _format_anthropic_prompt_value(self, value):
formatted_list = f"<{self.name}>\n"
for i, item in enumerate(value):
formatted_list += f" <{self.name} {i + 1}>\n"
for key, val in item.items():
formatted_list += f" <{key}>{val}</{key}>\n"
formatted_list += f" </{self.name} {i + 1}>\n"
formatted_list += f"</{self.name}>"
return formatted_list

class OutputField(FieldDescriptor):
START_TOKEN_OPENAI = "🔑"
START_TOKEN_ANTHROPIC = None
Expand Down
66 changes: 64 additions & 2 deletions tests/test_field_descriptors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from enum import Enum
from langdspy.field_descriptors import InputField, InputFieldList, OutputField, OutputFieldEnum, OutputFieldEnumList, OutputFieldBool, OutputFieldChooseOne
from langdspy.field_descriptors import InputField, InputFieldList, OutputField, OutputFieldEnum, OutputFieldEnumList, OutputFieldBool, OutputFieldChooseOne, InputFieldDict, InputFieldDictList

def test_input_field_initialization():
field = InputField("name", "description")
Expand Down Expand Up @@ -87,4 +87,66 @@ def test_output_field_choose_one_format_prompt_description():

field = OutputFieldChooseOne("name", "description", choices)
assert "One of: Option 1, Option 2, Option 3" in field.format_prompt_description("openai")
assert "One of: <choices>Option 1, Option 2, Option 3</choices>" in field.format_prompt_description("anthropic")
assert "One of: <choices>Option 1, Option 2, Option 3</choices>" in field.format_prompt_description("anthropic")

def test_format_prompt_value_openai():
field = InputFieldDict("input_dict", "A dictionary input")
input_dict = {
"name": "John Doe",
"age": 30,
"city": "New York"
}
expected_output = "✅input_dict name: John Doe\n✅input_dict age: 30\n✅input_dict city: New York"
print(field.format_prompt_value(input_dict, "openai"))
print(expected_output)
assert field.format_prompt_value(input_dict, "openai") == expected_output

def test_format_prompt_value_anthropic():
field = InputFieldDict("input_dict", "A dictionary input")
input_dict = {
"name": "John Doe",
"age": 30,
"city": "New York"
}
expected_output = "<input_dict>\n <name>John Doe</name>\n <age>30</age>\n <city>New York</city>\n</input_dict>"
assert field.format_prompt_value(input_dict, "anthropic") == expected_output

# tests/test_input_field_dict_list.py
import pytest
from langdspy.field_descriptors import InputFieldDictList

def test_format_prompt_value_openai():
field = InputFieldDictList("input_list", "A list of dictionaries")
input_list = [
{
"name": "John Doe",
"age": 30,
"city": "New York"
},
{
"name": "Jane Smith",
"age": 25,
"city": "London"
}
]
expected_output = "✅input_list Item 1:\n name: John Doe\n age: 30\n city: New York\n\n✅input_list Item 2:\n name: Jane Smith\n age: 25\n city: London"
print(field.format_prompt_value(input_list, "openai"))
print(expected_output)
assert field.format_prompt_value(input_list, "openai") == expected_output

def test_format_prompt_value_anthropic():
field = InputFieldDictList("input_list", "A list of dictionaries")
input_list = [
{
"name": "John Doe",
"age": 30,
"city": "New York"
},
{
"name": "Jane Smith",
"age": 25,
"city": "London"
}
]
expected_output = "<input_list>\n <input_list 1>\n <name>John Doe</name>\n <age>30</age>\n <city>New York</city>\n </input_list 1>\n <input_list 2>\n <name>Jane Smith</name>\n <age>25</age>\n <city>London</city>\n </input_list 2>\n</input_list>"
assert field.format_prompt_value(input_list, "anthropic") == expected_output

0 comments on commit ad3a5e1

Please sign in to comment.