RAG - Qdrant
Features
Getting StartedIntroduction
Vector databases are a relatively new way for interacting with abstract data representations derived from opaque machine learning models such as deep learning architectures.
These representations are often called vectors or embeddings and they are a compressed version of the data used to train a machine learning model to accomplish a task like sentiment analysis, speech recognition, object detection, and many others.
What is Qdrant?
Qdrant “is a vector similarity sear ...
Python - Debug + Profile
pdb
pdb 是 Python 自带的调试库,为 Python 程序提供交互式的源代码调试功能,是命令行版本的 IDE 断点调试器
Instruction
Desc
p
print
n
next - step over
l
list - show source code context
s
step into
r
stop out - 继续执行,直到当前函数完成后返回
`b [ ([filename:]lineno
function) [, condition] ]`
c
continue - 一直执行程序,直到遇到下一个断点
step into - --Call-- + --Return--
cProfile
瓶颈在于 fib 函数
Item
Desc
ncalls
相应代码/函数被调用的次数
tottime
相应代码/函数总共执行所需的时间(不包括它调用其它代码/函数的执行时间)
tottime percall
tottime / ncalls
cumtime
相应代 ...
Python - With
场景
资源是有限的,使用过后需要释放,否则会造成资源泄露
File123for x in range(10_000_000): f = open('test.txt', 'w') # OSError: [Errno 24] Too many open files f.write('hello')
context manager 帮助自动分配并释放资源 - with 语句
123for x in range(10_000_000): with open('test.txt', 'w') as f: # This will open and close the file 10_000_000 times f.write('hello')
try - finally
12345f = open('test.txt', 'w')try: f.write('hello')finall ...
Python - GC
计数引用
Python 中一切皆对象,变量的本质是对像的指针
当一个对象的引用计数(指针数)为 0 时,说明该对象不可达,成为垃圾,需要被回收
调用函数 func(),创建列表 a 后,内存占用迅速增加,在函数调用结束后,内存恢复正常
函数内部声明的列表 a 是局部变量,在函数返回后,局部变量的引用会被注销
列表 a 所指向的对象的引用数为 0,Python 会执行 GC,回收内存
全局变量 - global
将生成的列表返回,在主程序中接收
内部实现1234567891011121314import sysa = []print(sys.getrefcount(a)) # 2 = a + getrefcountdef func(a): print(sys.getrefcount(a)) # 4 = a + getrefcount + func call stack + func argsfunc(a)print(sys.getrefcount(a)) # 2 = a + getrefcount
sys.getrefcount 本身也会引入一次计数
在函数调用发生的 ...
Python - GIL
Cpu bound
单线程 - 2.555494917
12345678910111213import timedef CountDown(n): while n > 0: n -= 1start = time.perf_counter()n = 100_000_000CountDown(n)end = time.perf_counter()print(f"Time elapsed: {end - start} seconds") # Time elapsed: 2.555494917 seconds
多线程 - 2.477930167
123456789101112131415161718192021import timefrom threading import Threaddef CountDown(n): while n > 0: n -= 1start = time.perf_counter()n = 100_000_000t1 = Thread(target=CountDown, args=[ ...
Python - Async IO
线程局限
多线程在运行过程中容易被打断,有可能会出现 race condition 的情况
线程切换本身存在开销,不能无限增加线程数
Sync vs Async
Sync - 操作顺序执行,前面阻塞后面
Async - 不同操作间可以交替执行,如果其中一个操作被阻塞了,程序不会等待,而是会找出可执行的操作继续执行
原理
CSP - Communicating sequential processes
asyncio 与 Python 程序一样,都是单线程的
asyncio 只有一个主线程,但可以进行多个不同的任务(特殊的 Future 对象),这些不同的任务被 Event loop 控制
假设任务只有两个状态 - 预备状态 / 等待状态
预备状态 - 任务目前空闲,随时准备运行
等待状态 - 任务已经运行,但在等待外部操作完成(如 IO)
Event loop 维护两个任务列表,分别对应预备状态和等待状态
选取预备状态的一个任务(与任务的等待时长、占用资源等相关),使其运行,直到该任务将控制权交还给 Event loop 为止
当任务将控制权交还给 Event loop 时,Even ...
Python - Futures
并行 vs 并发
并发(Concurrency) - 在某个特定的时刻,只允许有一个操作发生,线程和任务之间会相互切换,交替运行
并行(Parallelism) - 在同一时刻,有多个操作同时进行
Python 中有两种并发形式 - threading + asyncio
threading
操作系统知道每个线程的所有信息,在适当的时候做线程切换
优点 - 代码易于编写,程序员不需要做任何切换操作
缺点 - 容易出现 race condition
asyncio
主程序想要切换任务时,必须得到此任务可以切换的通知
避免了 race condition 的情况
场景
并发通常用于 IO 密集的场景 - Web 应用
并行通常用于 CPU 密集的场景 - MapReduce
线程池 vs 进程池
大部分时间是浪费在 IO 等待上
多线程(并发) - 16.8s -> 3.5s
12with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: executor.map(downloa ...
Python - Coroutine
基础
协程是实现并发编程的一种方式
多线程/多进程模型,是解决并发问题的经典模式
C10K - 线程/进程上下文切换占用大量资源
Nginx Event loop
启动一个统一的调度器,让调度器来决定一个时刻去运行哪个任务
节省了多线程中启动线程、管理线程、同步锁等各种开销
相比于 Apache,用更低的资源支持更多的并发连接
Callback hell - JavaScript
继承了 Event loop 的优越性,同时还提供 async / await 语法糖,解决了执行性和可读性共存的难题
协程开始崭露头角,尝试使用 Node.js 实现后端
Python 3.7 提供基于 asyncio 的 async / await 方法
同步
简单实现
12345678910111213141516import timedef crawl_page(url): print('crawling {}'.format(url)) sleep_time = int(url.split('_ ...
Python - Iterator + Generator
迭代器
Python 中一切皆对象,对象的抽象就是类,对象的集合为容器(列表、元组、字典、集合)
所有的容器都是可迭代的(iterable)
迭代器(iterator)提供了一个 next 的方法
得到容器的下一个对象,或者得到一个 StopIteration 的错误
可迭代对象,通过 iter() 函数返回一个迭代器(iterator),再通过 next() 函数实现遍历
for in 语句隐式化了该迭代过程
判断一个对象是否可迭代 - iter(obj) 或者 isinstance(obj, Iterable)
1234567891011121314151617181920212223from typing import Iterabledef is_iterable(param): try: iter(param) return True except TypeError: return Falseparams = [ 1234, # False '1234', # True [1, 2, ...
Python - Metaclass
超越变形
YAMLObject 的一个超越变形能力,即的任意子类支持序列化和反序列化
123456789101112131415161718192021222324252627282930import yamlclass Monster(yaml.YAMLObject): yaml_tag = u'!Monster' def __init__(self, name, hp, ac, attacks): self.name = name self.hp = hp self.ac = ac self.attacks = attacks def __repr__(self): return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % ( self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)yaml.load("&q ...