ShivanshCodex commited on
Commit
ad427f3
Β·
verified Β·
1 Parent(s): 13900c3

Delete pipeline

Browse files
pipeline/__pycache__/answer_generator.cpython-310.pyc DELETED
Binary file (5.33 kB)
 
pipeline/__pycache__/crawler.cpython-310.pyc DELETED
Binary file (2.04 kB)
 
pipeline/__pycache__/embed_and_store.cpython-310.pyc DELETED
Binary file (933 Bytes)
 
pipeline/__pycache__/link_ranker.cpython-310.pyc DELETED
Binary file (1.44 kB)
 
pipeline/__pycache__/query_handler.cpython-310.pyc DELETED
Binary file (458 Bytes)
 
pipeline/__pycache__/search_and_scrape.cpython-310.pyc DELETED
Binary file (1.87 kB)
 
pipeline/answer_generator.py DELETED
@@ -1,141 +0,0 @@
1
-
2
- import streamlit as st
3
- import google.generativeai as genai
4
- from collections import defaultdict
5
- import math
6
-
7
- def score_documents_with_gemini(docs, user_query):
8
- model = genai.GenerativeModel("gemini-2.0-pro-exp-02-05")
9
- scored_docs = []
10
-
11
- for i, doc in enumerate(docs):
12
- url = doc.metadata.get("url", "No URL")
13
- snippet = doc.page_content[:500]
14
-
15
- prompt = f"""
16
- You are a relevance evaluator assistant.
17
-
18
- Given the user's query and a document snippet, score how relevant this document is (1 to 5 scale):
19
-
20
- User Query:
21
- \"\"\"{user_query}\"\"\"
22
-
23
- Document Snippet:
24
- \"\"\"{snippet}\"\"\"
25
-
26
- Return a single number (1-5):
27
- """
28
- try:
29
- response = model.generate_content(prompt)
30
- score = int("".join(filter(str.isdigit, response.text.strip())))
31
- except:
32
- score = 3 # fallback
33
-
34
- scored_docs.append({
35
- "doc": doc,
36
- "url": url,
37
- "score": score
38
- })
39
-
40
- scored_docs.sort(key=lambda x: x["score"], reverse=True)
41
- return scored_docs
42
-
43
- def get_diverse_documents(scored_docs, min_required):
44
- by_url = defaultdict(list)
45
- for entry in scored_docs:
46
- by_url[entry["url"]].append(entry)
47
-
48
- diverse_docs = []
49
- for entries in by_url.values():
50
- if len(diverse_docs) >= min_required:
51
- break
52
- diverse_docs.append(entries[0]) # take top scoring for each unique URL
53
-
54
- return diverse_docs
55
-
56
- def generate_answer(user_query, retriever, scraped_results):
57
- raw_docs = retriever.get_relevant_documents(user_query)
58
- scored_docs = score_documents_with_gemini(raw_docs, user_query)
59
-
60
- min_required = max(1, int(0.7 * len(scraped_results)))
61
- selected_docs = get_diverse_documents(scored_docs, min_required=math.ceil(0.7 * len(scraped_results)))
62
-
63
-
64
- context = ""
65
- unique_sources = {}
66
- for i, entry in enumerate(selected_docs):
67
- doc = entry["doc"]
68
- url = doc.metadata.get("url", "No URL Provided")
69
- if url not in unique_sources:
70
- unique_sources[url] = f"Source {len(unique_sources) + 1}"
71
- label = unique_sources[url]
72
- context += f"[{label}] ({url}):\n{doc.page_content}\n\n"
73
-
74
- prompt = f"""
75
- You are a senior research analyst generating professional and comprehensive reports based on provided source documents.
76
-
77
- Please create a well-structured response to the user query using the information below. Your goal is to present both qualitative and quantitative data (including tables and pricing breakdowns) in clean, readable Markdown.
78
-
79
- ### Instructions:
80
- - Use markdown headings for sections.
81
- - Format numbers or pricing data in tables if applicable.
82
- - Cite facts using inline citations like [Source 1].
83
- - Use bullet points where useful.
84
- - If structured data (e.g., features, specs, pricing, tables) is mentioned in sources, render it **as a table** with proper headers.
85
- - You MUST incorporate information from **at least 3 different sources** in your response.
86
- - If some sources contain overlapping content, reference each one explicitly.
87
- - Avoid relying only on a single source unless it's the only one that contains all details.
88
- - Use inline citations like [Source 1], [Source 2], etc. after each fact or quote.
89
- - If you cannot extract anything unique from a source, say so in the "Source Coverage" section at the bottom.
90
-
91
- ### Output Format:
92
- - Clean, structured Markdown
93
- - Use headers like `## Overview`, `## Key Pricing Details`, `## Comparison`, etc.
94
- - Always include citations and distinguish when info comes from different sources.
95
-
96
- ## Source Coverage
97
- - Source 1: Used in Model Comparison and Free Usage info
98
- - Source 2: Confirmed pricing differences
99
- - Source 3: Mentioned rate limits and billing tags
100
- - Source 4: Not used due to repetition with Source 1
101
-
102
- ---
103
-
104
- ### SOURCE DOCUMENTS:
105
- {context}
106
-
107
- ---
108
-
109
- ### USER QUERY:
110
- \"\"\"{user_query}\"\"\"
111
-
112
- Please begin.
113
-
114
-
115
- """
116
-
117
- model = genai.GenerativeModel("gemini-2.0-pro-exp-02-05")
118
- response = model.generate_content(prompt)
119
- answer = response.text.strip()
120
-
121
- st.markdown("### 🧠 Answer")
122
- if any(r.get("page", 1) > 1 for r in scraped_results):
123
- st.markdown("<span style='color:orange; font-weight:bold;'>⚠️ Includes content from deeper Google search pages</span>", unsafe_allow_html=True)
124
- st.markdown(answer, unsafe_allow_html=True)
125
-
126
- # Relevance Table UI
127
- with st.expander("πŸ“Š Document Relevance Ranking"):
128
- for entry in scored_docs:
129
- url = entry["url"]
130
- score = entry["score"]
131
- label = unique_sources.get(url, "-")
132
- rating = "High" if score >= 4 else "Medium" if score == 3 else "Low"
133
- st.markdown(f"<small>πŸ”Ή **{label}** | {rating} Relevance | Score: {score}/5 β€” <a href='{url}' target='_blank'>{url}</a></small>", unsafe_allow_html=True)
134
-
135
- # Final Source List
136
- with st.expander("πŸ”— Source Citations"):
137
- if unique_sources:
138
- for url, label in unique_sources.items():
139
- st.markdown(f"<small>πŸ”Ή **{label}**: <a href='{url}' target='_blank'>{url}</a></small>", unsafe_allow_html=True)
140
- else:
141
- st.markdown("<small>No sources available.</small>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pipeline/crawler.py DELETED
@@ -1,58 +0,0 @@
1
- # pipeline/crawler.py
2
-
3
- import requests
4
- from bs4 import BeautifulSoup
5
- from urllib.parse import urljoin, urlparse
6
- from typing import List, Dict, Tuple, Set
7
- from pipeline.link_ranker import rank_links_by_query
8
-
9
- def extract_internal_links(soup: BeautifulSoup, base_url: str) -> List[str]:
10
- internal_links = []
11
- base_domain = urlparse(base_url).netloc
12
-
13
- for a in soup.find_all("a", href=True):
14
- href = a["href"]
15
- full_url = urljoin(base_url, href)
16
- parsed = urlparse(full_url)
17
-
18
- if parsed.netloc == base_domain:
19
- internal_links.append(full_url)
20
-
21
- return list(set(internal_links))
22
-
23
- def crawl_site(start_url: str, user_query: str, max_depth: int = 2, max_links: int = 5) -> List[Dict]:
24
- visited: Set[str] = set()
25
- queue: List[Tuple[str, int]] = [(start_url, 0)]
26
- crawled_pages = []
27
-
28
- while queue and len(crawled_pages) < max_links:
29
- url, depth = queue.pop(0)
30
- if url in visited or depth > max_depth:
31
- continue
32
- visited.add(url)
33
-
34
- try:
35
- response = requests.get(url, timeout=10)
36
- response.raise_for_status()
37
- html = response.text
38
- soup = BeautifulSoup(html, "html.parser")
39
- content = "\n".join(p.get_text() for p in soup.find_all("p") if p.get_text())
40
-
41
- crawled_pages.append({
42
- "url": url,
43
- "depth": depth,
44
- "content": content.strip()
45
- })
46
-
47
- if len(crawled_pages) >= max_links:
48
- break
49
-
50
- internal_links = extract_internal_links(soup, url)
51
- ranked_links = rank_links_by_query(internal_links, user_query, top_k=5)
52
- queue.extend([(link, depth + 1) for link in ranked_links if link not in visited])
53
-
54
- except Exception as e:
55
- print(f"[Crawler] Failed to crawl {url}: {e}")
56
- continue
57
-
58
- return crawled_pages
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pipeline/embed_and_store.py DELETED
@@ -1,22 +0,0 @@
1
-
2
- from langchain.schema import Document
3
- from langchain.vectorstores import Chroma
4
-
5
- def embed_and_store_chunks(all_chunks, embedding_model, persist_dir="chroma_store"):
6
- embedded_chunks = []
7
- for chunk in all_chunks:
8
- vector = embedding_model.embed_query(chunk["content"])
9
- embedded_chunks.append({
10
- "embedding": vector,
11
- "content": chunk["content"],
12
- "metadata": chunk["metadata"]
13
- })
14
-
15
- documents = [Document(page_content=chunk["content"], metadata=chunk["metadata"]) for chunk in embedded_chunks]
16
- chroma_store = Chroma.from_documents(
17
- documents=documents,
18
- embedding=embedding_model,
19
- persist_directory=persist_dir
20
- )
21
- chroma_store.persist()
22
- return chroma_store
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pipeline/link_ranker.py DELETED
@@ -1,32 +0,0 @@
1
- # pipeline/link_ranker.py
2
-
3
- from typing import List
4
- from sklearn.feature_extraction.text import TfidfVectorizer
5
- from sklearn.metrics.pairwise import cosine_similarity
6
-
7
- def rank_links_by_query(links: List[str], query: str, top_k: int = 5) -> List[str]:
8
- """
9
- Rank internal links based on relevance to the query using TF-IDF cosine similarity.
10
-
11
- Args:
12
- links (List[str]): Anchor texts or hrefs to rank.
13
- query (str): User's question or topic.
14
- top_k (int): Number of top links to return.
15
-
16
- Returns:
17
- List[str]: Ranked list of links most relevant to the query.
18
- """
19
- if not links:
20
- return []
21
-
22
- try:
23
- vectorizer = TfidfVectorizer().fit([query] + links)
24
- vectors = vectorizer.transform([query] + links)
25
- query_vec = vectors[0]
26
- link_vecs = vectors[1:]
27
- scores = cosine_similarity(query_vec, link_vecs).flatten()
28
- ranked_links = [link for _, link in sorted(zip(scores, links), reverse=True)]
29
- return ranked_links[:top_k]
30
- except Exception as e:
31
- print(f"[LinkRanker] Failed to rank links: {e}")
32
- return links[:top_k]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pipeline/query_handler.py DELETED
@@ -1,8 +0,0 @@
1
-
2
- from agent.query_analyzer import QueryAnalyzer
3
-
4
- def analyze_query(user_query: str):
5
- analyzer = QueryAnalyzer()
6
- metadata = analyzer.analyze_query(user_query)
7
- keyword_chunks = metadata.get("KeywordChunks", [[user_query]])
8
- return keyword_chunks
 
 
 
 
 
 
 
 
 
pipeline/search_and_scrape.py DELETED
@@ -1,58 +0,0 @@
1
-
2
- # pipeline/search_and_scrape.py
3
-
4
- import streamlit as st
5
- from urllib.parse import urlparse
6
- from pipeline.crawler import crawl_site
7
-
8
- def search_and_scrape(keyword_chunks, search_tool, scraper, chunker, user_query, max_links=4, max_pages=3, max_crawl_depth=2, max_crawl_pages=3):
9
- st.sidebar.markdown("### πŸ”— Scraped Sources")
10
- scraped_results = []
11
- all_chunks = []
12
-
13
- for chunk in keyword_chunks:
14
- if len(scraped_results) >= max_links:
15
- break
16
-
17
- query = " ".join(chunk)
18
- chunk_results = search_tool.search(query, num_results=10, max_pages=max_pages)
19
-
20
- for result in chunk_results:
21
- if len(scraped_results) >= max_links:
22
- break
23
-
24
- # Check if it's a homepage-style URL
25
- parsed = urlparse(result["link"])
26
- if parsed.path in ["", "/", "/index.html", "/home"]:
27
- try:
28
- crawled_pages = crawl_site(result["link"], user_query, max_depth=max_crawl_depth, max_links=max_crawl_pages)
29
- for page in crawled_pages:
30
- if len(scraped_results) >= max_links:
31
- break
32
- doc_chunks = chunker.chunk_text(page["content"], {"url": page["url"], "title": f"Crawled from {result['link']}"})
33
- all_chunks.extend(doc_chunks)
34
- scraped_results.append({"title": f"Crawled from {result['link']}", "link": page["url"], "page": result.get("page", 1)})
35
- st.sidebar.markdown(f"<span style='color:green'>🌐 Crawled</span> πŸ”Ή <a href='{page['url']}' target='_blank'>{page['url']}</a>", unsafe_allow_html=True)
36
- except Exception as e:
37
- st.sidebar.warning(f"Failed to crawl {result['link']} β€” {e}")
38
- continue
39
-
40
- # Standard page scraping
41
- scraped = scraper.scrape(result["link"])
42
- if scraped["content"]:
43
- doc_chunks = chunker.chunk_text(scraped["content"], {
44
- "url": result["link"],
45
- "title": result["title"]
46
- })
47
- all_chunks.extend(doc_chunks)
48
- scraped_results.append(result)
49
-
50
- page_info = result.get("page", 1)
51
- if page_info > 1:
52
- st.sidebar.markdown(
53
- f"<span style='color:orange'>πŸ“„ Page {page_info}</span> πŸ”Ή <a href='{result['link']}' target='_blank'>{result['title']}</a>",
54
- unsafe_allow_html=True)
55
- else:
56
- st.sidebar.markdown(f"πŸ”Ή [Page {page_info}] [{result['title']}]({result['link']})")
57
-
58
- return scraped_results, all_chunks