Diese Seite zeigt kurze python-snippets zu verschiedenen Themen.
Die Beispiele wenden sich an Einsteiger im Bereich python.
KI-Textsuche mit haystack
Diese Variante der haystack-Nutzung basiert darauf, aus den zu untersuchenden Text-Dokumenten tags zu erzeugen und haystack zu dem Dokument dazu zu geben.
Damit liesse sich auch ohne KI eine Bewertung erbringen - tags in der taglist jedes Dokument suchen - Anzahl der Treffer nach Dokumenten sortieren - fertig.
Der grosse benefit an haystack ist hier die Möglichkeit der Freitext-Suche.
Zum Abschluss zeigt haystack das Ranking der Dokumente mitsamt prozentualer Treffer-Quote an.
Was jetzt noch fehlt, ist eine Liste der Treffer pro Dokument in geöffnetemDokumenten-Brwoser...
from sentence_transformers import SentenceTransformer, util
import os
import re
import glob
from datetime import date, timedelta, datetime
from datasets import load_dataset
from haystack import Document
# ------------------------------------------------------------------------------
# Modell laden (KI-Kern)
model = SentenceTransformer('all-MiniLM-L6-v2')
def search_documents(query, docs):
# Hashtags extrahieren & Einbettungen berechnen
doc_embeddings = model.encode(docs)
query_embedding = model.encode(query)
# Semantische Ähnlichkeit berechnen
hits = util.semantic_search(query_embedding, doc_embeddings)[0]
print(f"Suche nach: {query}")
for hit in hits:
doc_text = docs[hit['corpus_id']]
hashtags = re.findall(r"#\w+", doc_text)
score = round(hit['score'] * 100, 2)
tags = ', '.join(hashtags)[0:128]
print(f"[{score}%] {doc_text.split(" ")[0]}")
print()
# ------------------------------------------------------------------------------
# get the Text from file
def getText(path):
rc = ""
lines = ""
with open(path, "r") as f:
lines = f.readlines()
for line in lines:
rc += str(line)
return rc
# make a tag of each nome
def convert(zk):
s = zk.group(1)
if s is not None:
if len(s) >= 3:
tags = str('#' + s.replace(" *", ""))
tags = re.sub(r'[0-9]+', '', tags)
for tag in tags.split("\n"):
tagmap[tag] = None
return tags
return ""
# ------------------------------------------------------------------------------
def readDataBasis(pattern, tool):
for filename in glob.iglob("./docs/" + pattern):
cmd = tool + " " + filename
subprocess = os.popen(cmd)
result = subprocess.read()
fileset = {}
# read the resulting ".txt" files, which are the retrievable datasource
def readFileset():
for filename in glob.iglob("./docs/*.txt"):
fileset[filename] = {}
# ------------------------------------------------------------------------------
if __name__ == "__main__":
t0 = datetime.now()
readDataBasis("*.pdf", "pdftotext")
readDataBasis("*.doc", "docx2txt")
readDataBasis("*.docx", "docx2txt")
dokumente = []
readFileset()
for file in fileset.keys():
print("inspect ", file)
doc_text = getText(file)
taglist = []
tagmap = {}
tags_str = ""
doc_tags = re.sub(r"([A-Z]+)|([a-z]+)", convert, doc_text)
for tag in tagmap.keys():
tags_str += str(tag + " ")
fileset[file] = str(file + " " + doc_text + " " + tags_str)
dokumente.append(fileset[file])
t1 = datetime.now()
delta_t_docread = t1 - t0
print("delta_t_docread =", delta_t_docread)
t2 = datetime.now()
# Aufruf, mit Suchwortern und Datenbasis
print()
search_documents("SIP set_trace RAL NAL refresh Kommando", dokumente)
t3 = datetime.now()
delta_t_haystack = t3 - t2
print("delta_t_haystack =", delta_t_haystack)
#!/usr/bin/env python3
import sys
# binary search of a given number in range(0..1000)
# the number of tries is limited to O(log n)
def newTp(ug, og):
return int((ug + og) / 2)
while True:
xi = input("Zahl (0..999)? ")
if xi == 'q':
sys.exit(0)
x = int(xi)
if x < 0 or x > 999:
print("Zahl ungültig.")
continue
ug = 0
og = 1000
tp = newTp(ug, og)
n = 0
while True:
n += 1
if n > 33:
break
if tp == x:
print("%d.-Versuch, ug=%d, tp=%d, og=%d, Bingo, die Zahl ist %d" %(n, ug, tp, og, tp))
break
elif x < tp:
print("%d.-Versuch, ug=%d, tp=%d, og=%d, die Zahl ist kleiner als %d" %(n, ug, tp, og, tp))
og = tp
tp = newTp(ug, og)
elif x > tp:
print("%d.-Versuch, ug=%d, tp=%d, og=%d, die Zahl ist größer als %d" %(n, ug, tp, og, tp))
ug = tp
tp = newTp(ug, og)
python$ ./binary.py
Zahl (0..999)? 246
1.-Versuch, ug=0, tp=500, og=1000, die Zahl ist kleiner als 500
2.-Versuch, ug=0, tp=250, og=500, die Zahl ist kleiner als 250
3.-Versuch, ug=0, tp=125, og=250, die Zahl ist größer als 125
4.-Versuch, ug=125, tp=187, og=250, die Zahl ist größer als 187
5.-Versuch, ug=187, tp=218, og=250, die Zahl ist größer als 218
6.-Versuch, ug=218, tp=234, og=250, die Zahl ist größer als 234
7.-Versuch, ug=234, tp=242, og=250, die Zahl ist größer als 242
8.-Versuch, ug=242, tp=246, og=250, Bingo, die Zahl ist 246
Fibonacci Zahlen
#!/usr/bin/env python3
import sys
# fib.py: calculate the fibonacci number of n, which may be given as first arg.
# if n is not given, the literal default is 7.
# if a second arg is given, the output gets a bid verbose
n = 7
if len(sys.argv) > 1:
n = int(sys.argv[1])
results = {}
calls = 0
def fib(n):
global calls
calls += 1
if n == 0:
return 0
elif n == 1 or n == 2:
return 1
fib_n = fib(n - 1) + fib(n - 2)
global results
results[n] = fib_n
return fib_n
if __name__ == "__main__":
print("fib (%d) = %d, #calls = %d" % (n, fib(n), calls))
if len(sys.argv) > 2:
print()
print("fib (1) = 1")
print("fib (2) = 1")
for i in sorted(results):
print("fib (%d) = %d" % (i, results[i]))
Aufruf: python3 fib.py 14 v
Berechnet die Fibonacci-Zahl von 14, ist wg. zweitem Argument etwas schwatzhaft.
Bei der rekursiven Lösung zeigt sich gleich der gigantische Aufwand an Funktionsaufrufen. Hier bleibt einiges an Optiomierungs-Potential.
(Zum Bsp. durch ietrativer statt rekursiver Berechnung der Fibonaccis.)