Download patch.py from rks0612/Medbot: direct link, hf CLI and curl.
- Browser
- Download file 6.62 kB
-
https://huggingface.co/spaces/rks0612/Medbot/resolve/main/patch.py
- Command line
-
hf download hf://spaces/rks0612/Medbot/patch.py
-
curl -L -o patch.py https://huggingface.co/spaces/rks0612/Medbot/resolve/main/patch.py
6.62 kB
| import re | |
| with open("rag_pipeline.py", "r") as f: | |
| content = f.read() | |
| # Replace Imports | |
| content = content.replace( | |
| "from langchain_text_splitters import RecursiveCharacterTextSplitter", | |
| "import glob\nimport pymupdf4llm\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter, MarkdownHeaderTextSplitter" | |
| ) | |
| # Replace Config | |
| content = content.replace( | |
| """PDF_PATH = os.path.join( | |
| os.path.dirname(__file__), | |
| "Martindale-The-Complete-Drug-Reference_-36th-Edition (1).pdf" | |
| )""", | |
| """DATA_DIR = os.path.dirname(__file__)""" | |
| ) | |
| # Extract to Return pattern replacement | |
| pattern = r"# ββ PDF Text Extraction.*?logger\.info\(f\"Created \{len\(all_chunks\)\} chunks from \{len\(pages\)\} pages\"\)\n return all_chunks" | |
| new_extraction_code = """# ββ Markdown-Aware Ingestion & Chunking βββββββββββββββββββββββββ | |
| def chunk_documents_from_markdown(pdf_path: str) -> list[dict]: | |
| \"\"\"Extract PDF to Markdown and chunk via headings.\"\"\" | |
| filename = os.path.basename(pdf_path) | |
| logger.info(f"Extracting markdown from {filename} (This may take several minutes)...") | |
| try: | |
| md_text = pymupdf4llm.to_markdown(pdf_path) | |
| except Exception as e: | |
| logger.error(f"Failed to extract {filename}: {e}") | |
| return [] | |
| logger.info(f"Extraction complete for {filename}. Splitting text...") | |
| headers_to_split_on = [ | |
| ("#", "Header 1"), | |
| ("##", "Header 2"), | |
| ("###", "Header 3"), | |
| ] | |
| md_splitter = MarkdownHeaderTextSplitter( | |
| headers_to_split_on=headers_to_split_on, | |
| strip_headers=False | |
| ) | |
| char_splitter = RecursiveCharacterTextSplitter( | |
| chunk_size=CHUNK_SIZE, | |
| chunk_overlap=CHUNK_OVERLAP, | |
| ) | |
| md_docs = md_splitter.split_text(md_text) | |
| all_chunks = [] | |
| for i, doc in enumerate(md_docs): | |
| if len(doc.page_content) > CHUNK_SIZE: | |
| sub_docs = char_splitter.split_text(doc.page_content) | |
| else: | |
| sub_docs = [doc.page_content] | |
| for j, text_chunk in enumerate(sub_docs): | |
| if len(text_chunk.strip()) < 50: | |
| continue | |
| section = "General" | |
| if doc.metadata: | |
| headers = [str(v) for k, v in doc.metadata.items() if "Header" in k] | |
| if headers: | |
| section = " > ".join(headers) | |
| chunk_id = hashlib.md5(f"{filename}_{i}_{j}_{text_chunk[:50]}".encode()).hexdigest() | |
| all_chunks.append({ | |
| "id": chunk_id, | |
| "text": text_chunk, | |
| "metadata": { | |
| "book": filename, | |
| "section": section[:100], | |
| "chunk_index": i, | |
| "char_count": len(text_chunk), | |
| "page": "N/A" | |
| } | |
| }) | |
| logger.info(f"Created {len(all_chunks)} chunks from {filename}") | |
| return all_chunks""" | |
| content = re.sub(pattern, new_extraction_code, content, flags=re.DOTALL) | |
| # Replace Build Vector Store | |
| pattern_build = r"def build_vector_store\(force_rebuild: bool = False\) -> int:.*?return total" | |
| new_build_code = """def build_vector_store(force_rebuild: bool = False) -> int: | |
| \"\"\"Build the ChromaDB vector store from the PDFs. Returns chunks indexed.\"\"\" | |
| if collection_exists() and not force_rebuild: | |
| client = get_chroma_client() | |
| collection = client.get_collection( | |
| name=COLLECTION_NAME, | |
| embedding_function=get_embedding_function() | |
| ) | |
| count = collection.count() | |
| logger.info(f"Using existing vector store with {count} chunks") | |
| return count | |
| logger.info("Building vector store from PDFs...") | |
| client = get_chroma_client() | |
| try: | |
| client.delete_collection(name=COLLECTION_NAME) | |
| except Exception: | |
| pass | |
| ef = get_embedding_function() | |
| collection = client.create_collection( | |
| name=COLLECTION_NAME, | |
| embedding_function=ef, | |
| metadata={"hnsw:space": "cosine"} | |
| ) | |
| pdf_files = glob.glob(os.path.join(DATA_DIR, "*.pdf")) | |
| if not pdf_files: | |
| logger.error(f"No PDFs found in {DATA_DIR}") | |
| return 0 | |
| total_chunks_indexed = 0 | |
| BATCH_SIZE = 500 | |
| for pdf_path in pdf_files: | |
| chunks = chunk_documents_from_markdown(pdf_path) | |
| if not chunks: | |
| continue | |
| total = len(chunks) | |
| for start in range(0, total, BATCH_SIZE): | |
| end = min(start + BATCH_SIZE, total) | |
| batch = chunks[start:end] | |
| collection.add( | |
| ids=[c["id"] for c in batch], | |
| documents=[c["text"] for c in batch], | |
| metadatas=[c["metadata"] for c in batch], | |
| ) | |
| logger.info(f" Indexed {end}/{total} chunks from {os.path.basename(pdf_path)}...") | |
| total_chunks_indexed += total | |
| logger.info(f"Vector store built successfully with {total_chunks_indexed} total chunks") | |
| return total_chunks_indexed""" | |
| content = re.sub(pattern_build, new_build_code, content, flags=re.DOTALL) | |
| # Replace context stuff | |
| content = content.replace( | |
| ' "page": meta.get("page", "?"),', | |
| ' "book": meta.get("book", "Unknown"),\n "page": meta.get("page", "?"),' | |
| ) | |
| # Format for LLM | |
| content = content.replace( | |
| """ parts.append( | |
| f"[Reference {src_num} | Page {ctx['page']} | {ctx['section']}]\\n" | |
| f"{ctx['text']}" | |
| )""", | |
| """ book = ctx.get('book', 'Unknown') | |
| parts.append( | |
| f"[Reference {src_num} | Book: {book} | {ctx['section']}]\\n" | |
| f"{ctx['text']}" | |
| )""" | |
| ) | |
| # sources dict | |
| content = content.replace( | |
| """ sources = [ | |
| {"page": ctx["page"], "section": ctx["section"], "relevance": round(1 - ctx["distance"], 4)}""", | |
| """ sources = [ | |
| {"book": ctx.get("book", "?"), "section": ctx["section"], "relevance": round(1 - ctx["distance"], 4)}""" | |
| ) | |
| # System prompt update | |
| content = content.replace( | |
| "*Martindale: The Complete Drug Reference (36th Edition)*", | |
| "*Martindale: The Complete Drug Reference (36th Edition) and RxPrep*" | |
| ) | |
| content = content.replace( | |
| "f\"## Retrieved Reference Context (from Martindale 36th Ed.)\\n\\n\"", | |
| "f\"## Retrieved Reference Context (from Pharmaceutical Textbooks)\\n\\n\"" | |
| ) | |
| with open("rag_pipeline.py", "w") as f: | |
| f.write(content) | |