feat(rag): show cited sources and exit cleanly on interrupt/errors
- After a synthesized answer, print a legend mapping the [n] tags the model actually cited to their source files (on stderr, so piping the answer stays clean). Only cited tags are listed, not every retrieved chunk. - Catch KeyboardInterrupt/BrokenPipeError for a quiet abort and collapse other exceptions to a one-line message; set RAG_DEBUG=1 for the full traceback.
This commit is contained in:
parent
89c82cf804
commit
2b1bba0703
1 changed files with 24 additions and 1 deletions
|
|
@ -16,6 +16,7 @@ writers.writePython3Bin "rag"
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from openai import OpenAI
|
from openai import OpenAI
|
||||||
|
|
@ -128,12 +129,24 @@ writers.writePython3Bin "rag"
|
||||||
{"role": "user", "content": f"Context:\n{context}\n\nQuestion: {args.text}"},
|
{"role": "user", "content": f"Context:\n{context}\n\nQuestion: {args.text}"},
|
||||||
]
|
]
|
||||||
stream = client.chat.completions.create(model=CHAT_MODEL, messages=messages, stream=True)
|
stream = client.chat.completions.create(model=CHAT_MODEL, messages=messages, stream=True)
|
||||||
|
answer = []
|
||||||
for ev in stream:
|
for ev in stream:
|
||||||
delta = ev.choices[0].delta.content
|
delta = ev.choices[0].delta.content
|
||||||
if delta:
|
if delta:
|
||||||
|
answer.append(delta)
|
||||||
sys.stdout.write(delta)
|
sys.stdout.write(delta)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
# Legend for only the [n] tags actually cited (stderr keeps stdout pipe-clean).
|
||||||
|
cited = sorted({int(n) for n in re.findall(r"\[(\d+)\]", "".join(answer))})
|
||||||
|
cited = [i for i in cited if 1 <= i <= len(hits)]
|
||||||
|
if cited:
|
||||||
|
print("\nQuellen:", file=sys.stderr)
|
||||||
|
for i in cited:
|
||||||
|
h = hits[i - 1]
|
||||||
|
src = h.payload.get("source", "?")
|
||||||
|
chunk = h.payload.get("chunk", "?")
|
||||||
|
print(f" [{i}] {src}#{chunk} ({h.score:.3f})", file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -157,5 +170,15 @@ writers.writePython3Bin "rag"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
try:
|
||||||
|
main()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit(130)
|
||||||
|
except BrokenPipeError:
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
if os.environ.get("RAG_DEBUG"):
|
||||||
|
raise
|
||||||
|
print(f"rag: {type(e).__name__}: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
''
|
''
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue