mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-17 23:41:46 +00:00
community: Add MarkdownifyTransformer to langchain_community.document_transformers (#21247)
- Added new document_transformer: MarkdonifyTransformer, that uses `markdonify` package with customizable options to convert HTML to Markdown. It's similar to Html2TextTransformer, but has more flexible options and also I've noticed that sometimes MarkdownifyTransformer performs better than html2text one, so that's why I use markdownify on my project. - Added docs and tests - Usage: ```python from langchain_community.document_transformers import MarkdownifyTransformer markdownify = MarkdownifyTransformer() docs_transform = markdownify.transform_documents(docs) ``` - Example of better performance on simple task, that I've noticed: ``` <html> <head><title>Reports on product movement</title></head> <body> <p data-block-key="2wst7">The reports on product movement will be useful for forming supplier orders and controlling outcomes.</p> </body> ``` **Html2TextTransformer**: ```python [Document(page_content='The reports on product movement will be useful for forming supplier orders and\ncontrolling outcomes.\n\n')] # Here we can see 'and\ncontrolling', which has extra '\n' in it ``` **MarkdownifyTranformer**: ```python [Document(page_content='Reports on product movement\n\nThe reports on product movement will be useful for forming supplier orders and controlling outcomes.')] ``` --------- Co-authored-by: Sokolov Fedor <f.sokolov@sokolov-macbook.bbrouter> Co-authored-by: Harrison Chase <hw.chase.17@gmail.com> Co-authored-by: Sokolov Fedor <f.sokolov@sokolov-macbook.local> Co-authored-by: Sokolov Fedor <f.sokolov@192.168.1.6>
This commit is contained in:
@@ -13,6 +13,7 @@ EXPECTED_ALL = [
|
||||
"NucliaTextTransformer",
|
||||
"OpenAIMetadataTagger",
|
||||
"Html2TextTransformer",
|
||||
"MarkdownifyTransformer",
|
||||
]
|
||||
|
||||
|
||||
|
@@ -0,0 +1,138 @@
|
||||
"""Unit tests for markdownify document transformer."""
|
||||
import pytest
|
||||
from langchain_core.documents import Document
|
||||
|
||||
from langchain_community.document_transformers import MarkdownifyTransformer
|
||||
|
||||
|
||||
@pytest.mark.requires("markdownify")
|
||||
def test_empty_html() -> None:
|
||||
markdownify = MarkdownifyTransformer()
|
||||
empty_html = "<html></html>"
|
||||
documents = [Document(page_content=empty_html)]
|
||||
docs_transformed = markdownify.transform_documents(documents)
|
||||
assert docs_transformed[0].page_content == ""
|
||||
|
||||
|
||||
@pytest.mark.requires("markdownify")
|
||||
def test_extract_paragraphs() -> None:
|
||||
markdownify = MarkdownifyTransformer()
|
||||
paragraphs_html = (
|
||||
"<html><h1>Header</h1><p>First paragraph.</p>"
|
||||
"<p>Second paragraph.</p><h1>Ignore at end</h1></html>"
|
||||
)
|
||||
documents = [Document(page_content=paragraphs_html)]
|
||||
docs_transformed = markdownify.transform_documents(documents)
|
||||
assert docs_transformed[0].page_content == (
|
||||
"# Header\n\n" "First paragraph.\n\n" "Second paragraph.\n\n" "# Ignore at end"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.requires("markdownify")
|
||||
def test_extract_html() -> None:
|
||||
markdownify = MarkdownifyTransformer(skip="title")
|
||||
basic_html = (
|
||||
"<!DOCTYPE html>"
|
||||
'<html lang="en">'
|
||||
"<head>"
|
||||
' <meta charset="UTF-8">'
|
||||
" <title>Simple Test Page</title>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
" <h1>Test Header</h1>"
|
||||
" <p>First paragraph.</p>"
|
||||
" <p>Second paragraph.</p>"
|
||||
' <a href="https://example.com">Example Link</a>'
|
||||
"</body>"
|
||||
"</html>"
|
||||
)
|
||||
documents = [Document(page_content=basic_html)]
|
||||
docs_transformed = markdownify.transform_documents(documents)
|
||||
assert docs_transformed[0].page_content == (
|
||||
"Simple Test Page # Test Header\n\n "
|
||||
"First paragraph.\n\n "
|
||||
"Second paragraph.\n\n "
|
||||
"[Example Link](https://example.com)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.requires("markdownify")
|
||||
def test_strip_tags() -> None:
|
||||
markdownify = MarkdownifyTransformer(strip="strong")
|
||||
paragraphs_html = (
|
||||
"<html>"
|
||||
"<h1>Header</h1>"
|
||||
" <p><strong>1st paragraph.</strong></p>"
|
||||
' <p>2nd paragraph. Here is <a href="http://example.com">link</a></p>'
|
||||
' <img src="image.jpg" alt="Sample Image">'
|
||||
"<h1>Ignore at end</h1></html>"
|
||||
)
|
||||
documents = [Document(page_content=paragraphs_html)]
|
||||
docs_transformed = markdownify.transform_documents(documents)
|
||||
assert docs_transformed[0].page_content == (
|
||||
"# Header\n\n "
|
||||
"1st paragraph.\n\n "
|
||||
"2nd paragraph. Here is [link](http://example.com)\n\n "
|
||||
""
|
||||
"# Ignore at end"
|
||||
)
|
||||
|
||||
markdownify = MarkdownifyTransformer(strip=["strong", "a", "img"])
|
||||
documents = [Document(page_content=paragraphs_html)]
|
||||
docs_transformed = markdownify.transform_documents(documents)
|
||||
assert docs_transformed[0].page_content == (
|
||||
"# Header\n\n "
|
||||
"1st paragraph.\n\n "
|
||||
"2nd paragraph. Here is link\n\n "
|
||||
"# Ignore at end"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.requires("markdownify")
|
||||
def test_convert_tags() -> None:
|
||||
markdownify = MarkdownifyTransformer(convert=["strong", "a"])
|
||||
paragraphs_html = (
|
||||
"<html>"
|
||||
"<h1>Header</h1>"
|
||||
" <p><strong>1st paragraph.</strong></p>"
|
||||
' <p>2nd paragraph. Here is <a href="http://example.com">link</a></p>'
|
||||
' <img src="image.jpg" alt="Sample Image">'
|
||||
"<h1>Ignore at end</h1></html>"
|
||||
)
|
||||
documents = [Document(page_content=paragraphs_html)]
|
||||
docs_transformed = markdownify.transform_documents(documents)
|
||||
assert docs_transformed[0].page_content == (
|
||||
"Header "
|
||||
"**1st paragraph.** "
|
||||
"2nd paragraph. Here is [link](http://example.com) "
|
||||
"Ignore at end"
|
||||
)
|
||||
|
||||
markdownify = MarkdownifyTransformer(convert="p")
|
||||
documents = [Document(page_content=paragraphs_html)]
|
||||
docs_transformed = markdownify.transform_documents(documents)
|
||||
assert docs_transformed[0].page_content == (
|
||||
"Header "
|
||||
"1st paragraph.\n\n "
|
||||
"2nd paragraph. Here is link\n\n "
|
||||
"Ignore at end"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.requires("markdownify")
|
||||
def test_strip_convert_conflict_error() -> None:
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match="You may specify either tags to strip or tags to convert, but not both.",
|
||||
):
|
||||
markdownify = MarkdownifyTransformer(strip="h1", convert=["strong", "a"])
|
||||
paragraphs_html = (
|
||||
"<html>"
|
||||
"<h1>Header</h1>"
|
||||
" <p><strong>1st paragraph.</strong></p>"
|
||||
' <p>2nd paragraph. Here is <a href="http://example.com">link</a></p>'
|
||||
' <img src="image.jpg" alt="Sample Image">'
|
||||
"<h1>Ignore at end</h1></html>"
|
||||
)
|
||||
documents = [Document(page_content=paragraphs_html)]
|
||||
markdownify.transform_documents(documents)
|
Reference in New Issue
Block a user