Views
No views yet

ReaderLM-v2 is a 1.5B parameter language model that converts raw HTML into beautifully formatted markdown or JSON with superior accuracy and improved longer context handling. Supporting multiple languages (29 in total), ReaderLM-v2 is specialized for tasks involving HTML parsing, transformation, and text extraction.ReaderLM-v2ReaderLM-v2 represents a significant leap forward from its predecessor, with several key improvements:ReaderLM-v2 locally using the Hugging Face Transformers library.
For a more hands-on experience in a hosted environment, see the Google Colab Notebook.ReaderLM-v2 is now fully integrated with Reader API. To use it, simply specify x-engine: readerlm-v2 in your request headers and enable response streaming with -H 'Accept: text/event-stream':curl https://r.jina.ai/https://news.ycombinator.com/ -H 'x-engine: readerlm-v2' -H 'Accept: text/event-stream'ReaderLM-v2 via our Colab notebook, which demonstrates HTML-to-markdown conversion, JSON extraction, and instruction-following using the HackerNews frontpage as an example. The notebook is optimized for Colab's free T4 GPU tier and requires vllm and triton for acceleration and running.ReaderLM-v2 locally:pip install transformers1from transformers import AutoModelForCausalLM, AutoTokenizer
2
3device = "cuda" # or "cpu"
4tokenizer = AutoTokenizer.from_pretrained("jinaai/ReaderLM-v2")
5model = AutoModelForCausalLM.from_pretrained("jinaai/ReaderLM-v2").to(device)1import re
2
3# Patterns
4SCRIPT_PATTERN = r"<[ ]*script.*?\/[ ]*script[ ]*>"
5STYLE_PATTERN = r"<[ ]*style.*?\/[ ]*style[ ]*>"
6META_PATTERN = r"<[ ]*meta.*?>"
7COMMENT_PATTERN = r"<[ ]*!--.*?--[ ]*>"
8LINK_PATTERN = r"<[ ]*link.*?>"
9BASE64_IMG_PATTERN = r'<img[^>]+src="data:image/[^;]+;base64,[^"]+"[^>]*>'
10SVG_PATTERN = r"(<svg[^>]*>)(.*?)(<\/svg>)"
11
12
13def replace_svg(html: str, new_content: str = "this is a placeholder") -> str:
14 return re.sub(
15 SVG_PATTERN,
16 lambda match: f"{match.group(1)}{new_content}{match.group(3)}",
17 html,
18 flags=re.DOTALL,
19 )
20
21
22def replace_base64_images(html: str, new_image_src: str = "#") -> str:
23 return re.sub(BASE64_IMG_PATTERN, f'<img src="{new_image_src}"/>', html)
24
25
26def clean_html(html: str, clean_svg: bool = False, clean_base64: bool = False):
27 html = re.sub(
28 SCRIPT_PATTERN, "", html, flags=re.IGNORECASE | re.MULTILINE | re.DOTALL
29 )
30 html = re.sub(
31 STYLE_PATTERN, "", html, flags=re.IGNORECASE | re.MULTILINE | re.DOTALL
32 )
33 html = re.sub(
34 META_PATTERN, "", html, flags=re.IGNORECASE | re.MULTILINE | re.DOTALL
35 )
36 html = re.sub(
37 COMMENT_PATTERN, "", html, flags=re.IGNORECASE | re.MULTILINE | re.DOTALL
38 )
39 html = re.sub(
40 LINK_PATTERN, "", html, flags=re.IGNORECASE | re.MULTILINE | re.DOTALL
41 )
42
43 if clean_svg:
44 html = replace_svg(html)
45 if clean_base64:
46 html = replace_base64_images(html)
47 return html1def create_prompt(
2 text: str, tokenizer=None, instruction: str = None, schema: str = None
3) -> str:
4 """
5 Create a prompt for the model with optional instruction and JSON schema.
6 """
7 if not instruction:
8 instruction = "Extract the main content from the given HTML and convert it to Markdown format."
9 if schema:
10 instruction = "Extract the specified information from a list of news threads and present it in a structured JSON format."
11 prompt = f"{instruction}\n```html\n{text}\n```\nThe JSON schema is as follows:```json\n{schema}\n```"
12 else:
13 prompt = f"{instruction}\n```html\n{text}\n```"
14
15 messages = [
16 {
17 "role": "user",
18 "content": prompt,
19 }
20 ]
21
22 return tokenizer.apply_chat_template(
23 messages, tokenize=False, add_generation_prompt=True
24 )1html = "<html><body><h1>Hello, world!</h1></body></html>"
2
3html = clean_html(html)
4
5input_prompt = create_prompt(html, tokenizer=tokenizer)
6inputs = tokenizer.encode(input_prompt, return_tensors="pt").to(device)
7outputs = model.generate(
8 inputs, max_new_tokens=1024, temperature=0, do_sample=False, repetition_penalty=1.08
9)
10
11print(tokenizer.decode(outputs[0]))1schema = """
2{
3 "type": "object",
4 "properties": {
5 "title": {
6 "type": "string"
7 },
8 "author": {
9 "type": "string"
10 },
11 "date": {
12 "type": "string"
13 },
14 "content": {
15 "type": "string"
16 }
17 },
18 "required": ["title", "author", "date", "content"]
19}
20"""
21
22html = clean_html(html)
23input_prompt = create_prompt(html, tokenizer=tokenizer, schema=schema)
24
25inputs = tokenizer.encode(input_prompt, return_tensors="pt").to(device)
26outputs = model.generate(
27 inputs, max_new_tokens=1024, temperature=0, do_sample=False, repetition_penalty=1.08
28)
29
30print(tokenizer.decode(outputs[0]))