-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanswer_generator.py
More file actions
97 lines (74 loc) · 3.29 KB
/
Copy pathanswer_generator.py
File metadata and controls
97 lines (74 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import requests
import json
def ans_gen(query, results):
#STEP1:Extract Retrieved Context
retrieved_chunks=[]
if not results:
raise ValueError("No documents retrieved for the query")
for idx, doc in enumerate(results):
retrieved_chunks.append({
"chunk_id":f"C{idx+1}",
"text":doc.page_content.strip()
})
#STEP2:Build Prompt
def build_prompt(query, chunks):
context_block=""
for chunk in chunks:
context_block+=f"[{chunk['chunk_id']}]\n{chunk['text']}\n\n"
prompt=f"""
You are an assistant answering a question using ONLY the provided text snippets.
Question:
{query}
Retrieved Text Chunks:
{context_block}
Instructions:
1. Synthesize the answer by combining information across all retrieved text snippets.
2. Before writing the paragraph, identify all major themes present in the retrieved text (e.g., causes, impacts, regions, time scales), and ensure the paragraph covers as many of these themes as possible.
3. Write a single, well-structured paragraph of upto 300 words(if sufficient information is available) answering the question. The paragraph must be fully based on the retrieved text only.
4. Write a single coherent paragraph. The answer should be upto 7-10 sentences if sufficient information is available.
5. Do not include external knowledge.
6. If the answer is not present, say "The retrieved text does not contain sufficient information."
7. Output STRICT JSON only. Do NOT include explanations or extra text.
Output Format (STRICT JSON):
{{
"answer": "...",
"supporting_chunks": ["C1", "C2"]
}}
"""
return prompt
#STEP3:Call LLaMA-3 via Ollama
OLLAMA_URL="http://localhost:11434/api/generate"
prompt = build_prompt(query, retrieved_chunks)
payload={
"model":"llama3:8b",
"prompt":prompt,
"stream":False,
"options":{
"temperature":0.0,
"num_predict":1000
}
}
response=requests.post(OLLAMA_URL,json=payload, timeout=120)
if response.status_code!=200:
raise RuntimeError("Ollama request failed")
response_json=response.json()
if "response" not in response_json:
raise RuntimeError("Ollama response missing 'response' field")
raw_output=response_json["response"]
#STEP4:Parse & Validate Output
try:
parsed_output=json.loads(raw_output)
except json.JSONDecodeError:
raise ValueError("LLM output is not a valid JSON")
answer=parsed_output.get("answer", "No answer generated.").strip()
supporting_chunks=parsed_output.get("supporting_chunks",[])
if not answer:
raise ValueError("Empty answer generated by LLM")
if not isinstance(supporting_chunks, list):
raise ValueError("supporting_chunks must be a list")
valid_ids={c["chunk_id"] for c in retrieved_chunks}
# if answer and not any(cid in valid_ids for cid in supporting_chunks):
# raise ValueError("Answer generated without valid supporting evidence")
print("\nFinal Answer : \n")
print(answer)
return