mirror of
https://github.com/hwchase17/langchain.git
synced 2026-02-04 16:20:16 +00:00
Compare commits
1 Commits
mdrxy/lang
...
vwp/test_o
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b81fb57a0e |
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@@ -27,8 +27,15 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: "poetry"
|
||||
- name: Install dependencies
|
||||
run: poetry install
|
||||
- name: Build wheel
|
||||
run: poetry build
|
||||
- name: Create virtual environment and install wheel
|
||||
run: |
|
||||
python -m venv .ci_venv
|
||||
. .ci_venv/bin/activate
|
||||
whl_file=$(find dist -name "*.whl" | head -n 1)
|
||||
pip install "${whl_file}[ci-testing]"
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
make test
|
||||
. .ci_venv/bin/activate
|
||||
pytest tests/unit_tests
|
||||
|
||||
@@ -74,6 +74,17 @@ azure-cosmos = {version="^4.4.0b1", optional=true}
|
||||
lark = {version="^1.1.5", optional=true}
|
||||
lancedb = {version = "^0.1", optional = true}
|
||||
pexpect = {version = "^4.8.0", optional = true}
|
||||
# Used for CI testing
|
||||
pytest = {version = "^7.3.0", optional = true}
|
||||
pytest-cov = {version = "^4.0.0", optional = true}
|
||||
pytest-dotenv = {version = "^0.5.2", optional = true}
|
||||
duckdb-engine = {version = "^0.7.0", optional = true}
|
||||
pytest-watcher = {version = "^0.2.6", optional = true}
|
||||
freezegun = {version = "^1.2.2", optional = true}
|
||||
responses = {version = "^0.22.0", optional = true}
|
||||
pytest-asyncio = {version = "^0.20.3", optional = true}
|
||||
|
||||
|
||||
|
||||
[tool.poetry.group.docs.dependencies]
|
||||
autodoc_pydantic = "^1.8.0"
|
||||
@@ -152,6 +163,7 @@ cohere = ["cohere"]
|
||||
embeddings = ["sentence-transformers"]
|
||||
azure = ["azure-identity", "azure-cosmos", "openai", "azure-core"]
|
||||
all = ["anthropic", "cohere", "openai", "nlpcloud", "huggingface_hub", "jina", "manifest-ml", "elasticsearch", "opensearch-py", "google-search-results", "faiss-cpu", "sentence-transformers", "transformers", "spacy", "nltk", "wikipedia", "beautifulsoup4", "tiktoken", "torch", "jinja2", "pinecone-client", "pinecone-text", "weaviate-client", "redis", "google-api-python-client", "wolframalpha", "qdrant-client", "tensorflow-text", "pypdf", "networkx", "nomic", "aleph-alpha-client", "deeplake", "pgvector", "psycopg2-binary", "boto3", "pyowm", "pytesseract", "html2text", "atlassian-python-api", "gptcache", "duckduckgo-search", "arxiv", "azure-identity", "clickhouse-connect", "azure-cosmos", "lancedb", "lark", "pexpect"]
|
||||
ci-testing = ["pytest", "pytest-cov", "pytest-dotenv", "duckdb-engine", "pytest-watcher", "freezegun", "responses", "pytest-asyncio", "pandas"]
|
||||
|
||||
[tool.ruff]
|
||||
select = [
|
||||
|
||||
38
tests/integration_tests/chains/test_bash.py
Normal file
38
tests/integration_tests/chains/test_bash.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""Test the bash utility."""
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from langchain.utilities.bash import BashProcess
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform.startswith("win"), reason="Test not supported on Windows"
|
||||
)
|
||||
def test_pwd_command_persistent() -> None:
|
||||
"""Test correct functionality when the bash process is persistent."""
|
||||
session = BashProcess(persistent=True, strip_newlines=True)
|
||||
commands = ["pwd"]
|
||||
output = session.run(commands)
|
||||
|
||||
assert subprocess.check_output("pwd", shell=True).decode().strip() in output
|
||||
|
||||
session.run(["cd .."])
|
||||
new_output = session.run(["pwd"])
|
||||
# Assert that the new_output is a parent of the old output
|
||||
assert Path(output).parent == Path(new_output)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform.startswith("win"), reason="Test not supported on Windows"
|
||||
)
|
||||
def test_create_bash_persistent() -> None:
|
||||
"""Test the pexpect persistent bash terminal"""
|
||||
session = BashProcess(persistent=True)
|
||||
response = session.run("echo hello")
|
||||
response += session.run("echo world")
|
||||
|
||||
assert "hello" in response
|
||||
assert "world" in response
|
||||
171
tests/integration_tests/prompts/test_jinja2.py
Normal file
171
tests/integration_tests/prompts/test_jinja2.py
Normal file
@@ -0,0 +1,171 @@
|
||||
"""Test functionality related to prompts."""
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
import pytest
|
||||
|
||||
from langchain.prompts.few_shot import FewShotPromptTemplate
|
||||
from langchain.prompts.prompt import PromptTemplate
|
||||
|
||||
|
||||
def test_prompt_from_jinja2_template() -> None:
|
||||
"""Test prompts can be constructed from a jinja2 template."""
|
||||
# Empty input variable.
|
||||
template = """Hello there
|
||||
There is no variable here {
|
||||
Will it get confused{ }?
|
||||
"""
|
||||
prompt = PromptTemplate.from_template(template, template_format="jinja2")
|
||||
expected_prompt = PromptTemplate(
|
||||
template=template, input_variables=[], template_format="jinja2"
|
||||
)
|
||||
assert prompt == expected_prompt
|
||||
|
||||
# Multiple input variables.
|
||||
template = """\
|
||||
Hello world
|
||||
|
||||
Your variable: {{ foo }}
|
||||
|
||||
{# This will not get rendered #}
|
||||
|
||||
{% if bar %}
|
||||
You just set bar boolean variable to true
|
||||
{% endif %}
|
||||
|
||||
{% for i in foo_list %}
|
||||
{{ i }}
|
||||
{% endfor %}
|
||||
"""
|
||||
prompt = PromptTemplate.from_template(template, template_format="jinja2")
|
||||
expected_prompt = PromptTemplate(
|
||||
template=template,
|
||||
input_variables=["bar", "foo", "foo_list"],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
assert prompt == expected_prompt
|
||||
|
||||
# Multiple input variables with repeats.
|
||||
template = """\
|
||||
Hello world
|
||||
|
||||
Your variable: {{ foo }}
|
||||
|
||||
{# This will not get rendered #}
|
||||
|
||||
{% if bar %}
|
||||
You just set bar boolean variable to true
|
||||
{% endif %}
|
||||
|
||||
{% for i in foo_list %}
|
||||
{{ i }}
|
||||
{% endfor %}
|
||||
|
||||
{% if bar %}
|
||||
Your variable again: {{ foo }}
|
||||
{% endif %}
|
||||
"""
|
||||
prompt = PromptTemplate.from_template(template, template_format="jinja2")
|
||||
expected_prompt = PromptTemplate(
|
||||
template=template,
|
||||
input_variables=["bar", "foo", "foo_list"],
|
||||
template_format="jinja2",
|
||||
)
|
||||
assert prompt == expected_prompt
|
||||
|
||||
|
||||
def test_prompt_jinja2_wrong_input_variables() -> None:
|
||||
"""Test error is raised when name of input variable is wrong."""
|
||||
template = "This is a {{ foo }} test."
|
||||
input_variables = ["bar"]
|
||||
with pytest.raises(ValueError):
|
||||
PromptTemplate(
|
||||
input_variables=input_variables, template=template, template_format="jinja2"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def example_jinja2_prompt() -> Tuple[PromptTemplate, List[Dict[str, str]]]:
|
||||
example_template = "{{ word }}: {{ antonym }}"
|
||||
|
||||
examples = [
|
||||
{"word": "happy", "antonym": "sad"},
|
||||
{"word": "tall", "antonym": "short"},
|
||||
]
|
||||
|
||||
return (
|
||||
PromptTemplate(
|
||||
input_variables=["word", "antonym"],
|
||||
template=example_template,
|
||||
template_format="jinja2",
|
||||
),
|
||||
examples,
|
||||
)
|
||||
|
||||
|
||||
def test_prompt_jinja2_missing_input_variables(
|
||||
example_jinja2_prompt: Tuple[PromptTemplate, List[Dict[str, str]]]
|
||||
) -> None:
|
||||
"""Test error is raised when input variables are not provided."""
|
||||
prefix = "Starting with {{ foo }}"
|
||||
suffix = "Ending with {{ bar }}"
|
||||
|
||||
# Test when missing in suffix
|
||||
with pytest.raises(ValueError):
|
||||
FewShotPromptTemplate(
|
||||
input_variables=[],
|
||||
suffix=suffix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
# Test when missing in prefix
|
||||
with pytest.raises(ValueError):
|
||||
FewShotPromptTemplate(
|
||||
input_variables=["bar"],
|
||||
suffix=suffix,
|
||||
prefix=prefix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
|
||||
def test_prompt_jinja2_extra_input_variables(
|
||||
example_jinja2_prompt: Tuple[PromptTemplate, List[Dict[str, str]]]
|
||||
) -> None:
|
||||
"""Test error is raised when there are too many input variables."""
|
||||
prefix = "Starting with {{ foo }}"
|
||||
suffix = "Ending with {{ bar }}"
|
||||
with pytest.raises(ValueError):
|
||||
FewShotPromptTemplate(
|
||||
input_variables=["bar", "foo", "extra", "thing"],
|
||||
suffix=suffix,
|
||||
prefix=prefix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
|
||||
def test_prompt_jinja2_functionality(
|
||||
example_jinja2_prompt: Tuple[PromptTemplate, List[Dict[str, str]]]
|
||||
) -> None:
|
||||
prefix = "Starting with {{ foo }}"
|
||||
suffix = "Ending with {{ bar }}"
|
||||
|
||||
prompt = FewShotPromptTemplate(
|
||||
input_variables=["foo", "bar"],
|
||||
suffix=suffix,
|
||||
prefix=prefix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
output = prompt.format(foo="hello", bar="bye")
|
||||
expected_output = (
|
||||
"Starting with hello\n\n" "happy: sad\n\n" "tall: short\n\n" "Ending with bye"
|
||||
)
|
||||
|
||||
assert output == expected_output
|
||||
@@ -1,5 +1,4 @@
|
||||
"""Test few shot prompt template."""
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -11,25 +10,6 @@ EXAMPLE_PROMPT = PromptTemplate(
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def example_jinja2_prompt() -> Tuple[PromptTemplate, List[Dict[str, str]]]:
|
||||
example_template = "{{ word }}: {{ antonym }}"
|
||||
|
||||
examples = [
|
||||
{"word": "happy", "antonym": "sad"},
|
||||
{"word": "tall", "antonym": "short"},
|
||||
]
|
||||
|
||||
return (
|
||||
PromptTemplate(
|
||||
input_variables=["word", "antonym"],
|
||||
template=example_template,
|
||||
template_format="jinja2",
|
||||
),
|
||||
examples,
|
||||
)
|
||||
|
||||
|
||||
def test_suffix_only() -> None:
|
||||
"""Test prompt works with just a suffix."""
|
||||
suffix = "This is a {foo} test."
|
||||
@@ -195,71 +175,3 @@ def test_partial() -> None:
|
||||
"Now you try to talk about party."
|
||||
)
|
||||
assert output == expected_output
|
||||
|
||||
|
||||
def test_prompt_jinja2_functionality(
|
||||
example_jinja2_prompt: Tuple[PromptTemplate, List[Dict[str, str]]]
|
||||
) -> None:
|
||||
prefix = "Starting with {{ foo }}"
|
||||
suffix = "Ending with {{ bar }}"
|
||||
|
||||
prompt = FewShotPromptTemplate(
|
||||
input_variables=["foo", "bar"],
|
||||
suffix=suffix,
|
||||
prefix=prefix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
output = prompt.format(foo="hello", bar="bye")
|
||||
expected_output = (
|
||||
"Starting with hello\n\n" "happy: sad\n\n" "tall: short\n\n" "Ending with bye"
|
||||
)
|
||||
|
||||
assert output == expected_output
|
||||
|
||||
|
||||
def test_prompt_jinja2_missing_input_variables(
|
||||
example_jinja2_prompt: Tuple[PromptTemplate, List[Dict[str, str]]]
|
||||
) -> None:
|
||||
"""Test error is raised when input variables are not provided."""
|
||||
prefix = "Starting with {{ foo }}"
|
||||
suffix = "Ending with {{ bar }}"
|
||||
|
||||
# Test when missing in suffix
|
||||
with pytest.raises(ValueError):
|
||||
FewShotPromptTemplate(
|
||||
input_variables=[],
|
||||
suffix=suffix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
# Test when missing in prefix
|
||||
with pytest.raises(ValueError):
|
||||
FewShotPromptTemplate(
|
||||
input_variables=["bar"],
|
||||
suffix=suffix,
|
||||
prefix=prefix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
|
||||
def test_prompt_jinja2_extra_input_variables(
|
||||
example_jinja2_prompt: Tuple[PromptTemplate, List[Dict[str, str]]]
|
||||
) -> None:
|
||||
"""Test error is raised when there are too many input variables."""
|
||||
prefix = "Starting with {{ foo }}"
|
||||
suffix = "Ending with {{ bar }}"
|
||||
with pytest.raises(ValueError):
|
||||
FewShotPromptTemplate(
|
||||
input_variables=["bar", "foo", "extra", "thing"],
|
||||
suffix=suffix,
|
||||
prefix=prefix,
|
||||
examples=example_jinja2_prompt[1],
|
||||
example_prompt=example_jinja2_prompt[0],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
@@ -145,100 +145,3 @@ def test_partial() -> None:
|
||||
assert new_result == "This is a 3 test."
|
||||
result = prompt.format(foo="foo")
|
||||
assert result == "This is a foo test."
|
||||
|
||||
|
||||
def test_prompt_from_jinja2_template() -> None:
|
||||
"""Test prompts can be constructed from a jinja2 template."""
|
||||
# Empty input variable.
|
||||
template = """Hello there
|
||||
There is no variable here {
|
||||
Will it get confused{ }?
|
||||
"""
|
||||
prompt = PromptTemplate.from_template(template, template_format="jinja2")
|
||||
expected_prompt = PromptTemplate(
|
||||
template=template, input_variables=[], template_format="jinja2"
|
||||
)
|
||||
assert prompt == expected_prompt
|
||||
|
||||
# Multiple input variables.
|
||||
template = """\
|
||||
Hello world
|
||||
|
||||
Your variable: {{ foo }}
|
||||
|
||||
{# This will not get rendered #}
|
||||
|
||||
{% if bar %}
|
||||
You just set bar boolean variable to true
|
||||
{% endif %}
|
||||
|
||||
{% for i in foo_list %}
|
||||
{{ i }}
|
||||
{% endfor %}
|
||||
"""
|
||||
prompt = PromptTemplate.from_template(template, template_format="jinja2")
|
||||
expected_prompt = PromptTemplate(
|
||||
template=template,
|
||||
input_variables=["bar", "foo", "foo_list"],
|
||||
template_format="jinja2",
|
||||
)
|
||||
|
||||
assert prompt == expected_prompt
|
||||
|
||||
# Multiple input variables with repeats.
|
||||
template = """\
|
||||
Hello world
|
||||
|
||||
Your variable: {{ foo }}
|
||||
|
||||
{# This will not get rendered #}
|
||||
|
||||
{% if bar %}
|
||||
You just set bar boolean variable to true
|
||||
{% endif %}
|
||||
|
||||
{% for i in foo_list %}
|
||||
{{ i }}
|
||||
{% endfor %}
|
||||
|
||||
{% if bar %}
|
||||
Your variable again: {{ foo }}
|
||||
{% endif %}
|
||||
"""
|
||||
prompt = PromptTemplate.from_template(template, template_format="jinja2")
|
||||
expected_prompt = PromptTemplate(
|
||||
template=template,
|
||||
input_variables=["bar", "foo", "foo_list"],
|
||||
template_format="jinja2",
|
||||
)
|
||||
assert prompt == expected_prompt
|
||||
|
||||
|
||||
def test_prompt_jinja2_missing_input_variables() -> None:
|
||||
"""Test error is raised when input variables are not provided."""
|
||||
template = "This is a {{ foo }} test."
|
||||
input_variables: list = []
|
||||
with pytest.raises(ValueError):
|
||||
PromptTemplate(
|
||||
input_variables=input_variables, template=template, template_format="jinja2"
|
||||
)
|
||||
|
||||
|
||||
def test_prompt_jinja2_extra_input_variables() -> None:
|
||||
"""Test error is raised when there are too many input variables."""
|
||||
template = "This is a {{ foo }} test."
|
||||
input_variables = ["foo", "bar"]
|
||||
with pytest.raises(ValueError):
|
||||
PromptTemplate(
|
||||
input_variables=input_variables, template=template, template_format="jinja2"
|
||||
)
|
||||
|
||||
|
||||
def test_prompt_jinja2_wrong_input_variables() -> None:
|
||||
"""Test error is raised when name of input variable is wrong."""
|
||||
template = "This is a {{ foo }} test."
|
||||
input_variables = ["bar"]
|
||||
with pytest.raises(ValueError):
|
||||
PromptTemplate(
|
||||
input_variables=input_variables, template=template, template_format="jinja2"
|
||||
)
|
||||
|
||||
@@ -21,23 +21,6 @@ def test_pwd_command() -> None:
|
||||
assert output == subprocess.check_output("pwd", shell=True).decode()
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform.startswith("win"), reason="Test not supported on Windows"
|
||||
)
|
||||
def test_pwd_command_persistent() -> None:
|
||||
"""Test correct functionality when the bash process is persistent."""
|
||||
session = BashProcess(persistent=True, strip_newlines=True)
|
||||
commands = ["pwd"]
|
||||
output = session.run(commands)
|
||||
|
||||
assert subprocess.check_output("pwd", shell=True).decode().strip() in output
|
||||
|
||||
session.run(["cd .."])
|
||||
new_output = session.run(["pwd"])
|
||||
# Assert that the new_output is a parent of the old output
|
||||
assert Path(output).parent == Path(new_output)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform.startswith("win"), reason="Test not supported on Windows"
|
||||
)
|
||||
@@ -83,16 +66,3 @@ def test_create_directory_and_files(tmp_path: Path) -> None:
|
||||
# check that the files were created in the temporary directory
|
||||
output = session.run([f"ls {temp_dir}"])
|
||||
assert output == "file1.txt\nfile2.txt"
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform.startswith("win"), reason="Test not supported on Windows"
|
||||
)
|
||||
def test_create_bash_persistent() -> None:
|
||||
"""Test the pexpect persistent bash terminal"""
|
||||
session = BashProcess(persistent=True)
|
||||
response = session.run("echo hello")
|
||||
response += session.run("echo world")
|
||||
|
||||
assert "hello" in response
|
||||
assert "world" in response
|
||||
|
||||
Reference in New Issue
Block a user