Repository navigation
Expand file tree
/
Copy pathgenerate.py
More file actions
90 lines (66 loc) · 2.11 KB
/
Copy pathgenerate.py
File metadata and controls
90 lines (66 loc) · 2.11 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
from openai import OpenAI
from dotenv import load_dotenv
import tiktoken
import os
load_dotenv()
client = OpenAI(api_key = os.getenv("OPENAI_API_KEY"))
GENERATION_MODEL = os.getenv("GENERATION_MODEL", "gpt-4o-mini")
TOKEN_BUDGET = int(os.getenv("TOKEN_BUDGET", "2000"))
NO_ANSWER_PHRASE = "I don't know based on the provided documents."
_PROMPTS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "prompts")
def _load_prompt(filename: str) -> str:
path = os.path.join(_PROMPTS_DIR, filename)
with open(path) as f:
return f.read().strip()
_SYSTEM_PROMPT = _load_prompt("system_prompt.txt")
def _count_tokens(text: str) -> int:
enc = tiktoken.get_encoding("cl100k_base")
return len(enc.encode(text))
def _select_chunks_within_budget(chunks: list[dict], budget: int) -> list[dict]:
selected = []
tokens_used = 0
for chunk in chunks:
chunk_tokens = _count_tokens(chunk["text"])
if tokens_used + chunk_tokens > budget:
continue
selected.append(chunk)
tokens_used += chunk_tokens
return selected
def _build_context_block(chunks: list[dict]) -> str:
lines = []
for i, chunk in enumerate(chunks, start = 1):
lines.append(f"[{i}] Source: {chunk['source']} (chunk {chunk['chunk_index']})")
lines.append(chunk["text"])
lines.append("")
return "\n".join(lines)
def generate_answer(question: str, chunks: list[dict]) -> dict:
selected_chunks = _select_chunks_within_budget(chunks, TOKEN_BUDGET)
if not selected_chunks:
return {
"answer": NO_ANSWER_PHRASE,
"sources": []
}
context_block = _build_context_block(selected_chunks)
user_message = f"Context:\n{context_block}\nQuestion: {question}"
response = client.chat.completions.create(
model = GENERATION_MODEL,
messages = [
{"role": "system", "content": _SYSTEM_PROMPT},
{"role": "user", "content": user_message}
],
temperature = 0.0
)
answer = response.choices[0].message.content.strip()
sources = [
{
"index": i + 1,
"source": chunk["source"],
"chunk_index": chunk["chunk_index"],
"text": chunk["text"]
}
for i, chunk in enumerate(selected_chunks)
]
return {
"answer": answer,
"sources": sources
}