diff --git a/.env.example b/.env.example index 97d390b..a336758 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,14 @@ -OPENAI_API_KEY=your-open-api-secret-key -USER_AGENT=Langrade/1.0 +# OpenAI Configuration +OPENAI_API_KEY=your-api-secret-key +OPENAI_MODEL=gpt-3.5-turbo-0125 + +# Google (Gemini) Configuration +GOOGLE_API_KEY=your-api-secret-key +GEMINI_MODEL=gemini-1.5-pro-latest + +# Anthropic (Claude) Configuration +ANTHROPIC_API_KEY=your-api-secret-key +CLAUDE_MODEL=claude-3-sonnet-20240229 + +# Default Engine Configuration +DEFAULT_ENGINE_TYPE=openai diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..9d9dc72 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,20 @@ +name: Publish docs via GitHub Pages +on: + push: + branches: + - main + +jobs: + build: + name: Deploy docs + runs-on: ubuntu-latest + steps: + - name: Checkout main + uses: actions/checkout@v2 + + - name: Deploy docs + uses: mhausenblas/mkdocs-deploy-gh-pages@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CONFIG_FILE: mkdocs.yml + EXTRA_PACKAGES: build-base diff --git a/.gitignore b/.gitignore index 6656130..c470085 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ Thumbs.db # Other create_txt.py file_structure_and_contents.txt +expeiments/ diff --git a/README.md b/README.md index 3faa9a3..a18c791 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # langrade -langrade is a Python library for grading and retrieving documents based on their relevance to a given question. +langrade is a Python library for grading and retrieving documents based on their relevance to a given question. It supports multiple LLM providers including OpenAI, Anthropic (Claude), and Google (Gemini). ## Installation @@ -41,11 +41,9 @@ print(f"Reasoning: {result.reasoning}") ## Features -Document retrieval from web URLs - -Document grading based on relevance to a question - -Optional reasoning for grading decisions +- Document retrieval from web URLs +- Document grading based on relevance to a question +- Support for multiple LLM providers (OpenAI, Anthropic, Google) ## Requirements diff --git a/docs/advanced_usage.md b/docs/advanced_usage.md new file mode 100644 index 0000000..6e9c2f6 --- /dev/null +++ b/docs/advanced_usage.md @@ -0,0 +1,60 @@ +# Advanced Usage + +## Custom Prompts + +You can customize the system prompt used by the grader: + +```python +from langrade.constants import SYSTEM_PROMPT + +# Modify the SYSTEM_PROMPT constant +SYSTEM_PROMPT = """ +Your custom prompt here. +""" + +# Then create your grader as usual +grader = document_grader(provider, api_key, model) +``` + +## Batch Processing + +For grading multiple documents: + +```python +documents = ["doc1 content", "doc2 content", "doc3 content"] +question = "What is AI?" + +results = [] +for doc in documents: + result = grader.grade_document(doc, question) + results.append(result) + +for i, result in enumerate(results): + print(f"Document {i+1}:") + print(f"Relevance: {result.binary_score}") + print(f"Reasoning: {result.reasoning}") + print() +``` + +## Custom Retriever + +You can create a custom retriever by subclassing BaseRetriever: + +```python +from langchain.schema import BaseRetriever, Document + +class CustomRetriever(BaseRetriever): + def get_relevant_documents(self, query: str) -> List[Document]: + # Your custom retrieval logic here + pass + + async def aget_relevant_documents(self, query: str) -> List[Document]: + # Your custom async retrieval logic here + pass + +# Use your custom retriever +custom_retriever = CustomRetriever() +docs = custom_retriever.get_relevant_documents("What is AI?") +``` + +For more advanced usage scenarios, refer to the source code and consider extending the base classes provided by Langrade. diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..25131e8 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,63 @@ +# API Reference + +## document_grader + +```python +def document_grader(provider: str, api_key: str, model: str = DEFAULT_MODEL) -> DocumentGrader: + """ + Create a DocumentGrader instance. + + Args: + provider (str): The LLM provider ("openai", "anthropic", or "google"). + api_key (str): The API key for the chosen provider. + model (str, optional): The model to use. Defaults to DEFAULT_MODEL. + + Returns: + DocumentGrader: An instance of the DocumentGrader class. + """ +``` + +## DocumentGrader + +```python +class DocumentGrader: + def __init__(self, provider: str, api_key: str, model: str = DEFAULT_MODEL): + """ + Initialize a DocumentGrader instance. + + Args: + provider (str): The LLM provider. + api_key (str): The API key for the chosen provider. + model (str, optional): The model to use. Defaults to DEFAULT_MODEL. + """ + + def grade_document(self, document: str, question: str) -> GradeDocuments: + """ + Grade a document based on its relevance to a question. + + Args: + document (str): The document text to grade. + question (str): The question to grade the document against. + + Returns: + GradeDocuments: An object containing the grading result. + """ +``` + +## create_retriever + +```python +def create_retriever(urls: list[str], api_key: str) -> BaseRetriever: + """ + Create a retriever for fetching relevant documents. + + Args: + urls (list[str]): A list of URLs to fetch documents from. + api_key (str): The API key for the embedding model. + + Returns: + BaseRetriever: A retriever instance. + """ +``` + +For more details on the returned objects and their properties, see the source code documentation. diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..dc3785a --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,27 @@ +# Configuration + +# Provider-Specific Configuration + +## OpenAI + +```python +from langrade import document_grader + +grader = document_grader("openai", "your_openai_api_key", "gpt-3.5-turbo-0125") +``` + +## Anthropic + +```python +from langrade import document_grader + +grader = document_grader("anthropic", "your_anthropic_api_key", "claude-3-opus-20240229") +``` + +## Google + +```python +from langrade import document_grader + +grader = document_grader("google", "your_google_api_key", "gemini-1.5-pro-latest") +``` diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 0000000..537246c --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,63 @@ +# Contributing to Langrade + +We welcome contributions to Langrade! Here's how you can help: + +## Setting Up the Development Environment + +1. Fork the repository +2. Clone your fork: + +```bash +git clone https://github.com/yourusername/langrade.git +cd langrade +``` + +3. Set up a virtual environment: + +```bash +python -m venv venv +source venv/bin/activate # On Windows, use `venv\Scripts\activate` +``` + +4. Install dependencies: + +```bash +pip install -e ".[dev]" +``` + +## Running Tests + +Run tests using pytest: + +```bash +poetry run test +``` + +## Coding Standards + +We use Black for code formatting and flake8 for linting: + +```bash +black . +flake8 +``` + +## Submitting Changes + +Create a new branch: + +`git checkout -b your-branch-name` + +Make your changes and commit them: + +`git commit -m "Your detailed commit message"` + +Push to your fork: + +`git push origin your-branch-name` + +Submit a pull request + +Please ensure your code adheres to our coding standards and is well-documented. + +Thank you for contributing to Langrade! diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000..f346397 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,51 @@ +# Frequently Asked Questions + +## General + +### Q: What is Langrade? + +A: Langrade is a Python library for grading and retrieving documents based on their relevance to a given question. It supports multiple LLM providers including OpenAI, Anthropic (Claude), and Google (Gemini). + +### Q: Which Python versions are supported? + +A: Langrade supports Python 3.9 and above. + +## Usage + +### Q: How do I choose between different LLM providers? + +A: You can specify the provider when creating a `DocumentGrader`: + +```python +from langrade import document_grader + +# For OpenAI +grader_openai = document_grader("openai", "your_openai_api_key", "gpt-3.5-turbo-0125") + +# For Anthropic +grader_anthropic = document_grader("anthropic", "your_anthropic_api_key", "claude-3-opus-20240229") + +# For Google +grader_google = document_grader("google", "your_google_api_key", "gemini-1.0-pro") +``` + +### Q: Can I use my own custom models? + +A: Currently, Langrade supports the models provided by OpenAI, Anthropic, and Google. Custom model support may be added in future versions. + +## Troubleshooting + +### Q: I'm getting an "API key not found" error. What should I do? + +A: Ensure that you've set up your .env file correctly with the appropriate API keys. Also, make sure you're loading the environment variables in your code: + +```python +from dotenv import load_dotenv +load_dotenv() +``` + +### Q: How can I report a bug or request a feature? + +A: Please open an issue on our GitHub repository. Provide as much detail as possible, including your Python version and any error messages you're seeing. + +For more detailed information, please refer to our [documentation](https://langrade.readthedocs.io/). diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..d73e3b5 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,42 @@ +# Welcome to Langrade + +Langrade is a Python library for grading and retrieving documents based on their relevance to a given question. It supports multiple LLM providers including OpenAI, Anthropic (Claude), and Google (Gemini). + +## Quick Start + +```python +from langrade import document_grader, create_retriever + +provider = "openai" +api_key = "your_api_key_here" +model = "gpt-3.5-turbo-0125" + +grader = document_grader(provider, api_key, model) + +urls = [ + "https://example.com/article1", + "https://example.com/article2", +] +retriever = create_retriever(urls, api_key) + +question = "What is AI?" +docs = retriever.get_relevant_documents(question) +doc_txt = docs[0].page_content + +result = grader.grade_document(doc_txt, question) +print(f"Relevance: {result.binary_score}") +print(f"Reasoning: {result.reasoning}") +``` + +## Table of Contents + +- Installation +- Usage +- API Reference +- Configuration +- Providers +- Advanced Usage +- Troubleshooting +- Contributing +- Changelog +- FAQ diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..726b43a --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,24 @@ +# Installation + +## Requirements + +- Python 3.9+ +- API key for the chosen LLM provider (OpenAI, Anthropic, or Google) + +## Using pip + +Install Langrade using pip: + +```bash +pip install langrade +``` + +## From source + +To install Langrade from source: + +```bash +git clone https://github.com/nisaji/langrade.git +cd langrade +pip install . +``` diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..28561eb --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,39 @@ +# Troubleshooting + +## Model Not Found + +If you get a "model not found" error: + +Check that you're using a valid model name for the chosen provider. + +Ensure your API key has access to the specified model. + +```python +from langrade import document_grader + +try: + grader = document_grader("openai", "your_api_key", "invalid-model-name") +except Exception as e: + print(f"Error: {e}") +``` + +## Import Errors + +If you're having trouble importing Langrade: + +Ensure Langrade is installed: pip install langrade +Check your Python path: + +```python +import sys +print(sys.path) +``` + +## Debugging + +For detailed debugging, enable logging: + +```python +import logging +logging.basicConfig(level=logging.DEBUG) +``` diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..fb22271 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,39 @@ +# Basic Usage + +## Initializing the Grader + +```python +from langrade import document_grader + +provider = "openai" # or "anthropic" or "google" +api_key = "your_api_key_here" +model = "gpt-3.5-turbo-0125" # or appropriate model for the chosen provider + +grader = document_grader(provider, api_key, model) +``` + +## Create Retriever + +```python +from langrade import create_retriever + +urls = [ + "https://example.com/article1", + "https://example.com/article2", +] +retriever = create_retriever(urls, api_key) +``` + +## Retrieving and Grading Documents + +```python +question = "What is AI?" +docs = retriever.get_relevant_documents(question) +doc_txt = docs[0].page_content + +result = grader.grade_document(doc_txt, question) +print(f"Relevance: {result.binary_score}") +print(f"Reasoning: {result.reasoning}") +``` + +For more advanced usage, see the Advanced Usage guide. diff --git a/langrade/__init__.py b/langrade/__init__.py index 21fbe66..6712bb6 100644 --- a/langrade/__init__.py +++ b/langrade/__init__.py @@ -1,4 +1,10 @@ from .grader import document_grader, DocumentGrader from .retriever import create_retriever +from .providers import LLMProviderFactory -__all__ = ["document_grader", "DocumentGrader", "create_retriever"] +__all__ = [ + "document_grader", + "DocumentGrader", + "create_retriever", + "LLMProviderFactory", +] # noqa: E501 diff --git a/langrade/grader.py b/langrade/grader.py index 1ce40df..46e58f4 100644 --- a/langrade/grader.py +++ b/langrade/grader.py @@ -1,50 +1,20 @@ -from langchain_core.pydantic_v1 import BaseModel, Field -from langchain_core.prompts import ChatPromptTemplate -from langchain_openai import ChatOpenAI -from .constants import ( - SYSTEM_PROMPT, - DEFAULT_MODEL, - REASONING_DESCRIPTION, - BINARY_SCORE_DESCRIPTION, -) -import html - - -class GradeDocuments(BaseModel): - reasoning: str = Field(description=REASONING_DESCRIPTION) - binary_score: str = Field(description=BINARY_SCORE_DESCRIPTION) +from .providers import LLMProviderFactory, GradeDocuments +from .constants import DEFAULT_MODEL class DocumentGrader: - def __init__(self, api_key: str, model: str = DEFAULT_MODEL): - self.llm = ChatOpenAI(api_key=api_key, model=model) - self.prompt = self._create_prompt() - - def _create_prompt(self): - return ChatPromptTemplate.from_messages( - [ - ("system", SYSTEM_PROMPT), - ( - "human", - "Retrieved document: \n\n {document} \n\n User question: \n\n {question}", # noqa: E501 - ), - ] - ) - - def grade_document(self, document: str, question: str): - # Sanitize inputs - safe_document = html.escape(document) - safe_question = html.escape(question) - - structured_llm = self.llm.with_structured_output(GradeDocuments) - chain = self.prompt | structured_llm - result = chain.invoke( - {"document": safe_document, "question": safe_question} + def __init__( + self, provider: str, api_key: str, model: str = DEFAULT_MODEL + ): # noqa: E501 + self.provider = LLMProviderFactory.create_provider( + provider, api_key, model ) # noqa: E501 - return result + + def grade_document(self, document: str, question: str) -> GradeDocuments: + return self.provider.grade_document(document, question) def document_grader( - api_key: str, model: str = DEFAULT_MODEL -) -> DocumentGrader: # noqa: E501 - return DocumentGrader(api_key, model) + provider: str, api_key: str, model: str = DEFAULT_MODEL +) -> DocumentGrader: + return DocumentGrader(provider, api_key, model) diff --git a/langrade/providers.py b/langrade/providers.py new file mode 100644 index 0000000..e2c38ca --- /dev/null +++ b/langrade/providers.py @@ -0,0 +1,75 @@ +from abc import ABC, abstractmethod +from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr +from langchain_core.prompts import ChatPromptTemplate +from langchain_openai import ChatOpenAI +from langchain_anthropic import ChatAnthropic +from langchain_google_genai import ChatGoogleGenerativeAI +from .constants import ( + SYSTEM_PROMPT, + DEFAULT_MODEL, + REASONING_DESCRIPTION, + BINARY_SCORE_DESCRIPTION, +) + + +class GradeDocuments(BaseModel): + reasoning: str = Field(description=REASONING_DESCRIPTION) + binary_score: str = Field(description=BINARY_SCORE_DESCRIPTION) + + +class LLMProvider(ABC): + def __init__(self, api_key: str, model: str): + self.llm = self._create_llm(api_key, model) + self.prompt = self._create_prompt() + + @abstractmethod + def _create_llm(self, api_key: str, model: str): + pass + + def _create_prompt(self): + return ChatPromptTemplate.from_messages( + [ + ("system", SYSTEM_PROMPT), + ( + "human", + "Retrieved document: \n\n {document} \n\n User question: \n\n {question}", # noqa: E501 + ), + ] + ) + + def grade_document(self, document: str, question: str) -> GradeDocuments: + structured_llm = self.llm.with_structured_output(GradeDocuments) + chain = self.prompt | structured_llm + return chain.invoke({"document": document, "question": question}) + + +class OpenAIProvider(LLMProvider): + def _create_llm(self, api_key: str, model: str): + return ChatOpenAI(api_key=api_key, model=model) + + +class AnthropicProvider(LLMProvider): + def _create_llm(self, api_key: str, model: str): + return ChatAnthropic(api_key=api_key, model_name=model) + + +class GoogleProvider(LLMProvider): + def _create_llm(self, api_key: str, model: str): + return ChatGoogleGenerativeAI( + google_api_key=SecretStr(api_key), model=model + ) # noqa: E501 + + +class LLMProviderFactory: + @staticmethod + def create_provider( + provider: str, api_key: str, model: str = DEFAULT_MODEL + ) -> LLMProvider: + if provider == "openai": + return OpenAIProvider(api_key, model) + elif provider == "anthropic": + return AnthropicProvider(api_key, model) + elif provider == "google": + return GoogleProvider(api_key, model) + else: + raise ValueError(f"Unsupported provider: {provider}") diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..777b82c --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,14 @@ +site_name: Langrade Documentation +theme: readthedocs + +nav: + - Home: index.md + - Installation: installation.md + - Usage: usage.md + - API Reference: api.md + - Configuration: configuration.md + - Advanced Usage: advanced_usage.md + - Troubleshooting: troubleshooting.md + - Contributing: contributing.md + - Changelog: changelog.md + - FAQ: faq.md diff --git a/poetry.lock b/poetry.lock index a51f746..10ea1c6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -123,23 +123,28 @@ files = [ [[package]] name = "anthropic" -version = "0.2.8" -description = "Library for accessing the anthropic API" +version = "0.31.1" +description = "The official Python library for the anthropic API" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "anthropic-0.2.8-py3-none-any.whl", hash = "sha256:7a11da8a3d8cb52835912e73d42e9245e7949155f4afb7093496f100a9bf610b"}, - {file = "anthropic-0.2.8.tar.gz", hash = "sha256:d2629d7e26415bcce2ed0fdff0096a3fdd861099a73a1351ee705511d1c2ea6e"}, + {file = "anthropic-0.31.1-py3-none-any.whl", hash = "sha256:d18809cbdecee2296f418e30beb2d0a8ecc225c065a1494cb02348af48794ff8"}, + {file = "anthropic-0.31.1.tar.gz", hash = "sha256:d2248dfc15f7fc7823ac0bb9d48e73429e9b1ed8327ac66839d00cdb2f29d3cb"}, ] [package.dependencies] -aiohttp = "*" -httpx = "*" -requests = "*" -tokenizers = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +jiter = ">=0.4.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tokenizers = ">=0.13.0" +typing-extensions = ">=4.7,<5" [package.extras] -dev = ["black (>=22.3.0)", "pytest"] +bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +vertex = ["google-auth (>=2,<3)"] [[package]] name = "anyio" @@ -319,13 +324,13 @@ virtualenv = ["virtualenv (>=20.0.35)"] [[package]] name = "cachetools" -version = "5.3.3" +version = "5.4.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, - {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, + {file = "cachetools-5.4.0-py3-none-any.whl", hash = "sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474"}, + {file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"}, ] [[package]] @@ -641,6 +646,17 @@ files = [ marshmallow = ">=3.18.0,<4.0.0" typing-inspect = ">=0.4.0,<1" +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "deprecated" version = "1.2.14" @@ -923,6 +939,23 @@ test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe, test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] tqdm = ["tqdm"] +[[package]] +name = "ghp-import" +version = "2.1.0" +description = "Copy your docs directly to the gh-pages branch." +optional = false +python-versions = "*" +files = [ + {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, + {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, +] + +[package.dependencies] +python-dateutil = ">=2.8.1" + +[package.extras] +dev = ["flake8", "markdown", "twine", "wheel"] + [[package]] name = "google-ai-generativelanguage" version = "0.6.6" @@ -1332,13 +1365,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "huggingface-hub" -version = "0.23.4" +version = "0.23.5" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = false python-versions = ">=3.8.0" files = [ - {file = "huggingface_hub-0.23.4-py3-none-any.whl", hash = "sha256:3a0b957aa87150addf0cc7bd71b4d954b78e749850e1e7fb29ebbd2db64ca037"}, - {file = "huggingface_hub-0.23.4.tar.gz", hash = "sha256:35d99016433900e44ae7efe1c209164a5a81dbbcd53a52f99c281dcd7ce22431"}, + {file = "huggingface_hub-0.23.5-py3-none-any.whl", hash = "sha256:d7a7d337615e11a45cc14a0ce5a605db6b038dc24af42866f731684825226e90"}, + {file = "huggingface_hub-0.23.5.tar.gz", hash = "sha256:67a9caba79b71235be3752852ca27da86bd54311d2424ca8afdb8dda056edf98"}, ] [package.dependencies] @@ -1468,6 +1501,76 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jiter" +version = "0.5.0" +description = "Fast iterable JSON parser." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jiter-0.5.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b599f4e89b3def9a94091e6ee52e1d7ad7bc33e238ebb9c4c63f211d74822c3f"}, + {file = "jiter-0.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a063f71c4b06225543dddadbe09d203dc0c95ba352d8b85f1221173480a71d5"}, + {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc0d5b8b3dd12e91dd184b87273f864b363dfabc90ef29a1092d269f18c7e28"}, + {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c22541f0b672f4d741382a97c65609332a783501551445ab2df137ada01e019e"}, + {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63314832e302cc10d8dfbda0333a384bf4bcfce80d65fe99b0f3c0da8945a91a"}, + {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a25fbd8a5a58061e433d6fae6d5298777c0814a8bcefa1e5ecfff20c594bd749"}, + {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:503b2c27d87dfff5ab717a8200fbbcf4714516c9d85558048b1fc14d2de7d8dc"}, + {file = "jiter-0.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d1f3d27cce923713933a844872d213d244e09b53ec99b7a7fdf73d543529d6d"}, + {file = "jiter-0.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c95980207b3998f2c3b3098f357994d3fd7661121f30669ca7cb945f09510a87"}, + {file = "jiter-0.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:afa66939d834b0ce063f57d9895e8036ffc41c4bd90e4a99631e5f261d9b518e"}, + {file = "jiter-0.5.0-cp310-none-win32.whl", hash = "sha256:f16ca8f10e62f25fd81d5310e852df6649af17824146ca74647a018424ddeccf"}, + {file = "jiter-0.5.0-cp310-none-win_amd64.whl", hash = "sha256:b2950e4798e82dd9176935ef6a55cf6a448b5c71515a556da3f6b811a7844f1e"}, + {file = "jiter-0.5.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d4c8e1ed0ef31ad29cae5ea16b9e41529eb50a7fba70600008e9f8de6376d553"}, + {file = "jiter-0.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6f16e21276074a12d8421692515b3fd6d2ea9c94fd0734c39a12960a20e85f3"}, + {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5280e68e7740c8c128d3ae5ab63335ce6d1fb6603d3b809637b11713487af9e6"}, + {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:583c57fc30cc1fec360e66323aadd7fc3edeec01289bfafc35d3b9dcb29495e4"}, + {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26351cc14507bdf466b5f99aba3df3143a59da75799bf64a53a3ad3155ecded9"}, + {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829df14d656b3fb87e50ae8b48253a8851c707da9f30d45aacab2aa2ba2d614"}, + {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42a4bdcf7307b86cb863b2fb9bb55029b422d8f86276a50487982d99eed7c6e"}, + {file = "jiter-0.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04d461ad0aebf696f8da13c99bc1b3e06f66ecf6cfd56254cc402f6385231c06"}, + {file = "jiter-0.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6375923c5f19888c9226582a124b77b622f8fd0018b843c45eeb19d9701c403"}, + {file = "jiter-0.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cec323a853c24fd0472517113768c92ae0be8f8c384ef4441d3632da8baa646"}, + {file = "jiter-0.5.0-cp311-none-win32.whl", hash = "sha256:aa1db0967130b5cab63dfe4d6ff547c88b2a394c3410db64744d491df7f069bb"}, + {file = "jiter-0.5.0-cp311-none-win_amd64.whl", hash = "sha256:aa9d2b85b2ed7dc7697597dcfaac66e63c1b3028652f751c81c65a9f220899ae"}, + {file = "jiter-0.5.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9f664e7351604f91dcdd557603c57fc0d551bc65cc0a732fdacbf73ad335049a"}, + {file = "jiter-0.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:044f2f1148b5248ad2c8c3afb43430dccf676c5a5834d2f5089a4e6c5bbd64df"}, + {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:702e3520384c88b6e270c55c772d4bd6d7b150608dcc94dea87ceba1b6391248"}, + {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:528d742dcde73fad9d63e8242c036ab4a84389a56e04efd854062b660f559544"}, + {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cf80e5fe6ab582c82f0c3331df27a7e1565e2dcf06265afd5173d809cdbf9ba"}, + {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:44dfc9ddfb9b51a5626568ef4e55ada462b7328996294fe4d36de02fce42721f"}, + {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c451f7922992751a936b96c5f5b9bb9312243d9b754c34b33d0cb72c84669f4e"}, + {file = "jiter-0.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:308fce789a2f093dca1ff91ac391f11a9f99c35369117ad5a5c6c4903e1b3e3a"}, + {file = "jiter-0.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7f5ad4a7c6b0d90776fdefa294f662e8a86871e601309643de30bf94bb93a64e"}, + {file = "jiter-0.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ea189db75f8eca08807d02ae27929e890c7d47599ce3d0a6a5d41f2419ecf338"}, + {file = "jiter-0.5.0-cp312-none-win32.whl", hash = "sha256:e3bbe3910c724b877846186c25fe3c802e105a2c1fc2b57d6688b9f8772026e4"}, + {file = "jiter-0.5.0-cp312-none-win_amd64.whl", hash = "sha256:a586832f70c3f1481732919215f36d41c59ca080fa27a65cf23d9490e75b2ef5"}, + {file = "jiter-0.5.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f04bc2fc50dc77be9d10f73fcc4e39346402ffe21726ff41028f36e179b587e6"}, + {file = "jiter-0.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6f433a4169ad22fcb550b11179bb2b4fd405de9b982601914ef448390b2954f3"}, + {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad4a6398c85d3a20067e6c69890ca01f68659da94d74c800298581724e426c7e"}, + {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6baa88334e7af3f4d7a5c66c3a63808e5efbc3698a1c57626541ddd22f8e4fbf"}, + {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ece0a115c05efca597c6d938f88c9357c843f8c245dbbb53361a1c01afd7148"}, + {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:335942557162ad372cc367ffaf93217117401bf930483b4b3ebdb1223dbddfa7"}, + {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649b0ee97a6e6da174bffcb3c8c051a5935d7d4f2f52ea1583b5b3e7822fbf14"}, + {file = "jiter-0.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f4be354c5de82157886ca7f5925dbda369b77344b4b4adf2723079715f823989"}, + {file = "jiter-0.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5206144578831a6de278a38896864ded4ed96af66e1e63ec5dd7f4a1fce38a3a"}, + {file = "jiter-0.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8120c60f8121ac3d6f072b97ef0e71770cc72b3c23084c72c4189428b1b1d3b6"}, + {file = "jiter-0.5.0-cp38-none-win32.whl", hash = "sha256:6f1223f88b6d76b519cb033a4d3687ca157c272ec5d6015c322fc5b3074d8a5e"}, + {file = "jiter-0.5.0-cp38-none-win_amd64.whl", hash = "sha256:c59614b225d9f434ea8fc0d0bec51ef5fa8c83679afedc0433905994fb36d631"}, + {file = "jiter-0.5.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0af3838cfb7e6afee3f00dc66fa24695199e20ba87df26e942820345b0afc566"}, + {file = "jiter-0.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:550b11d669600dbc342364fd4adbe987f14d0bbedaf06feb1b983383dcc4b961"}, + {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:489875bf1a0ffb3cb38a727b01e6673f0f2e395b2aad3c9387f94187cb214bbf"}, + {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b250ca2594f5599ca82ba7e68785a669b352156260c5362ea1b4e04a0f3e2389"}, + {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ea18e01f785c6667ca15407cd6dabbe029d77474d53595a189bdc813347218e"}, + {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:462a52be85b53cd9bffd94e2d788a09984274fe6cebb893d6287e1c296d50653"}, + {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92cc68b48d50fa472c79c93965e19bd48f40f207cb557a8346daa020d6ba973b"}, + {file = "jiter-0.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c834133e59a8521bc87ebcad773608c6fa6ab5c7a022df24a45030826cf10bc"}, + {file = "jiter-0.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab3a71ff31cf2d45cb216dc37af522d335211f3a972d2fe14ea99073de6cb104"}, + {file = "jiter-0.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cccd3af9c48ac500c95e1bcbc498020c87e1781ff0345dd371462d67b76643eb"}, + {file = "jiter-0.5.0-cp39-none-win32.whl", hash = "sha256:368084d8d5c4fc40ff7c3cc513c4f73e02c85f6009217922d0823a48ee7adf61"}, + {file = "jiter-0.5.0-cp39-none-win_amd64.whl", hash = "sha256:ce03f7b4129eb72f1687fa11300fbf677b02990618428934662406d2a76742a1"}, + {file = "jiter-0.5.0.tar.gz", hash = "sha256:1d916ba875bcab5c5f7d927df998c4cb694d27dceddf3392e58beaf10563368a"}, +] + [[package]] name = "jsonpatch" version = "1.33" @@ -1521,19 +1624,19 @@ adal = ["adal (>=1.0.2)"] [[package]] name = "langchain" -version = "0.2.7" +version = "0.2.8" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.2.7-py3-none-any.whl", hash = "sha256:98e79e0b9a60a9c740b44d5b0135c85f649219308f30d373cf5f10d0efe18b87"}, - {file = "langchain-0.2.7.tar.gz", hash = "sha256:8742f363d2890854501e0075af04fcb470600f201dec251c9bd5841e1990e73d"}, + {file = "langchain-0.2.8-py3-none-any.whl", hash = "sha256:53e7dfe50294a14200f33bec22b4e14cb63857ccf0a5500b0d18b0fd51285d58"}, + {file = "langchain-0.2.8.tar.gz", hash = "sha256:7fecb309e3558cde4e5cf7e9ffb7c1ab3f07121c40a7ff3b0c27135f8120c296"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -langchain-core = ">=0.2.12,<0.3.0" +langchain-core = ">=0.2.19,<0.3.0" langchain-text-splitters = ">=0.2.0,<0.3.0" langsmith = ">=0.1.17,<0.2.0" numpy = [ @@ -1546,6 +1649,22 @@ requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<9.0.0" +[[package]] +name = "langchain-anthropic" +version = "0.1.20" +description = "An integration package connecting AnthropicMessages and LangChain" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_anthropic-0.1.20-py3-none-any.whl", hash = "sha256:3a0d89ac6856be98beb3ec63813393bf29af3c5134247979c055938e741b7d9d"}, + {file = "langchain_anthropic-0.1.20.tar.gz", hash = "sha256:cb9607fecfc0f0de49b79dd0fc066790e2877873ef753abd98d2ae38d6e0f5b2"}, +] + +[package.dependencies] +anthropic = ">=0.28.0,<1" +defusedxml = ">=0.7.1,<0.8.0" +langchain-core = ">=0.2.17,<0.3" + [[package]] name = "langchain-community" version = "0.2.7" @@ -1574,13 +1693,13 @@ tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<9.0.0" [[package]] name = "langchain-core" -version = "0.2.18" +version = "0.2.19" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.2.18-py3-none-any.whl", hash = "sha256:c9dbb197508e76337ed810ec977d40ae0c896397d191b420ef126c3818a1be96"}, - {file = "langchain_core-0.2.18.tar.gz", hash = "sha256:ca5c5f1a783449dae8686e366ff3c5b775f8b5cef0de4ef346b8820d3d1c46ff"}, + {file = "langchain_core-0.2.19-py3-none-any.whl", hash = "sha256:5b3cd34395be274c89e822c84f0e03c4da14168c177a83921c5b9414ac7a0651"}, + {file = "langchain_core-0.2.19.tar.gz", hash = "sha256:13043a83e5c9ab58b9f5ce2a56896e7e88b752e8891b2958960a98e71801471e"}, ] [package.dependencies] @@ -1594,6 +1713,24 @@ pydantic = [ PyYAML = ">=5.3" tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<9.0.0" +[[package]] +name = "langchain-google-genai" +version = "1.0.7" +description = "An integration package connecting Google's genai package and LangChain" +optional = false +python-versions = "<4.0,>=3.9" +files = [ + {file = "langchain_google_genai-1.0.7-py3-none-any.whl", hash = "sha256:8fc03a0b5f635d369d1eec25076921ea7a472a1cb96dbea8e8ff2c2cdce58650"}, + {file = "langchain_google_genai-1.0.7.tar.gz", hash = "sha256:6522da59720ad551867e278d63c053e0fb65fa4fa1d65382aacedca5293930fa"}, +] + +[package.dependencies] +google-generativeai = ">=0.7.0,<0.8.0" +langchain-core = ">=0.2.9,<0.3" + +[package.extras] +images = ["pillow (>=10.1.0,<11.0.0)"] + [[package]] name = "langchain-openai" version = "0.1.16" @@ -1626,13 +1763,13 @@ langchain-core = ">=0.2.10,<0.3.0" [[package]] name = "langsmith" -version = "0.1.85" +version = "0.1.86" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.85-py3-none-any.whl", hash = "sha256:c1f94384f10cea96f7b4d33fd3db7ec180c03c7468877d50846f881d2017ff94"}, - {file = "langsmith-0.1.85.tar.gz", hash = "sha256:acff31f9e53efa48586cf8e32f65625a335c74d7c4fa306d1655ac18452296f6"}, + {file = "langsmith-0.1.86-py3-none-any.whl", hash = "sha256:55ed80cc6e98f9761f9b3ec3c49e01f6745d13e40bef80d9f831acabfd9a8a1e"}, + {file = "langsmith-0.1.86.tar.gz", hash = "sha256:2e66577817253327b99b727588c3173fbba217fe0ca07ac6b7cdd23fc4894104"}, ] [package.dependencies] @@ -1801,6 +1938,24 @@ html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] source = ["Cython (>=3.0.10)"] +[[package]] +name = "markdown" +version = "3.6" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, + {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -1924,6 +2079,65 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "mergedeep" +version = "1.3.4" +description = "A deep merge function for 🐍." +optional = false +python-versions = ">=3.6" +files = [ + {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, + {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, +] + +[[package]] +name = "mkdocs" +version = "1.6.0" +description = "Project documentation with Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7"}, + {file = "mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +ghp-import = ">=1.0" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +jinja2 = ">=2.11.1" +markdown = ">=3.3.6" +markupsafe = ">=2.0.1" +mergedeep = ">=1.3.4" +mkdocs-get-deps = ">=0.2.0" +packaging = ">=20.5" +pathspec = ">=0.11.1" +pyyaml = ">=5.1" +pyyaml-env-tag = ">=0.1" +watchdog = ">=2.0" + +[package.extras] +i18n = ["babel (>=2.9.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, + {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +mergedeep = ">=1.3.4" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" + [[package]] name = "mmh3" version = "4.1.0" @@ -2306,13 +2520,13 @@ sympy = "*" [[package]] name = "openai" -version = "1.35.13" +version = "1.35.14" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.35.13-py3-none-any.whl", hash = "sha256:36ec3e93e0d1f243f69be85c89b9221a471c3e450dfd9df16c9829e3cdf63e60"}, - {file = "openai-1.35.13.tar.gz", hash = "sha256:c684f3945608baf7d2dcc0ef3ee6f3e27e4c66f21076df0b47be45d57e6ae6e4"}, + {file = "openai-1.35.14-py3-none-any.whl", hash = "sha256:adadf8c176e0b8c47ad782ed45dc20ef46438ee1f02c7103c4155cff79c8f68b"}, + {file = "openai-1.35.14.tar.gz", hash = "sha256:394ba1dfd12ecec1d634c50e512d24ff1858bbc2674ffcce309b822785a058de"}, ] [package.dependencies] @@ -2585,6 +2799,33 @@ files = [ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "platformdirs" +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] + [[package]] name = "pluggy" version = "1.5.0" @@ -3132,6 +3373,20 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +description = "A custom YAML tag for referencing environment variables in YAML files. " +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, + {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, +] + +[package.dependencies] +pyyaml = "*" + [[package]] name = "regex" version = "2024.5.15" @@ -3877,6 +4132,50 @@ files = [ docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] +[[package]] +name = "watchdog" +version = "4.0.1" +description = "Filesystem events monitoring" +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"}, + {file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"}, + {file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"}, + {file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"}, + {file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"}, +] + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + [[package]] name = "watchfiles" version = "0.22.0" @@ -4261,4 +4560,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "c51a950510f208251a1d2e609b3f92ee1a1571e496f84e0f92df39c4d4019d8e" +content-hash = "394b8cb22689d72231bb3cafcb3f5e2e45372fc4560ee4e22d7b6372df14a4f3" diff --git a/pyproject.toml b/pyproject.toml index ca8daa9..5ce0c23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langrade" -version = "0.1.2" +version = "0.1.3" description = "A library for grading document relevance using LLMs" authors = ["nisaji "] license = "MIT" @@ -19,8 +19,10 @@ python-docx = "^1.1.2" beautifulsoup4 = "^4.12.3" numpy = "^1.22.5" chromadb = "^0.5.3,<0.6.0" +langchain-anthropic = "^0.1.20" +langchain-google-genai = "^1.0.7" - +mkdocs = "^1.6.0" [tool.poetry.group.dev.dependencies] ruff = "^0.5.0" mypy = "^1.10.1" diff --git a/setup.py b/setup.py index b1bad3f..5bfce9c 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="langrade", - version="0.1.2", + version="0.1.3", author="Your Name", author_email="your.email@example.com", description="A library for grading and retrieving documents based on relevance", # noqa: E501 diff --git a/tests/test_grader.py b/tests/test_grader.py index 34c4d8c..aa77cdd 100644 --- a/tests/test_grader.py +++ b/tests/test_grader.py @@ -1,5 +1,4 @@ import unittest -from unittest.mock import patch, MagicMock from langrade import document_grader from conftest import get_api_key @@ -7,24 +6,13 @@ class TestDocumentGrader(unittest.TestCase): def setUp(self): self.api_key = get_api_key() - self.grader = document_grader(self.api_key) - - @patch("langrade.grader.ChatOpenAI") - def test_grade_document(self, mock_chat_openai): - mock_llm = MagicMock() - mock_chat_openai.return_value = mock_llm - mock_result = MagicMock( - binary_score="yes", - reasoning="The document provides a definition of AI as a field of computer science creating intelligent machines, which directly answers the user question.", # noqa: E501 - ) - mock_llm.with_structured_output.return_value.invoke.return_value = ( - mock_result # noqa: E501 - ) + self.provider = "openai" # γΎγŸγ―ι©εˆ‡γͺプロバむダー + self.grader = document_grader(self.provider, self.api_key) + def test_grade_document(self): document = "AI is a field of computer science that focuses on creating intelligent machines." # noqa: E501 question = "What is AI?" result = self.grader.grade_document(document, question) - print("result", result) - self.assertEqual(result.binary_score, "yes") + self.assertIsNotNone(result.binary_score) self.assertIsNotNone(result.reasoning) diff --git a/tests/test_providers.py b/tests/test_providers.py new file mode 100644 index 0000000..fad89b7 --- /dev/null +++ b/tests/test_providers.py @@ -0,0 +1,64 @@ +import os +import unittest +from dotenv import load_dotenv +from langrade.providers import LLMProviderFactory, GradeDocuments + +# 環咃倉数をθͺ­γΏθΎΌγ‚€ +load_dotenv() + + +class TestProviders(unittest.TestCase): + + def setUp(self): + self.openai_api_key = os.getenv("OPENAI_API_KEY") + self.openai_model = os.getenv("OPENAI_MODEL") + self.google_api_key = os.getenv("GOOGLE_API_KEY") + self.gemini_model = os.getenv("GEMINI_MODEL") + self.anthropic_api_key = os.getenv("ANTHROPIC_API_KEY") + self.claude_model = os.getenv("CLAUDE_MODEL") + + self.test_document = "Artificial Intelligence (AI) is the simulation of human intelligence processes by machines, especially computer systems." # noqa: E501 + self.test_question = "What is AI?" + + def test_openai_provider(self): + provider = LLMProviderFactory.create_provider( + "openai", self.openai_api_key, self.openai_model + ) + result = provider.grade_document( + self.test_document, self.test_question + ) # noqa: E501 + self.assertIsInstance(result, GradeDocuments) + self.assertIn(result.binary_score.lower(), ["yes", "no"]) + self.assertIsNotNone(result.reasoning) + + def test_google_provider(self): + provider = LLMProviderFactory.create_provider( + "google", self.google_api_key, self.gemini_model + ) + result = provider.grade_document( + self.test_document, self.test_question + ) # noqa: E501 + self.assertIsInstance(result, GradeDocuments) + self.assertIn(result.binary_score.lower(), ["yes", "no"]) + self.assertIsNotNone(result.reasoning) + + def test_anthropic_provider(self): + provider = LLMProviderFactory.create_provider( + "anthropic", self.anthropic_api_key, self.claude_model + ) + result = provider.grade_document( + self.test_document, self.test_question + ) # noqa: E501 + self.assertIsInstance(result, GradeDocuments) + self.assertIn(result.binary_score.lower(), ["yes", "no"]) + self.assertIsNotNone(result.reasoning) + + def test_invalid_provider(self): + with self.assertRaises(ValueError): + LLMProviderFactory.create_provider( + "invalid_provider", "dummy_key", "dummy_model" + ) + + +if __name__ == "__main__": + unittest.main()