ToCode
Open in Telegram
××פ×× ×§×¦×Ø×× ×××Ŗ×× ×Ŗ×× ×××Ŗ ×× ×× ×¤×Ø×§
Show more1 429
Subscribers
+124 hours
-17 days
+430 days
Data loading in progress...
Similar Channels
Tags Cloud
Incoming and Outgoing Mentions
---
---
---
---
---
---
Attracting Subscribers
August '26
August '26
+27
in 0 channels
July '26
+35
in 0 channels
Get PRO
June '26
+10
in 0 channels
Get PRO
May '26
+8
in 0 channels
Get PRO
April '26
+8
in 0 channels
Get PRO
March '26
+15
in 0 channels
Get PRO
February '26
+15
in 0 channels
Get PRO
January '26
+14
in 0 channels
Get PRO
December '25
+12
in 0 channels
Get PRO
November '25
+17
in 0 channels
Get PRO
October '25
+15
in 0 channels
Get PRO
September '25
+12
in 0 channels
Get PRO
August '25
+12
in 0 channels
Get PRO
July '25
+20
in 0 channels
Get PRO
June '25
+26
in 0 channels
Get PRO
May '25
+13
in 0 channels
Get PRO
April '25
+15
in 0 channels
Get PRO
March '25
+5
in 0 channels
Get PRO
February '25
+11
in 0 channels
Get PRO
January '25
+21
in 0 channels
Get PRO
December '24
+13
in 0 channels
Get PRO
November '24
+17
in 0 channels
Get PRO
October '24
+14
in 0 channels
Get PRO
September '24
+10
in 0 channels
Get PRO
August '24
+20
in 0 channels
Get PRO
July '24
+27
in 0 channels
Get PRO
June '24
+23
in 0 channels
Get PRO
May '24
+16
in 0 channels
Get PRO
April '24
+13
in 0 channels
Get PRO
March '24
+15
in 0 channels
Get PRO
February '24
+12
in 0 channels
Get PRO
January '24
+21
in 0 channels
Get PRO
December '23
+18
in 0 channels
Get PRO
November '23
+14
in 0 channels
Get PRO
October '23
+26
in 0 channels
Get PRO
September '23
+11
in 0 channels
Get PRO
August '23
+8
in 0 channels
Get PRO
July '23
+16
in 0 channels
Get PRO
June '23
+14
in 0 channels
Get PRO
May '23
+2
in 0 channels
Get PRO
April '23
+15
in 0 channels
Get PRO
March '23
+15
in 0 channels
Get PRO
February '23
+12
in 0 channels
Get PRO
January '23
+13
in 0 channels
Get PRO
December '22
+10
in 0 channels
Get PRO
November '22
+24
in 0 channels
Get PRO
October '22
+16
in 0 channels
Get PRO
September '22
+12
in 0 channels
Get PRO
August '22
+48
in 0 channels
Get PRO
July '22
+17
in 0 channels
Get PRO
June '22
+18
in 0 channels
Get PRO
May '22
+20
in 0 channels
Get PRO
April '22
+22
in 0 channels
Get PRO
March '22
+18
in 0 channels
Get PRO
February '22
+19
in 0 channels
Get PRO
January '22
+33
in 0 channels
Get PRO
December '21
+25
in 0 channels
Get PRO
November '21
+41
in 0 channels
Get PRO
October '21
+48
in 0 channels
Get PRO
September '21
+403
in 0 channels
Get PRO
August '21
+22
in 0 channels
Get PRO
July '21
+33
in 0 channels
Get PRO
June '21
+25
in 0 channels
Get PRO
May '21
+17
in 0 channels
Get PRO
April '21
+17
in 0 channels
Get PRO
March '21
+22
in 0 channels
Get PRO
February '21
+34
in 0 channels
Get PRO
January '21
+54
in 0 channels
Get PRO
December '20
+773
in 0 channels
| Date | Subscriber Growth | Mentions | Channels | |
| 26 August | +2 | |||
| 25 August | +2 | |||
| 24 August | +2 | |||
| 23 August | 0 | |||
| 22 August | 0 | |||
| 21 August | +1 | |||
| 20 August | 0 | |||
| 19 August | +1 | |||
| 18 August | 0 | |||
| 17 August | +2 | |||
| 16 August | +1 | |||
| 15 August | +1 | |||
| 14 August | 0 | |||
| 13 August | +2 | |||
| 12 August | +1 | |||
| 11 August | 0 | |||
| 10 August | +2 | |||
| 09 August | 0 | |||
| 08 August | +2 | |||
| 07 August | +2 | |||
| 06 August | +1 | |||
| 05 August | 0 | |||
| 04 August | 0 | |||
| 03 August | +1 | |||
| 02 August | +2 | |||
| 01 August | +2 |
Channel Posts
××קר ××× ×××× ×©××× ×× ××¢×××Ŗ× ×Ŗ××× ××Ŗ ××××× ×Ø×× ×××©× ××× ×ש×××¢ ×××
https://www.tocode.co.il/talking_ai
×Ŗ×§××× ×× ×××× ××”××ר ×× ××Ŗ× ×רש×××Ŗ ×××××ר
| 2 | š ×צ××Ŗ× 8 ××¢×××Ŗ
×××§×©×Ŗ× ×××”××× ××¢××ר ×¢× ××§×× ×××× ××××:
I found eight concrete cases where the uncommitted views cause redundant or oversized queries.
×××¦× ××× ×× ××¢×× ×©××××Ŗ ××× ××× ××Ŗ××Ŗ ××Ŗ ××§×× ×× ××××Ŗ××××, ××× ×× ×©××Ŗ ×× ××× ×××× ×©××Ŗ××Ŗ ××Ŗ ××§××, ×× ××× ×§××Ø× ×× ×× ××××Ŗ× ××קש ×××××§ ש×× ×× ×× ××××Ŗ× ××קש ×××××§ ×××××× ××ר××Ŗ, ××× ×× 8 ×××¢×××Ŗ ×××× ××××Ŗ×××Ŗ, ××× ×ש ××¢×××Ŗ ××ר××Ŗ ש×× ××פ××¢××Ŗ ×רש×××. ×× ××× ×©××××Ŗ הפצ×פ×××Ŗ ×¢× ×פר×××§× ××פ×צ'ר.
×××Ŗ× ×××תר ×ש××¢××Ŗ× ××× "××× ×ש ××Ø× ×©××Ŗ×××× ×××× ×××× ×××××××?" ×"××× ×××¢×××Ŗ ×××× ×××× ×ש××××Ŗ?".
×× ×ש ××Ø× ×©××Ŗ×××× ×××× ×××× ××××××× ×× ×× ×× × ×× ×¦×Ø×××× ××××× ×Ŗ×× ××Ŗ. ×הפ××§ ××××× ××××©× ××× ××Ŗ ×ש×× ×××××¤× ××××××× ××”××× ×ר×ׄ ××××רצ×× ××××ש ××Ŗ ××, ×שפר ××Ŗ ××§×× ×©× ×¢×¦×× ×¢× ×× ×§××× ×××פ××××××Ŗ. ××× ××¢× ×××ר ×¢× ×ר××××§×××Ø× ×× ××§×× ××××××Ŗ ×× ×××× × ××§×××Ŗ ××Ŗ ×××Ŗ× ××××××Ŗ ××× ××תר. ××× ××¢× ××××× ×ש××§ ×××§×” ×¢××××, ×× ×¤×Ŗ×ר, ×××× × ××××× ×ש××§ ×××§×” ×¢×××× ××× ×¦× ×Ŗ×××. ××××Ŗ× ××××¤× ×ש×× ×©×× ×××ר×× "×Ŗ×× ××Ŗ ×× ×¤×Ŗ×ר" ×× ×××× ××Ŗ×××× ×× ×©×××× × ××××× ×××Ŗ×× ×§×× ××תר ××× ××× ××× ××× ××¦× ×צ××Ø× ××××××××Ŗ ×××ר×. ×× ×× × ×× ×©× ××× ×ר××ש×× ××Ŗ ×××Ŗ×.
×××Ŗ× ××”×§× × ××Ŗ×§×××Ŗ ×× × ×§×× ×©×©××× × ×××¢×××Ŗ ש××× ××¦× ×× ×ש××××Ŗ. ש××¢×¦× ××ער××Ŗ ×Ŗ×¢××× ×××”××× ×××× ×××ש×× ××”×ר ×עצ×× ××Ŗ ××§×× ××¤× "×ר×ש××Ŗ ××צר" ××× ×××¢×××Ŗ ×××× ××××× ×××¤×Ŗ×Ø× ×שת×××¢ ×ר×שת ××צר שע×××× ×××פ××¢ ×××. ×× ×× ×§××× ××××Ŗ ×× ×× × ×× ×©×. ×××× ×× ×× × ×ש××ר ××Ŗ 8 ×××¢×××Ŗ ×××× ××§×× ×× ×פ××× ×××§ ××× ××”××× ××××©× ×××××ש ×ר×שת ×××צר ×××× ××× × ×××ׄ ×××”×Ŗ×× ×¢× ××§×× ×©××× ××Ŗ× ×××××× ×××Ŗ× ××××Ŗ× ××¢××××Ŗ ××©× ××Ŗ ××§××. ××× ××× ×× ×× × ×ר××ש×× ××Ŗ ×××Ŗ×.
פ×××Ŗ ××××× ×××צר××Ŗ ×××× ××תר ×§×× ×¢×××, ×¢× ×× ××× ×××××. ×××Ŗ×ר ××× ×× ×××צר ×§×× ×¢××× ××× ×××צר ××Ŗ ××§×× ×©××× ××Ŗ××× ××¢××× ××Ŗ××× ×××ער××Ŗ ש×× ×× × ××× ××. ××× ×× Skillset ש×× × ××× ×©×ר×× ×פת××× ×××××§× ××¤× × ×©× ×Ŗ×××. × ××× ××××× × AI ×××× ×§× ×××צר ×Ŗ××× ××× ××× ×Ŗ××× ×ר×ש ×× ××× ××× ××××× ××Ŗ ××××× × ××××××× ×××× ×Ŗ××× ××צ×ר. ××§×ר ×××Ŗ× ××Ŗ×× ××Ŗ ××× ×©×× ×©×× ×Ø×××× ××Ŗ ××Ŗ×צ×× ×©× ××§×× ××× ××Ŗ ×§×× ×××§×ר ×××× ×§×©× ×ר×××Ŗ ××× ×ש×× ××××ר ×§×× X ××× ×§×× Y.
××©× × 2026. ××× ×× × ×¢×××× ××Ŗ××××× ×× ×× ×§×× ××× ××× ×××× ×¦×Ø×× ×××. | 78 |
| 3 | https://www.tocode.co.il/blog/2026-08-found-8-problems | 69 |
| 4 | š ××× 12 - ××§××× ×פ××Ŗ×× ×”××× ×× ×©×××× ××§××Ŗ ×פר××קש×
×××Ø× 11 ×××××××Ŗ ×¢× ×”××× ×× ×× × ×Ø××¦× ××”××× ××Ŗ ××”××Ø× ××××Ŗ ×רש×××Ŗ ××פ×× ×©××××Ŗ× ××× ×××Ŗ ×”××× ×× ×××§××××Ŗ ×××¢×××Ŗ× ×פר××קש×. ×××Ŗ ×רש××× ×©××:
1. ×Ŗ×¢×× ××Ŗ ×× ×ש××××Ŗ - ×¢××× ×¢× ××××× × ×©×× ×× ×× ×הפ××§. ×× ×Ø×§ ×× ××ר×× ×¢××××× ××רת ×פר×××§×©× ××× ×©×”×¤×¦×פ××Ŗ ×”××× ×× ××××Ŗ ××××ר×× ×Ŗ×©××××Ŗ ש×× ××Ŗ ×× ×¤×¢× ×©× ×¤× × ×××××. ××§×× ×××× ×××Ŗ××× × ×¢× ××¢×× ××× ×××× ××× ×××©× ×××¤× ×××Ŗ××× ××פש ×××Ŗ×. ×ש ××× ×”××£ פ××פ×ר×××Ŗ שש××ר××Ŗ ×××”××ר×××Ŗ ש××××Ŗ ×©× ×”××× ×× ××× ××× ××¢×× ×ש××ר ××Ŗ ×× ×××××¢××Ŗ ×××”××” ×× ×Ŗ×× ×× ×צ××× ××פ××קצ××. ×× ×©×ש×× ×©××Ø× ×××©× ××× ×× ×©×§×Ø×, ×¢×× ×Ŗ×¦×ר×× ×××Ŗ×.
2. ש××× ×× ××××§× ×× - ×ש××Ŗ× ××××§×× ××Ŗ ××”××× ××Ŗ× ××××¢×× ×××××§ ×× ×××Ŗ×× ×× ××Ŗ× ××Ŗ××Ŗ× ××Ŗ ×פר××פ×. ××שת×ש×× ×©××× ×××××× ××שת×ש ×××§×”××× ×ר×× ××תר ×ר×××× ××ש××× ×©××××Ŗ ×× ×Ø×××× ××××Ŗ. ש××× ×× ×××× ××” ×× ×× ×× ×× ×©××××§×× ××× ×××§× ×× ×©××× ××”××××Ŗ ×¢××× ××× ××××× ×עצ×ר ש××××Ŗ ש×× ××××××Ŗ ×××××× ×× ×××. ×ר××§ × ×¤×ׄ ××× ××× ×× ×× ×× ×©× Guardrails ×©× ×”××× × ××”×£ ×§××Ø× ××Ŗ ×ש××× ×ש××× ××××× ×× ××× ×¤×Ø××××§×××××Ŗ ×× ×©×¢×××£ ×××Ŗ×× ×××Ŗ×.
3. ×ש×× ×¢× ××¢×××” - ש××× ×¢× ×”××× ×Ŗ×פהת Thread ×××××ר רשת ×× ××××ש×× ××××× ×תש××× ×©××××¢× × Streaming. ×× ×Ŗ×× ××Ŗ ×¢×××× ×××”××Ŗ ×××©× ×××× ×¢××× × ×××××§ ש×× ×שרשרת ×¢××××Ŗ ××× ×©×¦×Ø×× ×××Ŗ×. ש××× ×”××××Ŗ Staging ×Ŗ××××”× ××ר×× ××Ŗ×¢×××”× ××××¢××Ŗ ×¢× ×שרת ××¤× × ×©××××¢×× ××שת×ש×× ××××Ŗ××× ××× ×ר×××Ŗ ×× × ×©×ר. ××× ××ר××Ŗ ××¢× × ×ש ×××× ×¤×Ŗ×Ø×× ××Ŗ Deployment ××”××× ×× ×©××× ×××××§ ×××Ŗ× ××¤× × ×©××Ŗ× ××§×××× ×”×××× ×ש×××.
4. ×× × ×× ×× ×× × Fallback - ×× ×”××× ×¢× ××פר×××Ø× ××¢× 0 ×××× ×××××ר תש××××Ŗ ש×× ××Ŗ ××× ×פע××. ××× ×××× ×× ×××××ר תש××× ××××, ×××××ר תש××× ×××§××Ŗ ×× ×××××ר ××ש ש×××××Ŗ. × ×”× ×××××ר fallback ××××× ××ר ×× ×ש×× × ××©× ××Ŗ××× ××××× ×× ×§××Ø× ×ש××××× ××¢× × ×Ŗ×©××××Ŗ ××ר××Ŗ ××× ×©×¦×פ××Ŗ×.
5. ××צ××× ××× ×©××תר ×¢×××× ×××ׄ ××××× - ×§×× ××× ××ר×× ××”××, ×××× ××. ×× ×× × ×¦×Ø×× ×תר×× ××§×”× ××× ×× ×ר××Ø× ×× × ×¦×Ø×× ×××× ×©×¤×, ××× ×ש××× ×××ר×× ×Ø××××× ××”××£ ×× ×Ŗ××××Ŗ ש××Ø× ×× × ×× ×¦×Ø×× ×××Ŗ×. ××× ×©×Ŗ×”××Ø× ××תר ××× ××Ŗ ×××××¢ ××¤× × ×©×Ŗ×××¢× ××××× ×Ŗ×§××× ×Ŗ×צ×××Ŗ ×××××Ŗ ××××××§××Ŗ ××תר.
6. ×שק××¢× ××××רת ×××××× ×פר××פ××× (×ש××× ×× ×©×× ×××× ×××) - ××××× ××× ×קר ××× ×× ×Ŗ××× ××× ××× ××× ×Ø×§ ×××× ×××ר××Ŗ. ×ש××Ŗ× ××©× ×× ×××× ×”×××× ××× ×©×Ŗ×¦×ר×× ×××××§ ×××ש ××Ŗ ×פר××פ×. ×××××Ø× ×”× ×©× ×§××× ××××§× ××פע××× ×××Ŗ× ××× ×§×××¦× ×©× ×¤×Ø××פ××× ××××××× ×©××× ×Ŗ× ×ר×ש. ×ש××××¢ ×××× ××ש ×Ŗ×××× ××ר×ׄ ×××Ŗ× ×¢× ×××Ŗ× ×”× ×©× ×§××× ××××§×. ×צ××Ø× ××××Ŗ ×Ŗ×××× ××××× ×××× ×××× ××××Ŗ × ××Ŗ× ××Ŗ ××Ŗ×צ×× ××××××§×Ŗ ×××תר × Use Case ש×××.
7. ש××× ×× ××רש×××Ŗ - ×”××× ××× ×× ××××¢ ××§×× ××××××Ŗ ×צ××Ø× ×××× × ×××× ×Ŗ××× ×××× ××× ×× ×©×פ×× ×©× ×§×× ××× × ××× ×××× ×. ×××× ×××× ××”××× ×××× ××פע××? ×××× ××§×Ø× ××¢××ר ×××××¢ ×××”××× ××¤× × ×©×××× ×” ××ער××Ŗ? ×××, ××××”××£ ×¢×× ×”××× ×× ××¢××ר. ×ש ×× ×§××Ŗ ××Ŗ ×פ×× ×©× ××”××× ×× ××× ××¢×ר ××”××× ××§×× ×Ø×××.
8. ×× ×××××× ×××¢××ר ××××× ××Ŗ ×× ×ש××× ××× ×××××× ×××Ŗ×× ×Ø×§ ×”××× ××× - ×ש××Ŗ× ×××Ŗ××× ×”××× ×©××× ×©××× ×× ×©××Ŗ× ×× ×¦×Ø×××× ×××¢××ר ××Ŗ ×× ×××”××ר×××Ŗ ×ש××× ××× ×××××× ×××ש×× ×©××× ×©××× ×¢× ×××Ŗ× ×”×××. ×Ŗ×× ××Ŗ שע××× ×× ××× ×××Ŗ× ××ר×ׄ ×”××× "××××" ××Ŗ××××Ŗ ×ש××× ××ש×ש××× ××§×××Ŗ ××××× ×××¢××ר ××Ŗ ×ש×××× ××”××× ×”×¤×¦××¤× ××תר, ××× ××Ŗ×Ŗ ××× ×”××× ×פשר××Ŗ ××ר××§ ××Ŗ ×ש××× ×××Ø× ××”××× ××××× (××¢×רת ש××× ××”××× ××× ××”× ××× ×פע××Ŗ ×××).
9. × ×”××× ××Ŗ ×××ר×× - ××תר ×ש××× ××Ŗ ×××Ŗ× ×©××× ××”××× ××× ×¤×¢××× ××× ×Ø×× ×××× ×× ×× ×פק××××. ×× ×ש ×ש×× ×©×©×ר ××Ŗ ××”××× ×¤×¢× ×Ø×ש×× × ×ר×× ×¤×¢××× ××× ×ש××ר ××Ŗ ××”××× ×× ×¤×¢× ×©× ×× ×××× ××§×Ø× ××Ŗ× ×× ×Ø×צ×× ×××××Ŗ ×¢× 30% ×ש××× ××Ŗ. ×שת××©× ××ש××× ××Ŗ ××× ××××× ×¢× ××”××× ×× ×©××Ŗ××Ŗ×, ×¢× × ××§×× ××§×× ××פר××פ××× ××××Ŗ××× ×××Ŗ× ××× ××§×× ×Ŗ×©××× × ××× × ×¢× ×××Ŗ× ×§×× ×©× ×ש×.
10. צ×× ××ר×, ×× ×× ×× ×× ××ש×× - ×”××× ×× ××××× ×× ×¢×××× ×ר××§ ××ש ×הפר ××× ×”××× ×©×Ŗ××Ŗ×× ×××× ××Ŗ×× ××××. ×× ××× ×©×Ŗ××× ×Ø×§ ×Ŗ×¦× ×¢×× ××Ø× ×××©× ×××Ŗ×× ×”××× ×× ×ש×× ×Ŗ×××Ø× ×××Ŗ×××. ×§×× ××Ŗ Pydantic AI Agents ×× ×× ×”×¤×Ø×× ××רת ש××××Ŗ× ××× × ××Ŗ ××”××× ×ר×ש×× ×©×××.
×ש ××× ×¢××? ×”×¤×Ø× ×× ××Ŗ×××××Ŗ ××××ר×. | 96 |
| 5 | https://www.tocode.co.il/blog/2026-08-12-takeaways | 86 |
| 6 | "- Only mark genuine downtime as a break ā do not use it for slow "
"or informal but still on-topic teaching."
),
)
def analyze_chunk(
agent: Agent, chunk: dict, chunk_index: int, total_chunks: int
) -> list[Lesson]:
"""
Analyze one chunk ā list of lessons with timestamps converted to
original video time.
"""
offset = chunk["offset_seconds"]
video_file = upload_chunk(chunk["path"], chunk_index)
print(f" š¤ Analyzing chunk {chunk_index}/{total_chunks - 1} "
f"(offset={seconds_to_ts(offset)})...")
t0 = time.time()
result = agent.run_sync(
[
(
f"This is chunk {chunk_index} of a longer course video. "
f"The chunk starts at {seconds_to_ts(offset)} in the original video. "
f"Identify all complete 10-15 minute lessons within this chunk. "
f"Timestamps must be relative to THIS CHUNK (00:00:00 = chunk start). "
f"Do NOT include lessons that are cut off at chunk boundaries ā "
f"adjacent overlapping chunks will capture them."
),
video_file,
]
)
elapsed = time.time() - t0
chunk_lessons = result.output.lessons
print(f" ā
{len(chunk_lessons)} lessons found in {elapsed:.0f}s")
# Convert chunk-relative timestamps to original video timestamps
converted = []
for lesson in chunk_lessons:
rel_start = ts_to_seconds(lesson.start_timestamp)
rel_end = ts_to_seconds(lesson.end_timestamp)
abs_start = rel_start + offset
abs_end = rel_end + offset
converted.append(Lesson(
index=0, # will be re-indexed later
start_timestamp=seconds_to_ts(abs_start),
end_timestamp=seconds_to_ts(abs_end),
is_break=lesson.is_break,
# Force the canonical slug for breaks in code, rather than
# trusting the model to use the right literal string.
slug="breaktime" if lesson.is_break else lesson.slug,
title=lesson.title,
summary_markdown_hebrew=lesson.summary_markdown_hebrew,
))
return converted
×××©× ××§×× ×××§× ××Ŗ ×× ×××××¢ ש××”××× ××××ר ×××¢××Ø×Ŗ× ×©××ר ××Ŗ ×××§××× ××ר××× ××§××¢×× ×§×¦×Ø×× ××××”××£ ××Ŗ ×§××¦× ××”××××. ×”× ××× ××Ŗ××× ××Ŗ ×× ×××× ×ר××× (פ×××Ŗ × 500 ש×ר××Ŗ) ×××שפת ××Ŗ ××××¤× ×פ××Ŗ×× ×”×§×Ø×פ××× ××××: ×ש ×× × ×××××Ŗ ×××©× ×©×§××× ×× ×××Ŗ×, ××××××Ŗ ××××¢×ר ×××××× ×©×¤× ××× ××¤×¢× × ××××¢. ××Ŗ×× 500 ש×ר××Ŗ ×ר×× ×××××× ××× ×§×× ×¤×××Ŗ×× ×©×פשר ××× ×××Ŗ×× ×× ××¤× × ×©××ש ×©× ×× ×××× ×¢××× ×××Ŗ× ××ר - קר×××Ŗ API ×××Ŗ ××× ×× ×©×××××§× ××Ŗ ×× ××§×”×. | 110 |
| 7 | "Be thorough, detailed, and written in the same didactic style as a "
"professional programming course text (not a summary/recap). "
"If is_break is True, skip all of this and just write a brief note "
"that this was a break (e.g. '××¤×”×§× ā ××× ×Ŗ××× ×××××× ××§××¢ ××.')."
)
)
class ChunkOutline(BaseModel):
"""Lessons found within a single video chunk."""
lessons: list[Lesson] = Field(description="Ordered list of lessons in this chunk")
ā ××¢×××Ŗ ××§×צ×× ×××××
××××× ×ש Google File API ש××פשר ×× × ×ש××ר ×§×צ×× ××× ×©×'××× × ×××× ×קר×× ×××Ŗ×. ××× ×× ×× ×××Ŗ×× ××”××× ×× ××× ××רש ×××Ŗ× × ×××××§ ××Ŗ ××§×צ××, ×××× ××××§× ×××Ŗ× ××××××××Ŗ ×××Ø× ××× ×©×¢××Ŗ. ×× ×× ×× ×× ××××× ×§××××× ×× × Claude ××× × OpenAI. ×פ×× ×§×¦×× ×××× ××¢×× ×§××ׄ ×ש××רת ××Ŗ ××××× ×©×× ×צ××Ø× ××¢××Ø× ××”××× ××××©× ××Ŗ××× ××Ŗ:
def upload_chunk(chunk_path: str, chunk_index: int) -> UploadedFile:
"""Upload a single chunk to Google File API."""
print(f" š¤ Uploading chunk {chunk_index} ({Path(chunk_path).name})...")
client = genai.Client()
t0 = time.time()
uploaded = client.files.upload(
file=chunk_path,
config={"display_name": Path(chunk_path).name},
)
elapsed = time.time() - t0
print(f" ā {elapsed:.0f}s, state={uploaded.state.name}")
while uploaded.state.name != "ACTIVE":
time.sleep(5)
uploaded = client.files.get(name=uploaded.name)
print(f" ā
ACTIVE")
return UploadedFile(
file_id=uploaded.uri,
provider_name="google",
media_type=uploaded.mime_type or "video/mp4",
)
×××Ø× ××¢××× Google File API צר×× ××× ××¢×× ××Ŗ ××§××ׄ ××× ××”××× ××××××Ŗ ××××Ŗ× × ×©×× ×× × ×Ø×××× ×©×××× ×©××§××ׄ ×××× ××××.
ā פ××¢× ×× ×ש××¢×ר××
××××§ ××× ××× ××××§ ××ר××× ×©× ××Ŗ××× ××Ŗ - ××××ר×× ××Ŗ ××”××× ××ר×צ×× ×××Ŗ× ×¢× Chunk ש×××× ×הפר ש××¢×ר×× ××× ××××× ×××× ×©××¢×ר×× ×ש ש×:
def build_agent() -> Agent:
"""Create the course-builder agent with Google Gemini."""
model = GoogleModel("gemini-3-flash-preview")
return Agent(
model,
output_type=ChunkOutline,
system_prompt=(
"You are an expert course builder and video content analyst. "
"You receive a SEGMENT (chunk) of a longer course recording and must "
"identify complete, self-contained lessons of 10-15 minutes each "
"within this segment.\n\n"
"CRITICAL RULES:\n"
"- Timestamps MUST be relative to THIS CHUNK (00:00:00 = chunk start)\n"
"- Only include lessons that are FULLY or MOSTLY contained in this chunk\n"
"- If a lesson is cut off at the start or end, do NOT include it ā "
"the overlap with adjacent chunks will capture it\n"
"- Each lesson should be 10-15 minutes of coherent content\n"
"- Identify natural topic boundaries\n"
"- Create descriptive, URL-safe English slugs (lowercase, hyphens)\n"
"- Write comprehensive Hebrew markdown summaries including:\n"
" * Sub-topics covered\n"
" * ALL code snippets shown (in ``` code blocks)\n"
" * Links or references mentioned\n"
" * Key takeaways\n\n"
"BREAK-TIME DETECTION:\n"
"- Also detect BREAKS: segments with no teaching content, such as "
"coffee/lunch breaks, silence, students chatting among themselves, "
"the instructor stepping away, or any other non-lesson downtime.\n"
"- Treat a break exactly like a lesson entry ā give it a start/end "
"timestamp ā but set is_break=True and give it a short title such "
"as '×פהק×'. The slug field is ignored for breaks, just put any "
"placeholder.\n"
"- For a break's summary_markdown_hebrew, just write a brief note "
"that this was a break (e.g. '××¤×”×§× ā ××× ×Ŗ××× ×××××× ××§××¢ ××.'), "
"no need for a full lesson write-up.\n" | 80 |
| 8 | š ××× 11 - ×”×××ר הר××× ××§×רה
×× ×Ŗ×¢×©× ×× ××¢××Ø×Ŗ× ×§×רה AI ×××§×××Ŗ× ××Ŗ ×× ××רצ×××Ŗ שע××Ø× ×××××” ××¢×ש×× ×ש ××× ×©×¢××Ŗ ×©× ××××× ××× ××× ××§×”? ×Ŗ×× × ×”××× AI ×××××. ×××××× ×××× × ×× × ×”××× AI ש×××§× ××§××× ×ר××× ×ש××ר ×××Ŗ× ××××§×× ×§×× ×× ×צ×ר××£ ××× ××§×” ××§×”××××× ××× ××× ×××§ ××× ×©×פשר ×××× ××××ר רק ××××§×× ×©×× ×× × ×¦×Ø××××.
ā ×× ×× ×× × ××× ××
× ×Ŗ×× × ××§××× ×©× 4 שע××Ŗ ××פ×ש ××§×רה ××× ×× × ×Ø×צ×× ××¤×¦× ×××Ŗ× ×ש××¢×ר×× ×§×¦×Ø××, ×× ×©××¢×ר ×× 5-10 ××§××Ŗ ×××× ×©××¢×ר ×צרף ×”×××× ××§×”× ××Ŗ××. ×ש××× ×©×××× ×Ø××× ×××Ŗ× ×××§××Ŗ ××× ×©×¢××Ŗ ××× ××× × AI ×××× ×עש××Ŗ ×××Ŗ× ××§×××Ŗ ×צ××Ø× ×¢×¦××××Ŗ ×××ר×. ×× ×Ŗ×××× ××¢××××:
1. ×××Ŗ××× ××Ŗ ×××§××× ××§××¢×× ×©× 30 ××§××Ŗ ××× ×©×××× × AI ×§× ×××Ŗ×××× ×××Ŗ×.
2. ×× ×× × ×× ××××¢×× ×¢×××× ×××¤× ××× ××××× × ××”×× "ש××¢×ר" ××× × ××× ××פ××¤× ×©× 5 ××§××Ŗ ××× ××§××¢×× ×קצר×× ××× ×©××¢×ר ×× ××פ×× ×××××§ ×××צע ××× ×××.
3. × ×¢×× ×× ×§××¢ × Gemini ××Ø× Google File API.
4. × ×קש ×××”××× ×©××¢××ר ×¢× ×× ×§××¢ ××××Ŗ× ×× ××Ŗ × Timestamps ××× ××× ××××× × ×××Ŗ×× ××Ŗ ××§××¢ ×ש××¢×ר××.
5. × ××× ×× ××Ŗ×× ××Ŗ ×××§××× ××¤× ×××× ×× ×©×§×××× × ×××”××× ×× ×¦×Ø×£ ××Ŗ ××”××××××.
×§×× ×××××× ×××× ×××× ×©×× ××Ŗ××§×××Ŗ ××××××××Ŗ ×××¤×¢× ××”××× ×××× ×©××ר ××§××ׄ ×××:
https://github.com/ynonp/pydanticai-demos/blob/main/11-course-builder/build-course.py
× ×¢××ר ××× ×¢× ××××§×× ×××¢× ××× ××.
ā ××× × ×פ××
××”××× ××××ר רש××× ×©× ×©××¢×ר×× ××× ×©××¢×ר ×××× ×××× ××××¢: ××× ×××Ŗ××× ×©××, ××× ××”×××, ××× ××§×” ש××, ××× ×× ×©××¢×ר ×× ×פהק×, ×××× ×©×× ××× ×”×××× ×ש××¢×ר. ×× ×¤×Ø×× ××××¢ ××× ××××¢ ×××× × ××”××× ××¢× ××ר×××Ŗ ××”×××××Ŗ ×× ×× ×× ×רש×× ××Ŗ ×××ר×××Ŗ שקש×ר××Ŗ ××× ×©×× ××Ŗ×× ××§×××” ש××××ר ××Ŗ ××× × ×פ××. פ××× ×××§ ××פשר ××Ŗ ×× ×××צע××Ŗ פק×××Ŗ Field. ×× × ×Ø×× ××:
class Lesson(BaseModel):
index: int = Field(description="1-based lesson number within this chunk")
×§×××” ×ש××¢×ר ×××× ×××× ×× ×××”×ר×× ××× ××§×××” ×ר×ש×× ××§××ׄ:
class Lesson(BaseModel):
"""A single lesson extracted from the course video."""
index: int = Field(description="1-based lesson number within this chunk")
start_timestamp: str = Field(
description="Start time relative to THIS CHUNK as HH:MM:SS, e.g. '00:02:30'"
)
end_timestamp: str = Field(
description="End time relative to THIS CHUNK as HH:MM:SS, e.g. '00:14:45'"
)
is_break: bool = Field(
default=False,
description=(
"True if this segment is a BREAK with no teaching content ā e.g. "
"students chatting, silence, instructor away, coffee/lunch break. "
"False for a normal lesson."
),
)
slug: str = Field(
description=(
"URL-safe slug for the lesson, e.g. 'intro-to-pydantic'. "
"If is_break is True, this is ignored (the slug 'breaktime' is "
"applied automatically) ā still provide a placeholder value."
)
)
title: str = Field(description="Lesson title in the original language")
summary_markdown_hebrew: str = Field(
description=(
"A full, self-contained lesson write-up in Hebrew markdown, written so "
"that someone who never watched the video can read it and actually "
"learn the material ā NOT a table of contents or a bullet-point index "
"of what was covered. Write it like an article/tutorial: "
"Structure it as numbered sections ('### 1. <topic title>', "
"'### 2. <topic title>', ...), one per sub-topic covered in the "
"lesson, in the order they were taught. Under each heading, write "
"full explanatory paragraphs in flowing Hebrew prose that actually "
"teach the concept (what it is, why it matters, how it works) the "
"way the instructor explained it ā not short summaries or fragments. "
"Include exact code shown in the video in fenced code blocks, "
"including commands, filenames, and terminal output where relevant, "
"each with a sentence or two explaining what the code does and why. "
"Include any links or external references mentioned, and end with "
"practical conclusions/recommendations if the instructor gave any. " | 71 |
| 9 | https://www.tocode.co.il/blog/2026-08-11-coursebuilder | 72 |
| 10 | if key not in chapters:
chapters[key] = []
order.append(key)
chapters[key].append((verse, text))
chunks: list[dict] = []
for book, chapter in order:
entries = chapters[(book, chapter)]
for start in range(0, len(entries), step):
window = entries[start : start + chunk_size]
if not window:
continue
first_verse = window[0][0]
last_verse = window[-1][0]
verses_range = str(first_verse) if first_verse == last_verse else f"{first_verse}-{last_verse}"
chunk_text = " ".join(text for _, text in window)
chunks.append(
{
"book": book,
"chapter": chapter,
"verses_range": verses_range,
"chunk_text": chunk_text,
}
)
# Stop once the window has consumed the tail of the chapter.
if start + chunk_size >= len(entries):
break
return chunks
×פ×× ×§×¦×× ×Ø×¦× ×¢× ×××§×”× ×××הפת ×§××צ××Ŗ ×©× 6 פה××§×× ××× ×§×××¦× ××צרת chunk. ×× chunk ××× ×××××§ ××Ŗ ×הפר ××× × ××× × ××§×, ×פרק, ×××× ×¤×”××§×× ××× ×××× ×××Ŗ ×××§×”× ××××.
××××©× ×× × ×ר×ׄ ××Ŗ ×פק×××:
embeddings = embed_texts([c["chunk_text"] for c in chunks])
××× ××צ×ר ××Ŗ ×× ×××§××ר×× ××× ××Ŗ ×××××× ×××× ××× ×ש××ר ××× ×××”××” ×× ×Ŗ×× ××:
rows = [
(
chunk["book"],
chunk["chapter"],
chunk["verses_range"],
chunk["chunk_text"],
embedding,
)
for chunk, embedding in zip(chunks, embeddings)
]
with conn.cursor() as cur:
cur.execute(f"TRUNCATE {TABLE} RESTART IDENTITY")
cur.executemany(
f"INSERT INTO {TABLE} (book, chapter, verses_range, chunk_text, embedding) "
"VALUES (%s, %s, %s, %s, %s)",
rows,
)
conn.commit()
ā ××פ×ש ××§××ר×
×××פ×ש ×××צע ××§××ׄ app.py ×פ×× ×§×¦×× inject_rag_context. ×× ××§×× ×ר×××× ××:
embedding = embed_query(query)
with ctx.deps.conn.cursor() as cur:
cur.execute(
f"""
SELECT book, chapter, verses_range, chunk_text
FROM {TABLE}
ORDER BY embedding <=> %s
LIMIT %s
""",
(embedding, ctx.deps.top_k),
)
hits = cur.fetchall()
××Ŗ ××Ŗ×צ×× ×©××××× ××”××× ××× ×× ××”×פ×ר.
ā ×¢×ש×× ××Ŗ×
1. ×ר××¦× ××Ŗ ××ער××Ŗ ×צ×××. ש××× ×©××××Ŗ ××××§× ××× ××”××× ××¦× ××Ŗ ××§××¢×× ×ר×××× ××× ××¢× × ×Ŗ×©××××Ŗ ×××××§××Ŗ.
2. ×צ×× ×©××××Ŗ ש××”××× ×צ××× ×פת×ר ×ש××××Ŗ ××ר××Ŗ ש××× ×× ×צ×××. ×¢× ×× ×©××× ×©××× ×× ×צ××× × ×”× ××ש×× ×××¤× ×××Ŗ× ×××¢××.
3. ×××§× ×××××× ××ר×× ×©× Embedding. ××× ×ש ×××× ××Ŗ×צ×××Ŗ? × ×”× ××צ×× ×××× ××× ××תר ××× ×©×× × ×צ××Ŗ×.
4. ש××× ××פ×ש ××§×”× ××× ××ער××Ŗ ×× ×©××”××× ××§×× ×× ××Ŗ ××§××¢×× ×©×§×Ø×××× ×”×× ×××Ŗ ××× 5 ×§××¢×× ×©×××××× ××× ×ר×× ××××× ×ש×תפ××Ŗ ×¢× ×ש×××. ש××× ×× ××× ×× ××©× × ××Ŗ ××Ŗ×צ×××Ŗ. | 90 |
| 11 | š ××× 10 - ××פ×ש ××¢×רת Vector DB
××Ŗ××× ×Ø××× × ××× ××צע ××פ×ש ××§×”× ××× ×××Ŗ ×××Ŗ×ר×× ×©××. ×××× × ×ש×× ×¢× RAG ×××¤×¢× × ×× × ×× ××¢ ××פ×ש ××§×××Ø× ×× ×Ø×× ××××× ×קר×× ×× ××¢ ××× ×××× ××××§ ××Ŗ ××Ŗ×צ×××Ŗ.
ā ×××פ×ש ××§×”× ××× ×××פ×ש ××§××ר×
×××××× ×©×Ø××× × ××Ŗ××× × ××”×× × ××פש פ××”××× ×©×§×©×ר×× ×ש××× ×©×שת×ש ש×××. ר××× × ×©×× ××ש ×× ×¤×©××: ×שת×ש ×××× ××שת×ש ×××××× × ×Ø×פ××Ŗ, ×××× ××××× ××××× ××××××Ŗ ×©× ×צ×××Ŗ ××××× ×¤××”×××, ×××× ×××Ŗ×× ××¢×ר××Ŗ ×©× ×©× ××× × ×קצ××¢× ×× ×× ×××Ŗ×× ××Ŗ ×©× ×××× × ××××. ××× ××צ××× ×××× ×× × × ××¦× ×¤××”××× ×× ×Ø×××× ××× ×× ×©×× × ××¦× ×¤××”××× ×× ×Ø×××× ×××.
××× ×רע××× ××Ŗ ×ר×ש×× ×× ×©×× ×©×× ××¢×× ×ש××Ŗ×××× ×ש×× ××פ×ש×× ×××××× ×©×¤× ××× ××שת×ש ××××× ××©×¤× ××× ××פש ×ער××× ××××× ×©× ××§×”×, ×רע××× ××× ×××:
1. ××× ×©×××× ×× ×××× ×©×¤× ×××××Ŗ ×××©× ×××¢× ×ש×××, × ××× ×××× ×××× ×©×¤× ×××××Ŗ קשר ×”×× ×× ××× ××××× ××שפ×××.
2. ×שפ××× ×©×ש ××× ××× ×§×©×Ø ×”×× ××, ××××ר ×× ××פ××¢×× ×ר×× ×¤×¢××× ××× ×§×Ø×× ××××Ŗ× ××§×”××× ××§×××× ×××§××ר×× ×©××ר××§ ××× ××× ×§××. ××××× ××שפ××× ×©××× ××× ××× ×§×©×Ø ×× ×©×ש קשר ××ש ××§×××× ×××§××ר×× ×©××ר××§ ××× ××× ××××.
3. ××ער××Ŗ ש×× × ×Ŗ××§× ××§×”× ×××× ×× ×× ×× × ×Ø×צ×× ××פש, ×Ŗ×××§ ×××Ŗ× ××שפ××× ×× ×§××¢×× ×§×¦×Ø×× ××Ŗ×§××× ×× ×§××¢ קצר ×××§××ר. ×ש×שת×ש ××××¢ ×¢× ×©××× × ×§××× ×× ××Ŗ ×ש××× ×©× ××שת×ש ×××§××ר ××× × ××¦× ××××ר ×××××¢ ש×× × ××Ŗ ×××§××ר×× ×©××× ×§×Ø×××× ×ש×××Ŗ ××שת×ש. ××× ××שפ××× ×©×ש ××× ××Ŗ ×קשר ××”×× ×× ××× ×××§ ×ש×××Ŗ ××שת×ש.
×רע××× ××× ×××× × ×©××¢ ××××× × ××× ×ש ×× ×××× ××¢×××Ŗ. ××Ŗ×ר ××Ŗ××× ×× ×ר×ר ××× ××××§ ××§×”× ×ר×× ××שפ××× ×§×¦×Ø×× ××× ××§××× ×××Ŗ× ×××§××ר××, ×× ×ר×ר ××× ×©×ש××× ×Ŗ××× ×§×©××Ø× ×”×× ×××Ŗ ××××§× ×××©×¤× ××”××× ×× ××§××צת ×שפ×××, ××× ×××× ×××× ××Ŗ ××××× ××”×× ×× ×××¤× ×××× ×§×רפ××” ××§×”×××××. ×ש ×××× ×©××××Ŗ ×××Ŗ×××× ×¢× ×××Ŗ×ר×× ×××× ××× ××× ×¢× ××פ×ש ××§×”× ××× ×× ×× × ×× ×××ר×× ××× ×¢× × ××”××Ŗ ×§×”× ×××פ×ש ×××××§ ××× ×¢× ×××”×£ ×©× ××× ××§××Ŗ ש×××× ××¢××× ××××× ×× ××¢××× ××××Ø× ××× ×ער×××Ŗ ××××Ŗ×××Ŗ ×ש××× ××× ××פ×ש ××§××ר×, ××פ×ש ××§×”× ××× ×××× ××§×” ××פ×ש ×¢× ×××××¢ ××× ××××Ŗ ××צ××× ××¢× ××Ŗ ×ש××××Ŗ ×©× ×שת×ש××.
ā ×× ×× ×× × ××× ××
×××××× ×××× ×× ×× × ×Ø×צ×× ×ר×××Ŗ ××× ×¢××× ××פ×ש ××§×××Ø× ××× ××תר ××× ××פ×× ×××ר××Ŗ ×©× ×ער××Ŗ ××× ×××× ××§××Ŗ× ××Ŗ ×××פ×ש ××”×× ×× ××× ×§× ×©×צ××Ŗ× - ××פ×ש ×××§×”× ×ר×× ×©××¢××× ×× ××©×Ŗ× × ××ש ×× ××××§× ×××¢××Ŗ ×פה××§××, ××× ××Ŗ× "×. ×××××× ×××× × ××Ŗ×× ×ער××Ŗ ש×××§××Ŗ ש××× ×©× ×שת×ש ×××פשת ××Ŗ× "× ×§××¢×× ××¢×× ××××× ×”×× ×× ×ש××× ××× ××¢×××Ø× ××Ŗ ×ש××× ××× ×¢× ××§××¢×× ×©×× ×Ø×× ×Ø×××× ××× ××××× ×©×¤× ××× ××§×× ×Ŗ×©××× ×ש×××.
××ער××Ŗ ×¢××××Ŗ ××××¤× ×××:
1. ×Ŗ×××× ×¢××ר×× ×¢× ×× ××Ŗ× "× ×××§××××× ×× ×§×××¦× ×©× 6 פה××§×× ×××§××ר. ××× ××§××צ××Ŗ ×× × ×©××ר ×פ××¤× ×©× ×©× × ×¤×”××§×× ××× ×©××××¢ ×”×× ×× ×× ××× ×××××× ×××¢×ר ××× ×§××צ××Ŗ. ××Ŗ ×××§××ר×× ×©××ר×× ×××”××” × ×Ŗ×× ×× Postgres ×¢× ×ר××× ××©× pgvector ש××פשרת ש××רת ××§××ר×× ××ש×××× ××× ×××. ×× ×Ŗ×××× ×× ×¤×¢×× ×©×§××Ø× ××צ×רת ××ער××Ŗ.
2. ×ש××ער××Ŗ ×××××ר ×××§××× ×©××× ×××שת×ש××, ××§××××× ×× ×××Ŗ× ×××§××ר ×××פש×× 5 ××§××ר×× ×§×Ø×××× ××. ××ש××× ×××”××” ×× ×Ŗ×× ×× ××Ŗ ×××§×”××× ×©××Ŗ××××× ×××§××ר×× ××× ×ש××××× ××× ××'××× ×.
×§×× ×××××× ×××× ×××× ××Ŗ××§×××Ŗ ××××××××Ŗ ××§×ש×ר:
https://github.com/ynonp/pydanticai-demos/tree/main/10-bible-vectordb
××××× ×¢×¦×× × ×§×Ø× BAAI/bge-m3 ××פשר ×××Ŗ×§×× ×××Ŗ× ×הפר×××Ŗ פ×××Ŗ×× ××Ŗ×× Hugging Face. ×× ×××× ×”×× ×× ××¢×ר××Ŗ ×××× ××Ŗ××× ×××§×”× ×©×× ×. ×××Ø× ×©×ש ×× ××Ŗ ××××× ×××Ŗ×§× ×§×××× ×©× ××§×”× ×××§××ר ××× ××”× ××× ×§×Ø×××Ŗ פ×× ×§×¦×× ×פ×××Ŗ××:
def embed_texts(texts: list[str]) -> list[list[float]]:
"""Embed a batch of texts, returning one 768-dim vector per text."""
embeddings = get_model().encode(texts, show_progress_bar=True)
return [vec.tolist() for vec in embeddings]
ā ×§×××× ××Ŗ× × ×××§××ר××
××§×××× ×××§××ר×× ××××ש ××§××ׄ index.py.
×פ×× ×§×¦×× ×××¢× ××× ×Ŗ ××§××ׄ × ×§×Ø××Ŗ build_chunks ××× ××§×× ×©××:
def build_chunks(
verses: list[tuple[str, int, int, str]],
chunk_size: int,
overlap: int,
) -> list[dict]:
"""Group verses per (book, chapter) and split into overlapping windows."""
if chunk_size <= overlap:
raise ValueError(f"CHUNK_SIZE ({chunk_size}) must be greater than OVERLAP ({overlap})")
step = chunk_size - overlap
# Preserve file order while grouping by (book, chapter).
chapters: dict[tuple[str, int], list[tuple[int, str]]] = {}
order: list[tuple[str, int]] = []
for book, chapter, verse, text in verses:
key = (book, chapter) | 81 |
| 12 | https://www.tocode.co.il/blog/2026-08-10-vectordb | 75 |
| 13 | "for example 'Based on: file1.md, file2.md'. Then answer the question.\n\n"
+ "\n\n".join(sections)
)
1. ×××§××× ××Ŗ ×פר×××¤× ×©×¢××× ×××ש×× ×××××.
2. ×ר×צ×× ××פ×ש ×××××× ××× ××צ×× ×¤××”××× ×Ø×××× ×××.
3. ×××”×פ×× ×××£ ×××ר×××Ŗ ××Ŗ ×Ŗ××× ×× ×פ××”××× ×ר×××× ×××.
ā ×¢×ש×× ××Ŗ×
×ש××× ××ר×ׄ ××Ŗ ×××××× ×Ŗ×¦×ר×× ××¤×¢× ××Ŗ ××קר ×××ר ××ש ×× × ×× ××Ŗ ××”××” ×× ×Ŗ×× ×× meilisearch ××× ××Ŗ ××פ××קצ××. צ××Ø×¤×Ŗ× ××Ŗ××§×××Ŗ ×××××× ×§××ׄ docker-compose.yml ×× ×פשר ××שת×ש.
1. ×ר××¦× ××Ŗ ×××××× ×צ××× ×××Ø× ×××רת ××¤×Ŗ× ××××©× ××'××× × × .env. ש××× ××Ŗ ××”××× ×©××××Ŗ ×ש××× ×× ××××× ×¤××”××× ××× ×שת×ש ××× ××¢× ××Ŗ.
2. ×ש××: ××× ×××× × ××Ŗ×××§×× ××Ŗ ×××× ××§×” ××ער××Ŗ פר××קש×? ×× ×§××Ø× ×× ×Ŗ××× ×¤××”× ××Ŗ×¢×××? ×× ×× ×¤××”× × ×××§?
3. ×ש××: ×× ×§××Ø× ×× ×ש פ××”× ×ר×× ×××××× - ××× ×Ŗ××× ×¦×Ø×× ××××× ××Ŗ ×× ×פ××”× ××× ××¢× ××Ŗ ×¢× ×©×××Ŗ ××שת×ש? ××× ×××× ×הפ××§ ××××× ×××”×Ŗ×× ×¢× ×¤×”×§× ×××××Ŗ?
4. ×××××¤× ××Ŗ ×× ×× ×× × RAG ××××©× ××××”×”×Ŗ ×××× - ×Ŗ× × ××”××× ××× ×××פ×ש × meilisearch ×ש××× ××Ŗ ×××Ŗ× ×©××××Ŗ. ××× ×§××××Ŗ× ×Ŗ×©××××Ŗ ×××××Ŗ ××תר? ×××××Ŗ פ×××Ŗ?
5. ×××××¤× ××Ŗ ×× ×× ×× × RAG ××××©× ×ר×××Ŗ ×”××× ×× - ×× × ×”××× ××פ×ש שתפק××× ××פש × meilisearch ×§××¢×× ×Ø×××× ××× ×ש××× (××¢×רת ××× ×××פ×ש). ×פע××× ××Ŗ ×”××× ×××פ×ש ×××§×× ××× ××Ŗ ××Ŗ ×ש××××Ŗ× ×עצ××× ×××Ŗ ××Ŗ×צ×××Ŗ ××¢×××Ø× ××”××× ×ש×××. ××× ×× ×¢××?
6. ××Ŗ××§×××Ŗ docs ×©× ×¤××× ×××§ AI ×Ŗ×××× ××צ×× ××Ŗ ××Ŗ××¢×× ×©× ×הפר××. ××Ŗ×× ×”××× ×©××פש ××Ŗ××¢×× ×הפר×× ××¢×× × ×¢× ×©××××Ŗ ×××××. | 103 |
| 14 | "content": content,
}
)
return docs
×××××©× ×× ×× × ×§×ר××× ×פ×× ×§×¦×× ×©× ××××× ×©× ×§×Ø××Ŗ add_documents ××× ×ש××ר ××Ŗ ×××”×××× ×××”××” ×× ×Ŗ×× ××:
docs = build_documents()
task = index.add_documents(docs)
××צ×רת ×××× ××§×” ×× × ×©××ר ×× ×××× ×©× ××××× × ×Ø×פ××Ŗ. ×××× ×× ×Ŗ×¢××ר ××צ×× ×¤××”××× ×§×©×ר×× ×× ×ש×× ×שת××©× ×ש××× ××××Ŗ× ××××× ×××××§ - ××× ××Ŗ× ××ר ×××××× ×ר×××Ŗ ××Ŗ ×××Ŗ×ר ××× ×××, ×Ŗ××××§× ×ש×××Ø× ×©× ×××× ××:
HEBREW_SYNONYMS: dict[str, list[str]] = {
# Singular ā plural
"××פ": ["××פ××"],
"×××": ["××××"],
"ש××××": ["ש×××××Ŗ"],
"×××": ["×××××"],
"×§××": ["×§××××"],
"פ×צ׳ר": ["פ×צ׳ר××"],
"××××": ["××××××"],
"×”×××": ["×”××× ××"],
"פר×××§×": ["פר×××§×××"],
"ש×××": ["ש××××Ŗ"],
"תש×××": ["תש××××Ŗ"],
"פתר××": ["פתר×× ××Ŗ"],
"××¢××": ["××¢×××Ŗ"],
"×××××": ["×××××××Ŗ"],
"×§××ׄ": ["×§×צ××"],
"שפ×": ["שפ××Ŗ"],
"××Ŗ××": ["××Ŗ×××Ŗ"],
"פ××”×": ["פ××”×××"],
# Common abbreviations / shortcuts
"××× × ××××××Ŗ××Ŗ": ["AI", "ai", "×ד×"],
"×××××Ŗ ×××× ×": ["ML", "ml", "machine learning"],
"×¢×××× ×©×¤× ×××¢××Ŗ": ["NLP", "nlp"],
"××× ××××": ["big data"],
# English terms that appear in Hebrew text
"prompt": ["פר××פ×", "פר××פ×××", "×× ××”×Ŗ פר××פ×××"],
"agent": ["×××××³× ×", "×××××³× ×××"],
"token": ["×××§×", "×××§× ××"],
"API": ["api", "××שק"],
"framework": ["פר×××××רק", "פר×××××רק××"],
"library": ["הפר×××", "הפר×××Ŗ"],
"debugging": ["×××××", "× ×פ×× ×©×××××Ŗ"],
"refactoring": ["ר×פק××ר", "ר×פק××ר×× ×", "ש××Ŗ×× ×§××"],
"testing": ["××××§××Ŗ", "××”×××", "××”×"],
"code review": ["×§×× ×Ø×××××", "×”×§×רת ×§××"],
"open source": ["×§×× ×¤×Ŗ××", "open-source"],
"CLI": ["cli", "ש×רת פק×××"],
"LLM": ["llm", "×××× ×©×¤× ××××", "××××× ×©×¤×"],
"RAG": ["rag"],
"MCP": ["mcp"],
"VSCode": ["vs code", "×××××× ×”××××× ×§××", "vs-code"],
"Git": ["git", "×××"],
"GitHub": ["github", "××××××"],
"Copilot": ["copilot", "×§×פ×××××"],
"Claude": ["claude", "×§×××"],
"Docker": ["docker", "××קר"],
"Python": ["python", "פ×××Ŗ××"],
"JavaScript": ["javascript", "js", "×׳×××× ×”×§×Ø×פ×"],
"TypeScript": ["typescript", "ts"],
"Ruby": ["ruby", "ר×××"],
"Rails": ["rails", "ר××××”"],
"React": ["react", "ר×××§×"],
"Vue": ["vue", "×××"],
}
ā ××פ×ש ×ש×××× ××Ŗ×צ×××Ŗ
ר××× × ××××××××Ŗ ×§×××××Ŗ ××× ×××××ר ××”××× ××£ ××ר×××Ŗ ×”××× - ××××ר ××§×”× ×©× instructions ש××”××ר ××”××× ×× ×¦×Ø×× ×עש××Ŗ. ××¢×××× RAG ××£ ×××ר×××Ŗ × ×× × ×צ××Ø× ××× ×××Ŗ ××¤× ×ש××××Ŗ× ×××× ×× ×× × ×שת×ש×× ××× ×× ×× × ××”×£ ×©× Pydantic AI Agents ×©× ×§×Ø× Dynamic Instructions. ×× ×× ×× ×× ××פשר ×× × ×ש××ר פ×× ×§×¦×× ××Ŗ×ר ×Ŗ×הפת ×××ר×××Ŗ, פ××× ×××§ ×פע×× ××Ŗ ×פ×× ×§×¦×× ××××”××£ ××Ŗ ×¢×Ø× ××××ר ש×× ×××£ ×××ר×××Ŗ. ×פ×× ×§×¦×× ×Ø×¦× ×××××§ ××¤× × ×©××××Ŗ ×××××¢× ××××× ××ש ×× ×××©× ×פר×××¤× ×××Ŗ×××××Ŗ ×©× ×××Ŗ× ×קש×.
× ×§×Ø× ××Ŗ ××§×× ××× ××Ŗ×× ××§××ׄ app.py:
@agent.instructions
async def inject_rag_context(ctx: RunContext[Deps]) -> str:
"""Search Meilisearch and attach the top matching posts to the prompt.
The filenames are also stored in ``ctx.metadata['rag_sources']`` so the
output validator can prepend them to the final answer.
"""
query = _extract_query(ctx.prompt)
if not query:
return ""
if ctx.metadata is None:
ctx.metadata = {}
results = ctx.deps.meili.index(INDEX_NAME).search(query, {"limit": ctx.deps.top_k})
hits = results.get("hits", [])
filenames = [hit["filename"] for hit in hits]
ctx.metadata["rag_sources"] = filenames
if not hits:
return (
"No relevant blog posts were found for this question. "
"Answer based on your general knowledge, but mention that no posts matched."
)
sections = [f"--- {hit['filename']} ---\n{hit['content']}" for hit in hits]
return (
f"Relevant blog posts found by Meilisearch: {', '.join(filenames)}. "
"Use the content below to answer the user's question. "
"Start your response by listing the filenames of the posts you used, " | 69 |
| 15 | š ××× 9 - ××פ×ש ××××× ×××צע××Ŗ RAG ×××פ×ש ××§×”× ×××
×ר×× ×× ×©×× ×©×××¢×× RAG ×××× ××ש××× ×¢× ××פ×ש ××§××ר×, ××× ××××Ŗ ש RAG ××× ×ר×× ××תר ×××. ×××× × ××ר ×¢× RAG ××Ø× ×ש××× ×©× ××פ×ש פ××”××× ××××× ×××ר × ×¢××ר ×××××× ×¢× ××פ×ש ××§××ר×. ×©×Ŗ× ××××××××Ŗ ××× ×××©×¤× ×××§ ××××ר××××Ŗ ×××Ŗ×××Ŗ ×”××× ×× ×©×¦×Ø×××× ×××××ר תש××××Ŗ ××Ŗ×× ×××ר ×××¢.
ā ××Ŗ×ר ××§×× ××§×”×
××Ŗ××× × ××Ŗ ××”××Ø× ×¢× ××”××× ×××××, ×”××× ×©××§×× ×××ר ××××צר ××× × 10 ש××××Ŗ. ××××©× ×Ø××× × ××Ŗ ××”××× ×©×××צר × ×××××ר ××¢×רת ××××, ×××Ŗ× ×”××× ××פש ×עצ×× ×רשת ×××ר×× ××¢× ××× ×× ××××ר ×××Ŗ× ×× ×××××ר. ×©× × ××קר×× ××× ×××××××Ŗ פש××××Ŗ ××”××× ×× ×©××××ר×× ×Ŗ×©××× ×¢× ××”××” ×××ר ×××¢ ×××©× ××× ××¢×××× ×××Ŗ× ××××: ××”××× ×§××× ××Ŗ ×××××¢ ××× ×¢× ×××§×©× ×××”××£ ××××ר תש××× ×ש××××× ××§×× ××§×”× ×©×× ××× ×××××¢ ××ר×ש ×××××× ××ש××× ×©× ××שת×ש.
××× ×× ×× ××× ×××××§ ×× ×× × ×§×ר××× RAG ש×× ×Ø××©× ×Ŗ××××Ŗ ×©× Retrieval-augmented generation. ××××Ŗ ×××¤×Ŗ× ×©× RAG ××× Retrieval, ××ער××Ŗ ××ש××Ŗ ××Ŗ ×××××¢ ×ר×××× ××, ×××”××¤× ×××Ŗ× ××××× ××§×× ××§×”× (×× × Augmented) ××פע××× ××Ŗ ××××× ××× ×××צר תש×××.
××©×Ŗ× ××××××××Ŗ ש×צ××Ŗ× ×× ×××× × ×¦×Ø×××× ×××Ŗ××× ×××× ××××¢ ×××× ××” ××××× ××§×× ××§×”×. ××”××× ××××× ××× ×¦×Ø×× ××Ŗ ××××ר ××× ×× ×©××× ×§×××. ×”××× ×× ×××××ר ××× ×¦×Ø×× ×××ש×× ×××ר×× ××××× ×עצ×× ××Ŗ ×××××. ×ער×××Ŗ RAG ××תר ××¢× ××× ××Ŗ ×× ×ער×××Ŗ שצר××××Ŗ ×××××× ×צ××Ø× ××× ×××Ŗ ×××¤× ×קשת ××שת×ש ×××× ××××¢ ×××× ××” ××××× ××§×× ××§×”× ××¤× × ×©×¤×× ×× ×××××.
×ער××Ŗ RAG ××ר×××Ŗ ××× ×Ŗ××× ××הפר ×××§×× - ××××§ ×©× ××”××× ×××××§ ש××פש ××¢×××Ŗ ××Ŗ ×קשת ××שת×ש ×¢× ××××¢ ××××ר ××××¢. ש××× ×× ×©×× ×××§ ××× ×¢×¦×××, ××”××× ××× ××× ××¢××× ×× ×צ××× ××¢× ××Ŗ × ××× ×× ×× ×Ŗ×Ŗ× × ×× ××Ŗ ×××××¢, ××××××¢ ××× ×Ø×××× ×× ×× ××¢××ר ×× ××”××× ×× ×צ××× ××××× ×××Ŗ×. ×ר×× ×¤×¢××× × ×Ø×¦× ×ש×× ×× ××פצ×× ×××פ×ש ××ש×, ××××ר × ××Ŗ× ××”××× ××××¢ ר×ש×× × ××××× ××× ××ש×× ××××¢ × ××”×£.
×××××× ×××× × ×× × ×”××× ×©××××¢ ××¢× ××Ŗ ×¢× ×©××××Ŗ ××¤× ×¤××”××× ×××××× ×××. ×× ×× × × ×× ×:
1. הקר××¤× ×©××ר×× ××Ŗ ×פ××”××× ×××××× ×××× ××§×” ×××Ŗ× ×××”××” × ×Ŗ×× ×× ×××××¢× ×××פ×ש ××©× Meilisearch.
2. ×§×× ×¤×××Ŗ×× ×©××§×× ×©×××Ŗ ×שת×ש ×××פש × Meilisearch ×××× ×¤××”××× ×¢×©×××× ×××××Ŗ ר×××× ××× ×ש××× ×× (×××× ×¤××”××× ×××××× ××××× ××ש×××).
3. ×§×× ×”××× ×©××§×× ×¤××”××× ×××××× ×ש×××Ŗ ×שת×ש ××¢×× × ×¢× ×ש××× ××¤× ×× ×©××Ŗ×× ×פ××”×××.
ש××שת ××××§×× ×××××× ×ער××Ŗ RAG ×××××× ×××Ŗ× × ×¢× ×××Ŗ×ר×× ××× ×××Ŗ ×ער××Ŗ ×××.
ā ×צ×רת ×××××¢
ש×× ×Ø×ש×× ××ער××Ŗ ××× ×צ×רת ×××ר ×××××¢. ×××××× ×©×× × × ×Ŗ××× ×¢× ×הקר××¤× download-data.py ש××ר×× ××Ŗ ×× ×פ××”××× ×××תר ××§××¦× markdown ××§×××××. ×× ×§× ×× ×× × ××××× ××¤×Ø×”× ××Ŗ ×פ××”××× ×× × HTML ××× × Markdown ×××× ××§×× ×¦×Ø×× ×ר×ׄ ×¢× ××£ ×× ××¤× ××× ××§×” ××××××, ×××”××£ ××Ŗ ××§×ש×ר×× ×פ××”××× ××× ×××ר×× ×××Ŗ× ××× ×××¢×××” ×¢× ×שרת. ×××Ŗ ×פ×× ×§×¦×× ××ר××××Ŗ:
async def run(count: int) -> None:
DATA_DIR.mkdir(parents=True, exist_ok=True)
semaphore = asyncio.Semaphore(MAX_CONCURRENCY)
async with httpx.AsyncClient(
headers={"User-Agent": USER_AGENT},
follow_redirects=True,
timeout=30.0,
) as client:
slugs = await collect_slugs(client, count, semaphore)
if len(slugs) < count:
print(f"warning: only {len(slugs)} posts found (requested {count})")
# The slug list is the download queue; the semaphore enforces at most
# MAX_CONCURRENCY concurrent requests.
await asyncio.gather(
*[download_post(client, slug, semaphore) for slug in slugs]
)
print(f"done: downloaded {len(slugs)} posts to {DATA_DIR}/")
×הקר××¤× ×××§× ×××שת×ש ×הפר פ××”××× ×××ר×× ×ש××ר ××Ŗ ×××× ××Ŗ××§×××Ŗ data.
ā ש××רת ×פ××”××× ×××”××” × ×Ŗ×× ×× ×××פ×ש
×××Ø× ×©×ש ×× × ×××ר ××××¢ ×× ×× × ×Ø×צ×× ××× ××§×” ×××Ŗ× ××××ר ×ש××ר ××Ŗ ×××××¢ ×צ××Ø× ×©×××× ×§× ××××ר ××Ŗ ×פ××”××× ×ר×××× ××× ×ש××××Ŗ ×שת×ש××. ×× ×Ŗ×¤×§××× ×©× ×הקר××¤× ××§××ׄ index.py
×× ××¢ ×××פ×ש ××××× ×©××ר ×××××§××× ×××××¢ ××פש ×××§×”× ×©×××. ×פ×× ×§×¦×× ×ר×ש×× × ×§×ר××Ŗ ××Ŗ ××§×צ×× ×××××”×§ ×רש××× ×××ר××:
def build_documents() -> list[dict[str, str]]:
"""Read every ``.md`` file in ``data`` and build Meilisearch documents."""
docs: list[dict[str, str]] = []
for path in sorted(DATA_DIR.glob("*.md")):
content = path.read_text(encoding="utf-8")
docs.append(
{
"id": path.stem,
"filename": path.name,
"title": _extract_title(content), | 95 |
| 16 | https://www.tocode.co.il/blog/2026-08-09-blogsearch | 77 |
| 17 | ā ×§×× ××”×××
××”××× × ××¦× ××§××ׄ quiz_agent.py ××××× ××Ŗ ××××× ×©×××Ø× × (×'××× ×), ×××ר×××Ŗ ××××× ×××× × ×פ××. ××”××× ××××× ×Ŗ××× ××××ר פ×× ××××Ŗ× ××× × ×©×××× ×× ××Ŗ ×צ××× ×¢× ×ש××× ××§××××Ŗ ××× ××Ŗ ×ש××× ××××, ××שר ×× ××× ××ש×××Ŗ עש×× ×××××Ŗ ×××פה:
class QuizTurn(BaseModel):
"""One step of the conversational quiz."""
feedback: str = Field(
description="Assessment of the user's previous answer; empty for the "
"first question.",
)
score: int = Field(
ge=0,
le=10,
description="Score for the previous answer, 0 for the first question.",
)
next_question: str | None = Field(
description="The next question to ask; null when the quiz is over.",
)
ā ×××ר×
×ש××× ×××××ר ×××××Ø× ×פ×××Ŗ×× ×שת××©×Ŗ× ×הפר×××Ŗ python-telegram-bot. ××§×× ×©××Ŗ××ר ××××Ø× ×©××ר ××§××ׄ main.py.
××¢×××× ×¢× ××××Ø× ××××”×”×Ŗ ×¢× Handlers, ××××ר ×× ×× × ×Ø×ש××× ×¤×× ×§×¦×××Ŗ ש×× × ×©××קר×× ×ש××ר××¢×× ××”××××× ××§×Ø× ×××××Ø× ××××××:
app.add_handler(CommandHandler("start", on_start))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, on_text))
×שש××××× ×¤×§×××Ŗ /start × ×¤×¢×× ××Ŗ ×פ×× ×§×¦×× on_start. ×שש××××× ××§×”× ××ש×× ×©××× × ×¤×§××× × ×¤×¢×× ××Ŗ ×פ×× ×§×¦×× on_text. פ×× ×§×¦×××Ŗ ×××Ŗ××× ×©××××Ŗ ××××¢×Ŗ פת××× ×פ×× ×§×¦×××Ŗ קר×××Ŗ ×××§×”× ××××§×Ŗ ×× ×××§×”× × ×Ø×× ××× URL ××× ×Ŗ×Ŗ××× ×©××× ×××©× ×¢× ××”××× ×¢× ××××ר ×©× ×©××, ××× ××§×”× ××ר × ××©× ××Ŗ×ר תש××× ×ש××× ×©××”××× ×××× ×©××.
ā ×¢×ש×× ××Ŗ×
1. ×××Ø× ×¢× botfather, ×¦×Ø× ××× ××ש ×××××Ø× ××פע××× ××Ŗ ××”××× ××××× ×¢× ××××× × ×©××× ××× ×××ר ×¢× ×××× ×©×××. ××ר×× ×פ××Ø× ×××:
https://paths.grasp.study/public-modules/2989b86f-e56c-4677-b75d-5042f0666827/lessons/13e343e2-1bb8-43f5-abc0-08695aaff682
2. ×××× ×××צר ש××× ×××©× ×××Ø× ×× ××××¢×. ×¢××× × ××Ŗ ××§×× ×× ×©×××× ××× × ××Ŗ עשר ×ש××××Ŗ ××× ×¢× ×§×××Ŗ ××××ר. ×ש××: ×× ××תר×× ××Ŗ ×××הר×× ××Ŗ ×©× ×× ××ש×?
3. ××× ×שת×ש×× ×××××× ××©× ××Ŗ ××Ŗ ××Ŗ× ××××Ŗ ××××, ×××©× ×××צר ×הפר ש×× × ×©× ×©××××Ŗ ×× ××ר×× ×××× ××§×× ×Ŗ×©××××Ŗ ×× × ××× ××Ŗ, ×× ×פ××× ××ש××£ ××××¢ ש×× ×××ר ×××××Ŗ × ××ש ×××? ש××§× ×¢× ××××, × ×”× ×××¢×× ×× ×××צ×× × ×§××××Ŗ ×Ŗ×רפ×.
4. ×× ××§×Ø× ×× ×Ŗ× ×”× ×××××£ ××Ŗ ×××× ××× ×©××× ××Ŗ×× ×ר××¢ ×שרת ××¢× × ×©× Vercel? ×¢× ×××× ×©×Ø×Ŗ×× ×פשר ××ר×ׄ ××Ŗ ×××× ×××? ×× ×¦×Ø×× ××¢××× ××× ××ר×ׄ ×××Ŗ× ××Ŗ×ר AWS Lambda Function ×× Vercel Function? | 110 |
| 18 | š ××× 8: ×××× ××× ×רק×××× ×××××ר×
×××ר×× ××Ŗ ××”××× ××××× ×©××Ŗ××× × ×××Ŗ× ××Ŗ ××”×ר×? ××”××× ××§× ×××ר ××רשת ××צר ××× × ×©××××Ŗ ××× × ××× ×©× ××× ××××× ×××ר ×צ××Ø× ××¢××× ××תר. ××”××× ×©× ×××× ××× ××Ø×”× ××ר×××Ŗ ×©× ×××Ŗ× ××”×××, ××¤×¢× ×× ×Ø×§ ש××× ×©××××Ŗ ××××Ø× ××× ×× × ×©×ר ××Ŗ×× ×××××§ ××Ŗ ×תש××××Ŗ ×××× ××Ŗ×× ××××ר×.
×§×× ×××××× ××§×ש×ר:
https://github.com/ynonp/pydanticai-demos/tree/main/08-interactice-telegram-quiz-agent
ā ×× ×× ×× × ××× ××
×××× ×××× ×ש××× ×¢× ×שת×ש×× ×Ø×××, ×× ×שת×ש ×××× ×ש××× ××× ×§ ××××ר, ×××× ××ש×× ××Ŗ ××××ר ××××× 10 ש××××Ŗ ××× × ×¢× ×××Ŗ× ×××ר. ××ר ×× ×××× ×ש×× ××שת×ש ש××× ×Ø×ש×× ×, ×××× ×תש××× ××× ×ש×× ××Ŗ ×ש××× ×××× ××× ×¢× ××”××× ×××××.
ā ×××”×× ×ש××××Ŗ
× ×§×××Ŗ ×××Ŗ××× ××”×§××Ø× ×××× ××× ××§××ׄ store.py ש×× ×× ××Ŗ ×ש××××Ŗ. ××§××ׄ ××”× ××× ×©××ר Dictionary ×××ר×× ×¢× ×× ×ש××××Ŗ ×©× ×× ××שת×ש××. ××¢×Ŗ×× ×פשר ×××× ×××¢××ר ××Ŗ ×× ×××”××” × ×Ŗ×× ×× ××”××ר ×× × redis. ×× ×××××ש:
class InMemoryKVStore:
"""A ``KVStore`` backed by a plain dict. State is lost when the process exits."""
def __init__(self) -> None:
self._data: dict[str, Any] = {}
def get(self, key: str, default: Any = None) -> Any:
return self._data.get(key, default)
def set(self, key: str, value: Any) -> None:
self._data[key] = value
def has(self, key: str) -> bool:
return key in self._data
def delete(self, key: str) -> None:
self._data.pop(key, None)
ā ××× ×©× ×××× - ××§××ׄ quiz
××§××ׄ quiz.py × ××¦× ×××× ×©× ××××. ××§××ׄ ××××ר ××”× ××× ×©×Ŗ× ×¤×× ×§×¦×××Ŗ:
1. ××Ŗ×××Ŗ ××××
2. ××פ×× ×תש×××
פ×× ×§×¦×××Ŗ ××Ŗ×××Ŗ ××××× ××ש××Ŗ ××Ŗ ××××ר ×××× × ××× × ××Ŗ ×ש××× ×ר×ש×× ×:
async def start_quiz(
store: KVStore, agent: Agent[None, QuizTurn], chat_id: int | str, url: str
) -> list[str]:
"""Fetch the article and ask the first question."""
try:
title, text = fetch_article(url)
except ValueError as exc:
return [f"ā ļø {exc}"]
result = await agent.run(SEED_PROMPT.format(article=text))
turn = result.output
store.set(
_key(chat_id),
{
"title": title,
"q_number": 1,
"total_score": 0,
"status": "active",
"pai_history": _dump_history(result),
},
)
return [
f"š Quizzing you on: *{title}*\nSend /start anytime to begin a new one.",
f"Question 1/{TOTAL_QUESTIONS}:\n{turn.next_question}",
]
פ×× ×§×¦×××Ŗ ×××פ×× ×תש××× ××פשת ××Ŗ ×ש××× ×× ×××××Ŗ, ×××× ×× ×הפר ×ש××× ×ש××××Ŗ ××”××× ××Ŗ ×תש××× ×©××שת×ש ש××. ××ר ×× ××× ×©××××Ŗ פ××××§ ×××Ŗ ×ש××× ××××:
async def handle_answer(
store: KVStore, agent: Agent[None, QuizTurn], chat_id: int | str, text: str
) -> list[str]:
"""Evaluate the user's answer and ask the next question (or wrap up)."""
session = store.get(_key(chat_id))
if not session or session.get("status") != "active":
return [
"Send me an article link (starting with http) and I'll quiz you "
"on it."
]
q_number = session["q_number"]
final = q_number >= TOTAL_QUESTIONS
prompt = text
if final:
prompt += FINAL_CONTROL.format(n=q_number, total=TOTAL_QUESTIONS)
history = _load_history(session)
result = await agent.run(prompt, message_history=history)
turn = result.output
total_score = session["total_score"] + turn.score
session["total_score"] = total_score
session["pai_history"] = _dump_history(result)
feedback_line = f"š {turn.feedback} (Score: {turn.score}/10)"
if final or turn.next_question is None:
session["status"] = "finished"
store.set(_key(chat_id), session)
max_score = TOTAL_QUESTIONS * 10
scorecard = (
f"š Quiz complete!\n\n"
f"Final score: *{total_score}/{max_score}*\n\n"
f"Send another article link to play again."
)
return [feedback_line, scorecard]
session["q_number"] = q_number + 1
store.set(_key(chat_id), session)
return [
feedback_line,
f"Question {q_number + 1}/{TOTAL_QUESTIONS}:\n{turn.next_question}",
] | 76 |
| 19 | https://www.tocode.co.il/blog/2026-08-08-quiz-telegram-agent | 89 |
| 20 | ctx: RunContext[Deps], file: str, existing_text: str, replacement_text: str
) -> str:
"""Replace the single, exact occurrence of ``existing_text`` in ``file``."""
path = _resolve(ctx.deps.work_dir, file)
if not path.is_file():
return f"Error: no such file: {file}"
text = path.read_text(encoding="utf-8")
count = text.count(existing_text)
if count == 0:
return f"Error: existing_text not found in {file}"
if count > 1:
return (
f"Error: existing_text appears {count} times in {file}; "
"add more surrounding context to make it unique"
)
path.write_text(text.replace(existing_text, replacement_text), encoding="utf-8")
return f"Edited {file}"
ā ×פע××Ŗ פק×××Ŗ ×ער××Ŗ
×××× ×××ר××, bash, ×פע×× ×¤×§×××Ŗ ×ער××Ŗ. ×¤× ×ש ×× × ×©× × ××Ŗ×ר××:
1. ×¢××× × ××××× ×©×פק××× ×× ×Ŗ××Ŗ×§×¢, ×××× ×× ×× × ××××ר×× timeout.
2. ×¢××× × ××××× ×©×פק××× ×× ×Ŗ×××ר פ×× ×ר×× ×××. ×× ×××× ××§××ׄ ×©× ×©×ר ×¢× ××××”×§, פ×× ×©× ×¤×§××× × ×¢×× ×××Ø× ×©×פע×× × ×××Ŗ×, ×××× ×××× ×××Ŗ× ××Ŗ ×פ×× ××§××ׄ ××× × ×××¢××ר ××Ŗ ×©× ××§××ׄ ××”×××. ×× ×× ×פ×× ×× ×ר×× ××× ××”××× ×××× ×קר×× ×××Ŗ× ××¢×Ø× ×©×××ר ×××××. ×× ×פ×× ×× ×ר×× ××”××× ×צ××Ø× ××פע×× ××Ŗ ××× read_file ×××Ø× ×פע××Ŗ פק×××Ŗ ××ער××Ŗ ××קר×× ××Ŗ ×××ש×.
×× ×§×× ××××:
def bash(ctx: RunContext[Deps], command: str) -> str:
"""Run a shell command in the project directory and return its output.
Returns the first 10,000 chars of combined stdout+stderr. The full
output is saved to a temp file whose path is reported when truncated,
so it can be read in full later with read_file.
"""
try:
proc = subprocess.run(
command,
shell=True,
cwd=ctx.deps.work_dir,
capture_output=True,
text=True,
timeout=BASH_TIMEOUT,
)
except subprocess.TimeoutExpired:
return f"Error: command timed out after {BASH_TIMEOUT}s"
output = proc.stdout + proc.stderr
header = f"(exit code {proc.returncode})\n"
if len(output) <= MAX_OUTPUT:
return header + output
with tempfile.NamedTemporaryFile(
mode="w", delete=False, suffix=".txt", prefix="minicoder-", encoding="utf-8"
) as fh:
fh.write(output)
tmp_path = fh.name
return (
header
+ output[:MAX_OUTPUT]
+ f"\n\n[output truncated; full output saved to {tmp_path} ā "
"read it with read_file]"
)
ā ×¢×ש×× ××Ŗ×
1. ×פע××× ××Ŗ ××”××× ×¢× ××××× × ×©××× ××× × ××¢××Ø×Ŗ× ×ש××§. ××× ××× ×צ×××? × ×”× ××××××£ ×××× ××××§× ×××¦× ×××××× ×©×× ×× ××Ŗ×××××× ×¢× ××ש×××.
2. ×××”××¤× ××”××× "××ר××" ×× ×©××”××× ×××Ŗ×× ×¤×Ø××× ×ש×××× ×©××× ×××× ×¢× ××§×× ××§××ׄ ××§×”×. ×××”××¤× ××Ŗ ×§××ׄ ×××§×”× ××× ×פר×××¤× ××××¤× ×××××××. ××× ×××ר×× ×¢××ר ××”××× ×××Ŗ×× ×§×× ××× ××תר?
3. ×××”××¤× ×Ŗ×××× ×× ×××× ×הפר ש××××Ŗ ×××§×××. פק×××Ŗ /new פ××Ŗ××Ŗ ש××× ××ש×, פק×××Ŗ /list ×ר×× ××Ŗ ×× ×ש××××Ŗ ×פק×××Ŗ /resume ×××רת ×ש××× ××רת. | 98 |
