Thamaraikannan commited on
Commit
8d75571
·
verified ·
1 Parent(s): 04fc0fb

Update src/llm.py

Browse files
Files changed (1) hide show
  1. src/llm.py +124 -108
src/llm.py CHANGED
@@ -1,108 +1,124 @@
1
- import streamlit as st
2
- import google.generativeai as genai
3
- import requests
4
- from PIL import Image
5
- import io
6
- import base64
7
-
8
- genai.configure(api_key="AIzaSyAjz4MluTeLnMogaO5wY8B2UAxWK1RaYHE")
9
- client = genai.GenerativeModel("gemini-2.5-flash")
10
-
11
-
12
- def fetch_image_as_pil(image_url):
13
- try:
14
- response = requests.get(image_url, timeout=10)
15
- response.raise_for_status()
16
- return Image.open(io.BytesIO(response.content))
17
- except Exception as e:
18
- st.warning(f"Failed to fetch image from {image_url}: {e}")
19
- return None
20
-
21
- def analyze_image_with_query(relevant_docs, query):
22
- try:
23
- if not relevant_docs or len(relevant_docs) == 0:
24
- st.warning("⚠️ No relevant documents found for analysis.")
25
- return "No relevant images found to analyze."
26
-
27
- # Collect images and context
28
- image_parts = []
29
- context_texts = []
30
-
31
- for i, doc in enumerate(relevant_docs[:5], 1): # top_k = 5
32
- metadata = doc.get("metadata", {})
33
- image_url = metadata.get("image_url")
34
- company = metadata.get("company", "Unknown")
35
- fiscal_year = metadata.get("fiscal_year", "Unknown")
36
- page_number = metadata.get("page_number", "Unknown")
37
-
38
- if image_url:
39
- pil_image = fetch_image_as_pil(image_url)
40
- if pil_image:
41
- image_parts.append(pil_image)
42
- context_texts.append(f"[DOC {i}] {company} ({fiscal_year}) - Page {page_number}")
43
-
44
- if not image_parts:
45
- st.warning("⚠️ No images could be loaded from the retrieved documents.")
46
- return "No images found to analyze."
47
-
48
- context_info = "\n".join(context_texts)
49
-
50
- st.info(f"Analyzing {len(image_parts)} images using Gemini...")
51
-
52
- # Build structured content with roles
53
- contents = [
54
- {
55
- "role": "model",
56
- "parts": [
57
- {
58
- "text": (
59
- """You are a professional assistant that answers user questions based **only on the content of provided document excerpts**. The user will ask a question, and you will also receive related text chunks retrieved from company documents or PDFs.
60
- Instructions:
61
- 1. Use **only** the retrieved chunks to answer the user’s question. Do **not** add information from memory or outside sources.
62
- 2. If multiple chunks provide relevant info, combine them into a **clear, concise answer**.
63
- 3. If the answer is **not found** in the chunks, respond exactly with: "The document does not provide enough information to answer this question."
64
- 4. Keep the style **professional, factual, and concise**.
65
- 5. retrun the response as markdown format
66
- 7. Refuse to answer or speculate if no reliable evidence is found in the chunks."""
67
- )
68
- }
69
- ]
70
- },
71
- {
72
- "role": "user",
73
- "parts": [
74
- {
75
- "text": (f"""
76
- You will answer the question using ONLY the provided document excerpts.
77
- When you use information from a document, cite it with the format [DOC i],
78
- where i corresponds to the document number given in CONTEXT DOCUMENTS.
79
- If multiple docs are relevant, cite all of them (e.g., [DOC 1][DOC 3]).
80
- Context documents:\n{context_info}\n\n
81
- Question: {query}"""
82
- )
83
- }
84
- ]
85
- }
86
- ]
87
-
88
- def pil_image_to_blob(pil_image):
89
- """Convert PIL image to base64 blob for Gemini."""
90
- import io
91
- buf = io.BytesIO()
92
- pil_image.save(buf, format="PNG")
93
- byte_data = buf.getvalue()
94
- b64_data = base64.b64encode(byte_data).decode("utf-8")
95
- return {"mime_type": "image/png", "data": b64_data}
96
-
97
- # Append all images properly
98
- for pil_image in image_parts:
99
- contents[1]["parts"].append(pil_image_to_blob(pil_image))
100
-
101
- # Send request to Gemini
102
- response = client.generate_content(contents)
103
-
104
- return response.text.strip() if response and hasattr(response, "text") else "No response received."
105
-
106
- except Exception as e:
107
- st.error(f"Gemini analysis error: {e}")
108
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from groq import Groq
3
+ import requests
4
+ from PIL import Image
5
+ import io
6
+ import base64
7
+
8
+ # Initialize Groq client
9
+ groq_client = Groq(api_key="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")
10
+
11
+ def fetch_image_as_pil(image_url):
12
+ try:
13
+ response = requests.get(image_url, timeout=10)
14
+ response.raise_for_status()
15
+ return Image.open(io.BytesIO(response.content))
16
+ except Exception as e:
17
+ st.warning(f"Failed to fetch image from {image_url}: {e}")
18
+ return None
19
+
20
+
21
+ def pil_image_to_data_url(pil_image):
22
+ """Convert PIL image to base64 data URL for Groq."""
23
+ buf = io.BytesIO()
24
+ pil_image.save(buf, format="PNG")
25
+ byte_data = buf.getvalue()
26
+ b64_data = base64.b64encode(byte_data).decode("utf-8")
27
+ return f"data:image/png;base64,{b64_data}"
28
+
29
+
30
+ def analyze_image_with_query(relevant_docs, query):
31
+ try:
32
+ if not relevant_docs or len(relevant_docs) == 0:
33
+ st.warning("⚠️ No relevant documents found for analysis.")
34
+ return "No relevant images found to analyze."
35
+
36
+ # Collect images and context
37
+ image_data_urls = []
38
+ context_texts = []
39
+
40
+ for i, doc in enumerate(relevant_docs[:5], 1): # top_k = 5
41
+ metadata = doc.get("metadata", {})
42
+ image_url = metadata.get("image_url")
43
+ company = metadata.get("company", "Unknown")
44
+ fiscal_year = metadata.get("fiscal_year", "Unknown")
45
+ page_number = metadata.get("page_number", "Unknown")
46
+
47
+ if image_url:
48
+ pil_image = fetch_image_as_pil(image_url)
49
+ if pil_image:
50
+ image_data_urls.append(pil_image_to_data_url(pil_image))
51
+ context_texts.append(f"[DOC {i}] {company} ({fiscal_year}) - Page {page_number}")
52
+
53
+ if not image_data_urls:
54
+ st.warning("⚠️ No images could be loaded from the retrieved documents.")
55
+ return "No images found to analyze."
56
+
57
+ context_info = "\n".join(context_texts)
58
+
59
+ st.info(f"Analyzing {len(image_data_urls)} images using Groq...")
60
+
61
+ # Build the system prompt
62
+ system_prompt = """You are a professional assistant that answers user questions based **only on the content of provided document excerpts**. The user will ask a question, and you will also receive related text chunks retrieved from company documents or PDFs.
63
+
64
+ Instructions:
65
+ 1. Use **only** the retrieved chunks to answer the user's question. Do **not** add information from memory or outside sources.
66
+ 2. If multiple chunks provide relevant info, combine them into a **clear, concise answer**.
67
+ 3. If the answer is **not found** in the chunks, respond exactly with: "The document does not provide enough information to answer this question."
68
+ 4. Keep the style **professional, factual, and concise**.
69
+ 5. Return the response as markdown format.
70
+ 6. Refuse to answer or speculate if no reliable evidence is found in the chunks."""
71
+
72
+ # Build user message with images
73
+ user_content = [
74
+ {
75
+ "type": "text",
76
+ "text": f"""You will answer the question using ONLY the provided document excerpts.
77
+ When you use information from a document, cite it with the format [DOC i],
78
+ where i corresponds to the document number given in CONTEXT DOCUMENTS.
79
+ If multiple docs are relevant, cite all of them (e.g., [DOC 1][DOC 3]).
80
+
81
+ Context documents:
82
+ {context_info}
83
+
84
+ Question: {query}"""
85
+ }
86
+ ]
87
+
88
+ # Add all images to the user message
89
+ for image_url in image_data_urls:
90
+ user_content.append({
91
+ "type": "image_url",
92
+ "image_url": {
93
+ "url": image_url
94
+ }
95
+ })
96
+
97
+ # Create messages for Groq
98
+ messages = [
99
+ {
100
+ "role": "system",
101
+ "content": system_prompt
102
+ },
103
+ {
104
+ "role": "user",
105
+ "content": user_content
106
+ }
107
+ ]
108
+
109
+ # Send request to Groq
110
+ completion = groq_client.chat.completions.create(
111
+ model="meta-llama/llama-4-scout-17b-16e-instruct",
112
+ messages=messages,
113
+ temperature=0.3,
114
+ max_completion_tokens=2048,
115
+ top_p=1,
116
+ stream=False
117
+ )
118
+
119
+ response_text = completion.choices[0].message.content
120
+ return response_text.strip() if response_text else "No response received."
121
+
122
+ except Exception as e:
123
+ st.error(f"Groq analysis error: {e}")
124
+ return None