דילוג לתוכן
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר
עיצובים
  • בהיר
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • כהה
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
מתמחים טופ
  1. דף הבית
  2. כללי - עזרה הדדית
  3. בירור | יצירת אלגוריתם/כללים למנוע חיפוש

בירור | יצירת אלגוריתם/כללים למנוע חיפוש

מתוזמן נעוץ נעול הועבר כללי - עזרה הדדית
59 פוסטים 8 כותבים 575 צפיות 5 עוקבים
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • ע"ה דכו"עע ע"ה דכו"ע

    @עידו300 כתב:

    קלוד עשה ניסוי עם החיפוש הוקטורי, התוצאות לא טובות בכלל... לא מתאים לכזה דבר, למרות שזה מוזר.

    איך הוא חילק את השאילת לעמודות או יותר נכון איך הוא חיבר את העמודות באינדקס? הוא חישבן את זה בכלל כשהוא שלח את זה להטמעה וקטורית?

    ע מנותק
    ע מנותק
    עידו300
    כתב נערך לאחרונה על ידי
    #49

    @ע-ה-דכו-ע שיתבייש לעצמו, הכניס רק את שם הספר, לא חשב על זה בכלל.

    עכשיו עושה בדיקה חוזרת, אמרתי לו שיתכנן הפעם את צעדיו.

    תגובה 1 תגובה אחרונה
    0
    • ע מנותק
      ע מנותק
      עידו300
      כתב נערך לאחרונה על ידי
      #50

      מהבדיקה האחרונה יוצא שהבעיה העקרית היא שחיפוש וקטורי תמיד מחזיר תשובה, גם אם היא שגויה לחלוטין, מה שגרוע מאוד במקרה שלי.

      ע"ה דכו"עע תגובה 1 תגובה אחרונה
      0
      • ע עידו300

        מהבדיקה האחרונה יוצא שהבעיה העקרית היא שחיפוש וקטורי תמיד מחזיר תשובה, גם אם היא שגויה לחלוטין, מה שגרוע מאוד במקרה שלי.

        ע"ה דכו"עע מנותק
        ע"ה דכו"עע מנותק
        ע"ה דכו"ע
        כתב נערך לאחרונה על ידי
        #51

        @עידו300 כתב:

        מהבדיקה האחרונה יוצא שהבעיה העקרית היא שחיפוש וקטורי תמיד מחזיר תשובה, גם אם היא שגויה לחלוטין, מה שגרוע מאוד במקרה שלי.

        יש אחוזי התאמה, מ0 עד אחד

        ע תגובה 1 תגובה אחרונה
        0
        • ע"ה דכו"עע ע"ה דכו"ע

          @עידו300 כתב:

          מהבדיקה האחרונה יוצא שהבעיה העקרית היא שחיפוש וקטורי תמיד מחזיר תשובה, גם אם היא שגויה לחלוטין, מה שגרוע מאוד במקרה שלי.

          יש אחוזי התאמה, מ0 עד אחד

          ע מנותק
          ע מנותק
          עידו300
          כתב נערך לאחרונה על ידי
          #52

          @ע-ה-דכו-ע תשובות שגויות נותנות ציון גבוה כמו תשובות נכונות... תשובות נכונות קיבלו ציון בין 0.73 ל-0.88, ושגויות עד 0.844

          מה לגבי זה?

          עידו300 כתב:

          תראו מה יש עד עכשיו, בקשתי מקלוד שיתמצת בשביל להראות לחבר שיחווה דעתו.

          לדעתי עשה שם שטויות, אבל אני לא מבין בזה.

          בעקרון הוא חילק את זה ל-4 לא ל-2.

          מפת החיפוש.pdf

          ע"ה דכו"עע תגובה 1 תגובה אחרונה
          0
          • ע עידו300

            @ע-ה-דכו-ע תשובות שגויות נותנות ציון גבוה כמו תשובות נכונות... תשובות נכונות קיבלו ציון בין 0.73 ל-0.88, ושגויות עד 0.844

            מה לגבי זה?

            עידו300 כתב:

            תראו מה יש עד עכשיו, בקשתי מקלוד שיתמצת בשביל להראות לחבר שיחווה דעתו.

            לדעתי עשה שם שטויות, אבל אני לא מבין בזה.

            בעקרון הוא חילק את זה ל-4 לא ל-2.

            מפת החיפוש.pdf

            ע"ה דכו"עע מנותק
            ע"ה דכו"עע מנותק
            ע"ה דכו"ע
            כתב נערך לאחרונה על ידי
            #53

            @עידו300 כתב:

            @ע-ה-דכו-ע תשובות שגויות נותנות ציון גבוה כמו תשובות נכונות... תשובות נכונות קיבלו ציון בין 0.73 ל-0.88, ושגויות עד 0.844

            שגויות שאין ביניהם שום קשר? אולי באמת יש קשר סמנטי, נניח עוז והדר יכול בהחלט להיות קרוב סמנטית למילה ספר

            באיזה מודל הטמעה השתמשת? ואיזה מנוע חיפוש?

            ע תגובה 1 תגובה אחרונה
            0
            • ע"ה דכו"עע ע"ה דכו"ע

              @עידו300 כתב:

              @ע-ה-דכו-ע תשובות שגויות נותנות ציון גבוה כמו תשובות נכונות... תשובות נכונות קיבלו ציון בין 0.73 ל-0.88, ושגויות עד 0.844

              שגויות שאין ביניהם שום קשר? אולי באמת יש קשר סמנטי, נניח עוז והדר יכול בהחלט להיות קרוב סמנטית למילה ספר

              באיזה מודל הטמעה השתמשת? ואיזה מנוע חיפוש?

              ע מנותק
              ע מנותק
              עידו300
              כתב נערך לאחרונה על ידי
              #54

              @ע-ה-דכו-ע

              1. ספר עם שם דומה, אבל ספר אחר: 8 טעויות
                הלקוח ביקש -> החיפוש הוקטורי החזיר
                רמב"ן המבואר -> רמב"ם מבואר המורחב, שופטים (אבל)
                סט רמב"ן המבואר -> סט רמב"ם מבואר כחול (34 כר')
                רמב"ן המבואר על התורה -> סט רמב"ן מנוקד על התורה (כלומר מהדורה אחרת, עוד נסבל אבל לא תקין).
                ערוך השלחן -> שולחן ערוך יומי בכרך אחד
                בית יוסף -> ראש יוסף מסכת ביצה (למרות שאין ספר בית יוסף עד כמה שזכור לי, עדיין הוא לא היה אמור למצוא את זה)
                ספר חסידים -> סט אוצר החסידות (29 כר')
                תלמוד בבלי -> חוברת יד משס תלמודו, בבא בתרא
                משנה ברורה (נשמע "משנא ברורה") -> חוברת משנ"ב חנוכה (בתכלס זה נכון אבל זו לא התשובה הנכונה כי אנחנו מצפים לסטים הסונדרטיים ולא לאיזה חוברת לא ידועה שהוציאו)
                את "רמב"ן" ו"רמב"ם" הוא מבלבל בשתי הגרסאות.

              2. שאילתה שמתארת ספר: 2 טעויות
                הלקוח ביקש -> החיפוש הוקטורי החזיר
                ספר מוסר על מידות טובות -> שכל טוב ב (מדרש על התורה)
                משניות עם פירוש מבואר -> פנינים משנ"ב המבואר (משנה ברורה ולא משניות)

              3. שיבוש בשמיעה או כתיב שגוי: 4 טעויות
                הלקוח ביקש -> החיפוש הוקטורי החזיר
                שוקאמין (ש"ס חתנים, איך ג'ימני הגיע לשוקאמין, אין לי מושג...) -> סידור השלם סקאי, אשכנז (למען האמת אני לא מצפה שמישהו כן יבין את זה...)
                שף חתנים (ש"ס חתנים) -> אוצר מחמדים חלק ד
                מילתך בדרך (בלכתך בדרך) -> מילתא חדתא במדבר
                דף יומי (לעוז והדר יש כאלו גמרות, לדוגמא "ברכות מנוקד מאורות דף היומי") -> אור החיים כרך אחד לוח יומי

              4. ספר שלא קיים בקטלוג: 20 מתוך 20 טעויות
                על כל שאילתה הוא החזיר ספר כלשהו. כמה דוגמאות:

              הלקוח ביקש -> החיפוש הוקטורי החזיר
              נתיבות המשפט -> נתיבות דעת בראשית
              אגרות משה -> תורת משה, אלשיך המבואר ויקרא
              ים של שלמה -> מנחת שלמה ב"מ א
              מורה נבוכים -> רמב"ם מבואר המורחב, שופטים (מלכים)
              שמירת שבת כהלכתה -> זמירות שבת אלבומי יגל יעקב
              מקדחה נטענת -> סט נ"ך מקראות גדולות (25 כר')
              שעון קיר -> 5 זמירות שבת יגל יעקב במעמד

              קלוד יצר בשביל זה מנוע חיפוש, לא השתמש במנוע קיים.

              המודל הוא מה שדיברנו עליו EmbeddingGemma 2 של גוגל, בגרסת ONNX הדחוסה (q4). הוא רץ על המעבד של השרת דרך הספרייה transformers.js 4.3.1.

              את השורות הבאות לא הבנתי אז הבאתי כלשונו:
              לכל שאילתה חישבתי ציון דמיון מול כל 4,077 הספרים, ומיינתי לפי הציון.
              מה זה אומר על הטעויות: כל אחד מ-4,077 הספרים קיבל ציון, אז אין כאן טעויות של קירוב. כל טעות נובעת מהמודל עצמו. שני גורמים אפשריים לא בדקתי: הדחיסה של המודל (q4), ותבנית המסמך שבחרתי.

              ע"ה דכו"עע תגובה 1 תגובה אחרונה
              0
              • ע עידו300

                @ע-ה-דכו-ע

                1. ספר עם שם דומה, אבל ספר אחר: 8 טעויות
                  הלקוח ביקש -> החיפוש הוקטורי החזיר
                  רמב"ן המבואר -> רמב"ם מבואר המורחב, שופטים (אבל)
                  סט רמב"ן המבואר -> סט רמב"ם מבואר כחול (34 כר')
                  רמב"ן המבואר על התורה -> סט רמב"ן מנוקד על התורה (כלומר מהדורה אחרת, עוד נסבל אבל לא תקין).
                  ערוך השלחן -> שולחן ערוך יומי בכרך אחד
                  בית יוסף -> ראש יוסף מסכת ביצה (למרות שאין ספר בית יוסף עד כמה שזכור לי, עדיין הוא לא היה אמור למצוא את זה)
                  ספר חסידים -> סט אוצר החסידות (29 כר')
                  תלמוד בבלי -> חוברת יד משס תלמודו, בבא בתרא
                  משנה ברורה (נשמע "משנא ברורה") -> חוברת משנ"ב חנוכה (בתכלס זה נכון אבל זו לא התשובה הנכונה כי אנחנו מצפים לסטים הסונדרטיים ולא לאיזה חוברת לא ידועה שהוציאו)
                  את "רמב"ן" ו"רמב"ם" הוא מבלבל בשתי הגרסאות.

                2. שאילתה שמתארת ספר: 2 טעויות
                  הלקוח ביקש -> החיפוש הוקטורי החזיר
                  ספר מוסר על מידות טובות -> שכל טוב ב (מדרש על התורה)
                  משניות עם פירוש מבואר -> פנינים משנ"ב המבואר (משנה ברורה ולא משניות)

                3. שיבוש בשמיעה או כתיב שגוי: 4 טעויות
                  הלקוח ביקש -> החיפוש הוקטורי החזיר
                  שוקאמין (ש"ס חתנים, איך ג'ימני הגיע לשוקאמין, אין לי מושג...) -> סידור השלם סקאי, אשכנז (למען האמת אני לא מצפה שמישהו כן יבין את זה...)
                  שף חתנים (ש"ס חתנים) -> אוצר מחמדים חלק ד
                  מילתך בדרך (בלכתך בדרך) -> מילתא חדתא במדבר
                  דף יומי (לעוז והדר יש כאלו גמרות, לדוגמא "ברכות מנוקד מאורות דף היומי") -> אור החיים כרך אחד לוח יומי

                4. ספר שלא קיים בקטלוג: 20 מתוך 20 טעויות
                  על כל שאילתה הוא החזיר ספר כלשהו. כמה דוגמאות:

                הלקוח ביקש -> החיפוש הוקטורי החזיר
                נתיבות המשפט -> נתיבות דעת בראשית
                אגרות משה -> תורת משה, אלשיך המבואר ויקרא
                ים של שלמה -> מנחת שלמה ב"מ א
                מורה נבוכים -> רמב"ם מבואר המורחב, שופטים (מלכים)
                שמירת שבת כהלכתה -> זמירות שבת אלבומי יגל יעקב
                מקדחה נטענת -> סט נ"ך מקראות גדולות (25 כר')
                שעון קיר -> 5 זמירות שבת יגל יעקב במעמד

                קלוד יצר בשביל זה מנוע חיפוש, לא השתמש במנוע קיים.

                המודל הוא מה שדיברנו עליו EmbeddingGemma 2 של גוגל, בגרסת ONNX הדחוסה (q4). הוא רץ על המעבד של השרת דרך הספרייה transformers.js 4.3.1.

                את השורות הבאות לא הבנתי אז הבאתי כלשונו:
                לכל שאילתה חישבתי ציון דמיון מול כל 4,077 הספרים, ומיינתי לפי הציון.
                מה זה אומר על הטעויות: כל אחד מ-4,077 הספרים קיבל ציון, אז אין כאן טעויות של קירוב. כל טעות נובעת מהמודל עצמו. שני גורמים אפשריים לא בדקתי: הדחיסה של המודל (q4), ותבנית המסמך שבחרתי.

                ע"ה דכו"עע מנותק
                ע"ה דכו"עע מנותק
                ע"ה דכו"ע
                כתב נערך לאחרונה על ידי
                #55

                @עידו300 חוץ מהמקדחה והשעון קיר כל שאר השאילתות באמת התשובה מאוד קרובה מבחינה וקטורית לכאו', אולי אם תכוונן מודל לנתונים שלך זה יעזור יותר...

                השאלה אם אפשר בכלל לסמוך על קלוד שהמנוע שהוא עשה עובד בכלל, איך הוא כתב אותו? באיזה שפה? איך הוא בכלל שמר את האינדקס הוקטורי?

                ע תגובה 1 תגובה אחרונה
                1
                • ע"ה דכו"עע ע"ה דכו"ע

                  @עידו300 חוץ מהמקדחה והשעון קיר כל שאר השאילתות באמת התשובה מאוד קרובה מבחינה וקטורית לכאו', אולי אם תכוונן מודל לנתונים שלך זה יעזור יותר...

                  השאלה אם אפשר בכלל לסמוך על קלוד שהמנוע שהוא עשה עובד בכלל, איך הוא כתב אותו? באיזה שפה? איך הוא בכלל שמר את האינדקס הוקטורי?

                  ע מנותק
                  ע מנותק
                  עידו300
                  כתב נערך לאחרונה על ידי
                  #56

                  @ע-ה-דכו-ע כתב בJS
                  מה זאת אומרת איך הוא שמר? הוא השתמש בספריה הרשמית כמדומני.

                  אם זה משנה, ניסיתי לשלוף מה"חשיבה" שלו את מה שהוא עשה, מקוה שאלו הקודים הנכונים.
                  זה הקוד של ההטמעה:

                  // מטמיע את כל ספרי העותק בגרסת מסמך נתונה. קריאה בלבד מהמסד.
                  //   node embed.mjs <db> <variant: name|desc|desc_sup> [dtype]
                  import { pipeline, env } from '@huggingface/transformers';
                  import Database from '/var/www/responsa/node_modules/better-sqlite3/lib/index.js';
                  import fs from 'fs';
                  
                  env.cacheDir = new URL('./models/', import.meta.url).pathname;
                  const [dbPath, variant, dtype = 'q4'] = process.argv.slice(2);
                  const db = new Database(dbPath, { readonly: true });
                  const rows = db.prepare(`SELECT b.id, b.name, b.notes, s.name AS supplier
                    FROM books b LEFT JOIN suppliers s ON s.id = b.supplier_id ORDER BY b.id`).all();
                  
                  // "תיאור:" מופיע בראש כמעט כל הערה — רעש שחוזר בכל המסמכים
                  const clean = (t) => (t || '').replace(/^\s*תיאור\s*:\s*/, '').replace(/\s+/g, ' ').trim();
                  const DOC = {
                    name: (r) => `title: none | text: ${r.name}`,
                    desc: (r) => `title: ${r.name} | text: ${clean(r.notes) || r.name}`,
                    desc_sup: (r) => `title: ${r.name} | text: ${[clean(r.notes), r.supplier && `הוצאה: ${r.supplier}`].filter(Boolean).join('. ') || r.name}`,
                  };
                  if (!DOC[variant]) throw new Error(`גרסה לא מוכרת: ${variant}`);
                  
                  const ex = await pipeline('feature-extraction', 'onnx-community/embeddinggemma-2-ONNX', { device: 'cpu', dtype });
                  const t0 = Date.now(); const out = []; let peak = 0;
                  const BATCH = 8;
                  for (let i = 0; i < rows.length; i += BATCH) {
                    const batch = rows.slice(i, i + BATCH);
                    const e = await ex(batch.map(DOC[variant]), { pooling: 'mean', normalize: true });
                    e.tolist().forEach((v, j) => out.push({ id: batch[j].id, name: batch[j].name, v: v.map((x) => +x.toFixed(5)) }));
                    peak = Math.max(peak, process.memoryUsage().rss);
                    if (i % 400 === 0) console.log(`${variant} ${i}/${rows.length} ${Math.round((Date.now() - t0) / 1000)}s rss ${Math.round(peak / 1e6)}MB`);
                  }
                  fs.writeFileSync(`vectors-${variant}-${dtype}.json`, JSON.stringify(out));
                  console.log(`DONE ${variant} ${out.length} sec ${Math.round((Date.now() - t0) / 1000)} peak ${Math.round(peak / 1e6)}MB`);
                  

                  וזה החיפוש:

                  // ניסוי חוזר: חיפוש וקטורי בגרסאות מסמך שונות מול החיפוש הקיים (קוד הענף).
                  // קריאה בלבד: עותק הגיבוי, וקטורים שחושבו מראש, הקורפוס מהריפו.
                  //
                  // node eval.mjs <db> <variant,...> [dtype]
                  
                  import { pipeline, env } from '@huggingface/transformers';
                  import Database from '/var/www/responsa/node_modules/better-sqlite3/lib/index.js';
                  import fs from 'fs';
                  
                  import {
                    compileQuery,
                    tokenize,
                  } from '/var/www/responsa/apps/catalog/lib/search.js';
                  
                  import {
                    searchBooks,
                  } from '/var/www/responsa/apps/voice/facts/book-search.js';
                  
                  import {
                    toCustomerBook,
                  } from '/var/www/responsa/apps/voice/facts/catalog-client.js';
                  
                  env.cacheDir = new URL('./models/', import.meta.url).pathname;
                  
                  const [dbPath, variantsArg, dtype = 'q4'] =
                    process.argv.slice(2);
                  
                  const variants = variantsArg.split(',');
                  
                  const db = new Database(dbPath, {
                    readonly: true,
                  });
                  
                  const rows = db.prepare(`
                    SELECT
                      b.id,
                      b.name,
                      b.category,
                      b.notes,
                      s.name AS supplier_name
                    FROM books b
                    LEFT JOIN suppliers s
                      ON s.id = b.supplier_id
                    ORDER BY b.name, b.id
                  `).all();
                  
                  const {
                    queries,
                  } = JSON.parse(
                    fs.readFileSync(
                      '/var/www/responsa/apps/voice/scripts/search-corpus.json',
                      'utf8'
                    )
                  );
                  
                  function engineCatalog(term) {
                    const c = compileQuery(term);
                  
                    if (c.empty) {
                      return rows;
                    }
                  
                    return rows
                      .filter((b) =>
                        c.test(
                          tokenize(
                            [
                              b.name,
                              b.category,
                              b.supplier_name,
                              b.notes,
                            ]
                              .map((x) => x || '')
                              .join(' ')
                          )
                        )
                      )
                      .map((b, i) => ({
                        b,
                        i,
                        s: c.score(
                          tokenize(b.name || '')
                        ),
                      }))
                      .sort(
                        (x, y) =>
                          y.s - x.s || x.i - y.i
                      )
                      .map((e) => e.b);
                  }
                  
                  const client = {
                    async search(term, limit = 25) {
                      const all = engineCatalog(term);
                  
                      return {
                        ok: true,
                        total: all.length,
                        books: all
                          .slice(0, limit)
                          .map((b) =>
                            toCustomerBook({
                              ...b,
                              pricing: {
                                effective: 1,
                              },
                            })
                          ),
                      };
                    },
                  };
                  
                  const ex = await pipeline(
                    'feature-extraction',
                    'onnx-community/embeddinggemma-2-ONNX',
                    {
                      device: 'cpu',
                      dtype,
                    }
                  );
                  
                  const lat = [];
                  const qvecs = new Map();
                  
                  for (const { q } of queries) {
                    const t = Date.now();
                  
                    qvecs.set(
                      q,
                      (
                        await ex(
                          [
                            `task: search result | query: ${q}`,
                          ],
                          {
                            pooling: 'mean',
                            normalize: true,
                          }
                        )
                      ).tolist()[0]
                    );
                  
                    lat.push(Date.now() - t);
                  }
                  
                  const dot = (a, b) => {
                    let s = 0;
                  
                    for (let i = 0; i < a.length; i++) {
                      s += a[i] * b[i];
                    }
                  
                    return s;
                  };
                  
                  const lexical = [];
                  
                  for (const item of queries) {
                    const r = await searchBooks(
                      item.q,
                      {
                        client,
                        limit: 5,
                      }
                    );
                  
                    lexical.push(
                      r.books.map((b) => b.title)
                    );
                  }
                  
                  const report = {
                    dtype,
                    n: queries.length,
                  
                    latencyMs: {
                      median:
                        lat.sort((a, b) => a - b)[
                          lat.length >> 1
                        ],
                  
                      max: lat.at(-1),
                    },
                  
                    variants: {},
                  };
                  
                  for (const variant of variants) {
                    const docs = JSON.parse(
                      fs.readFileSync(
                        `vectors-${variant}-${dtype}.json`,
                        'utf8'
                      )
                    );
                  
                    const per = queries.map(
                      (item, k) => {
                        const qv = qvecs.get(item.q);
                  
                        const top = docs
                          .map((d) => ({
                            name: d.name,
                            s: dot(qv, d.v),
                          }))
                          .sort(
                            (a, b) => b.s - a.s
                          )
                          .slice(0, 5);
                  
                        const re =
                          item.expect === null
                            ? null
                            : new RegExp(item.expect);
                  
                        const lex = lexical[k];
                  
                        return {
                          q: item.q,
                          src: item.src,
                  
                          positive: re !== null,
                  
                          lexTop1:
                            re
                              ? lex.length > 0 &&
                                re.test(lex[0])
                              : lex.length === 0,
                  
                          lexEmpty:
                            lex.length === 0,
                  
                          vTop1:
                            re
                              ? re.test(top[0].name)
                              : false,
                  
                          vTop5:
                            re
                              ? top.some((t) =>
                                  re.test(t.name)
                                )
                              : false,
                  
                          score:
                            +top[0].s.toFixed(3),
                  
                          top:
                            top[0].name,
                        };
                      }
                    );
                  
                    const pos =
                      per.filter(
                        (p) => p.positive
                      );
                  
                    const neg =
                      per.filter(
                        (p) => !p.positive
                      );
                  
                    const desc =
                      per.filter(
                        (p) => p.src === 'תיאור'
                      );
                  
                    const cnt = (arr, f) =>
                      arr.filter(f).length;
                  
                    const right =
                      per
                        .filter((p) => p.vTop1)
                        .map((p) => p.score)
                        .sort((a, b) => a - b);
                  
                    const wrong =
                      per
                        .filter((p) => !p.vTop1)
                        .map((p) => p.score)
                        .sort((a, b) => a - b);
                  
                    const fallback =
                      per.filter(
                        (p) => p.lexEmpty
                      );
                  
                    const sweep = [];
                  
                    for (
                      let tau = 0.75;
                      tau <= 0.951;
                      tau += 0.025
                    ) {
                      const offered =
                        fallback.filter(
                          (p) => p.score >= tau
                        );
                  
                      sweep.push({
                        tau: +tau.toFixed(3),
                  
                        offered: offered.length,
                  
                        right: cnt(
                          offered,
                          (p) => p.vTop1
                        ),
                  
                        wrong: cnt(
                          offered,
                          (p) => !p.vTop1
                        ),
                      });
                    }
                  
                    report.variants[variant] = {
                      positives: {
                        n: pos.length,
                  
                        lexTop1: cnt(
                          pos,
                          (p) => p.lexTop1
                        ),
                  
                        vTop1: cnt(
                          pos,
                          (p) => p.vTop1
                        ),
                  
                        vTop5: cnt(
                          pos,
                          (p) => p.vTop5
                        ),
                      },
                  
                      descriptive: {
                        n: desc.length,
                  
                        lexTop1: cnt(
                          desc,
                          (p) => p.lexTop1
                        ),
                  
                        vTop1: cnt(
                          desc,
                          (p) => p.vTop1
                        ),
                  
                        vTop5: cnt(
                          desc,
                          (p) => p.vTop5
                        ),
                      },
                  
                      negatives: {
                        n: neg.length,
                  
                        lexCorrect: cnt(
                          neg,
                          (p) => p.lexTop1
                        ),
                  
                        maxScore:
                          Math.max(
                            ...neg.map(
                              (p) => p.score
                            )
                          ),
                      },
                  
                      scoreSpread: {
                        right: {
                          n: right.length,
                          min: right[0],
                  
                          median:
                            right[
                              right.length >> 1
                            ],
                        },
                  
                        wrong: {
                          n: wrong.length,
                  
                          median:
                            wrong[
                              wrong.length >> 1
                            ],
                  
                          max: wrong.at(-1),
                        },
                  
                        rightAboveAllWrong:
                          cnt(
                            right,
                            (s) =>
                              s > wrong.at(-1)
                          ),
                      },
                  
                      fallback: {
                        n: fallback.length,
                        sweep,
                      },
                  
                      rows: per,
                    };
                  }
                  
                  report.rssMB =
                    Math.round(
                      process.memoryUsage().rss / 1e6
                    );
                  
                  fs.writeFileSync(
                    `eval-${variants.join('+')}-${dtype}.json`,
                    JSON.stringify(
                      report,
                      null,
                      1
                    )
                  );
                  
                  for (
                    const [v, r]
                    of Object.entries(
                      report.variants
                    )
                  ) {
                    console.log(
                      `\n== ${v} (${dtype})`
                    );
                  
                    console.log(
                      'positives',
                      r.positives,
                      '\ndescriptive',
                      r.descriptive,
                      '\nnegatives',
                      r.negatives
                    );
                  
                    console.log(
                      'spread',
                      JSON.stringify(
                        r.scoreSpread
                      )
                    );
                  
                    console.log(
                      'fallback n',
                      r.fallback.n,
                      r.fallback.sweep
                        .map(
                          (s) =>
                            `${s.tau}:${s.right}/${s.wrong}`
                        )
                        .join('  ')
                    );
                  }
                  
                  console.log(
                    '\nlatency',
                    report.latencyMs,
                    'rss',
                    report.rssMB
                  );
                  

                  אם יעזור ניתוח של GPT (שאותי מאוד בילבל) אז יש את זה https://chatgpt.com/share/6ac60b3e-71e0-83ed-bcc0-66dc593b42ab

                  תגובה 1 תגובה אחרונה
                  0
                  • ע מנותק
                    ע מנותק
                    עידו300
                    כתב נערך לאחרונה על ידי
                    #57

                    זה המסלול שהטקסט עובר כיום אחרי ההמלצה כאן בשרשור:

                    הפלט שחוזר מהמודל עובר בדיקת אורך תווים -> ניקוי תוים מסוימים -> תיקונים על פי טבלת תיקונים והחלפות שנצפו בתיעודים (הרי זה תמלול והוא לא תמיד מדוייק אז "בלכתך" הופך ל"מלתך" ו"משנה" ל"משנא") -> נרמול -> הסרת אותיות שימוש מובילות לצורך השוואה (השמיטה -> שמיטה).

                    כל זה במנגנון הדיבור.

                    במנגנון החיפוש עצמו:

                    מורצות שתי שאילתות:
                    1 - כמו שהיא, לדוגמא "שס חתנים"
                    2 - החלפות מסוימות כמו ש"ס -> סט "סט חתנים"

                    אם שתי השאילתות האלו לא הניבו תוצאות אז עוברים לשאילתות אחרות:
                    1 - אותה השאילתא רק בלי מילים תיאוריות (חומש, ספר, מהדורת, הוצאת) ובלי שם הוצאה שנאמר במלואו, לדוגמא "סט חומש מקראות גדולות" יהפוך ל"סט מקראות גדולות".
                    2 - אותו דבר רק עם החלפת ש"ס לסט.

                    כל מילה בשאילתא חייבת להתאים לעמודה אחת לפחות (במילים בנות 4 אותיות יכולה להיות טעות אחת, ומילים בנות 7 אותיות יכולות להיות 2 טעויות) הדירוג בפועל יהיה לפי שם הספר.

                    את השלב הזה לא הבנתי... וחלקו בכלל לא ברור לי למה הוא עשה אותו.
                    מה שכן הבנתי זה שהוא קודם בודק אם שם הספר תואם (לא מבין למה, אם שכחו מה שם הספר וביקשו משהו לפי התיאור והוא מתאים בהערות, למה לזרוק את הספר שנמצא?) ואם לא הוא מוציא אותו מהרשימה. אח"כ עושה מניפולציה על המילים, תלוי בסוג המילה ובאורך שלה ומחליף אותיות שלפעמים נשמעות אותו הדבר.

                    שלב 3 · שער הכיסוי (בערוץ), שבו נופלות ההחלטות
                    כל מועמד שהשרת החזיר עובר בדיקות מול שם הספר בלבד, לא מול ההערות. מועמד שלא עבר נזרק, גם אם השרת אהב אותו.

                    א. מילות תוכן: כל אחת חייבת להימצא בשם
                    מילת תוכן היא מילה בת 3 אותיות לפחות, שאינה מילה מבנית (סט, שס, ספר, כרך, גדול, מנוקד, עור, רוצה, יש וכו'). איך היא נבדקת תלוי באורך הגזע שלה:

                    אורך הגזע מה נדרש
                    2 (מילה של 3 שהגיזום קיצר) הצורה המקורית מופיעה בשם כמילה שלמה
                    3–4 הגזע מוכל בטוקן של השם. בלי שום סובלנות לשגיאה
                    5 ומעלה שני תנאים יחד: השרת היה מתאים אותה, וגם כל ההבדל "נשמע". זה השינוי של ס46
                    "נשמע" פירושו שמותרות רק שתי עריכות:

                    החלפה בין אותיות שנשמעות אותו דבר: ט/ת, כ/ח, כ/ק, ס/ש, א/ע/ה, ב/ו, ועוד זוג אחד שנצפה בשיחה אמיתית, ד/ת ("שס חדנים").
                    הוספה או השמטה של אם קריאה (א, ה, ו, י), כמו שולחן/שלחן.
                    כל החלפה אחרת פוסלת. לכן "שס קטנים" כבר לא מחזיר את "קרנים": ט ו-ר אינן נשמעות דומה. ההשוואה נעשית גם על הגזע וגם על צורת פני השטח, כדי ש"סמיטה" ימצא את "שמיטה" למרות שהגיזום הוריד את ה-ש רק בצד אחד.

                    ב. מילים בנות שתי אותיות שאינן מבניות
                    מילה כזו לבדה לא מזהה ספר. אבל אם נאמרה, היא חייבת להופיע בשם בדיוק, למשל ים של שלמה.

                    ג. שלילה
                    "לא מנוקד" פוסל שם שאומר "מנוקד" בלי "לא" לפניו, וההפך. שם שלא מזכיר את המאפיין בכלל עובר.

                    ד. אם אף מועמד לא עבר
                    עוברים לניסיון הבא. אם אף ניסיון לא הניב כלום, התשובה היא 0 תוצאות, במכוון (כ8).

                    בחזרה למנגנון הדיבור:

                    בודק אם יש התאמות של מאפיינים, לדוגמא כריכת עור, אם יש - כל מה שלא מתאים מסונן.

                    סדרות של יותר מ4 כרכים שכל כרך נמכר בנפרד מקובצות ל"סדרה של X כרכים" (הניסוח קצת מטעה בעיני)
                    יש עדיפות לספרים עם שם מדויק יותר
                    אם יש יותר מ5 תוצאות מבקשים מהמאזין לדייק בשם הספר

                    מה אתם אומרים?
                    ברור שיש עוד תיקונים לעשות והוא עוד לא מושלם אבל מה הכיוןן?

                    @pcinfogmach במקום אחר המלצת למישהו לעשות מנגנון פיצוי/ניקוד, על מה מדובר?

                    pcinfogmachP תגובה 1 תגובה אחרונה
                    0
                    • ע עידו300

                      זה המסלול שהטקסט עובר כיום אחרי ההמלצה כאן בשרשור:

                      הפלט שחוזר מהמודל עובר בדיקת אורך תווים -> ניקוי תוים מסוימים -> תיקונים על פי טבלת תיקונים והחלפות שנצפו בתיעודים (הרי זה תמלול והוא לא תמיד מדוייק אז "בלכתך" הופך ל"מלתך" ו"משנה" ל"משנא") -> נרמול -> הסרת אותיות שימוש מובילות לצורך השוואה (השמיטה -> שמיטה).

                      כל זה במנגנון הדיבור.

                      במנגנון החיפוש עצמו:

                      מורצות שתי שאילתות:
                      1 - כמו שהיא, לדוגמא "שס חתנים"
                      2 - החלפות מסוימות כמו ש"ס -> סט "סט חתנים"

                      אם שתי השאילתות האלו לא הניבו תוצאות אז עוברים לשאילתות אחרות:
                      1 - אותה השאילתא רק בלי מילים תיאוריות (חומש, ספר, מהדורת, הוצאת) ובלי שם הוצאה שנאמר במלואו, לדוגמא "סט חומש מקראות גדולות" יהפוך ל"סט מקראות גדולות".
                      2 - אותו דבר רק עם החלפת ש"ס לסט.

                      כל מילה בשאילתא חייבת להתאים לעמודה אחת לפחות (במילים בנות 4 אותיות יכולה להיות טעות אחת, ומילים בנות 7 אותיות יכולות להיות 2 טעויות) הדירוג בפועל יהיה לפי שם הספר.

                      את השלב הזה לא הבנתי... וחלקו בכלל לא ברור לי למה הוא עשה אותו.
                      מה שכן הבנתי זה שהוא קודם בודק אם שם הספר תואם (לא מבין למה, אם שכחו מה שם הספר וביקשו משהו לפי התיאור והוא מתאים בהערות, למה לזרוק את הספר שנמצא?) ואם לא הוא מוציא אותו מהרשימה. אח"כ עושה מניפולציה על המילים, תלוי בסוג המילה ובאורך שלה ומחליף אותיות שלפעמים נשמעות אותו הדבר.

                      שלב 3 · שער הכיסוי (בערוץ), שבו נופלות ההחלטות
                      כל מועמד שהשרת החזיר עובר בדיקות מול שם הספר בלבד, לא מול ההערות. מועמד שלא עבר נזרק, גם אם השרת אהב אותו.

                      א. מילות תוכן: כל אחת חייבת להימצא בשם
                      מילת תוכן היא מילה בת 3 אותיות לפחות, שאינה מילה מבנית (סט, שס, ספר, כרך, גדול, מנוקד, עור, רוצה, יש וכו'). איך היא נבדקת תלוי באורך הגזע שלה:

                      אורך הגזע מה נדרש
                      2 (מילה של 3 שהגיזום קיצר) הצורה המקורית מופיעה בשם כמילה שלמה
                      3–4 הגזע מוכל בטוקן של השם. בלי שום סובלנות לשגיאה
                      5 ומעלה שני תנאים יחד: השרת היה מתאים אותה, וגם כל ההבדל "נשמע". זה השינוי של ס46
                      "נשמע" פירושו שמותרות רק שתי עריכות:

                      החלפה בין אותיות שנשמעות אותו דבר: ט/ת, כ/ח, כ/ק, ס/ש, א/ע/ה, ב/ו, ועוד זוג אחד שנצפה בשיחה אמיתית, ד/ת ("שס חדנים").
                      הוספה או השמטה של אם קריאה (א, ה, ו, י), כמו שולחן/שלחן.
                      כל החלפה אחרת פוסלת. לכן "שס קטנים" כבר לא מחזיר את "קרנים": ט ו-ר אינן נשמעות דומה. ההשוואה נעשית גם על הגזע וגם על צורת פני השטח, כדי ש"סמיטה" ימצא את "שמיטה" למרות שהגיזום הוריד את ה-ש רק בצד אחד.

                      ב. מילים בנות שתי אותיות שאינן מבניות
                      מילה כזו לבדה לא מזהה ספר. אבל אם נאמרה, היא חייבת להופיע בשם בדיוק, למשל ים של שלמה.

                      ג. שלילה
                      "לא מנוקד" פוסל שם שאומר "מנוקד" בלי "לא" לפניו, וההפך. שם שלא מזכיר את המאפיין בכלל עובר.

                      ד. אם אף מועמד לא עבר
                      עוברים לניסיון הבא. אם אף ניסיון לא הניב כלום, התשובה היא 0 תוצאות, במכוון (כ8).

                      בחזרה למנגנון הדיבור:

                      בודק אם יש התאמות של מאפיינים, לדוגמא כריכת עור, אם יש - כל מה שלא מתאים מסונן.

                      סדרות של יותר מ4 כרכים שכל כרך נמכר בנפרד מקובצות ל"סדרה של X כרכים" (הניסוח קצת מטעה בעיני)
                      יש עדיפות לספרים עם שם מדויק יותר
                      אם יש יותר מ5 תוצאות מבקשים מהמאזין לדייק בשם הספר

                      מה אתם אומרים?
                      ברור שיש עוד תיקונים לעשות והוא עוד לא מושלם אבל מה הכיוןן?

                      @pcinfogmach במקום אחר המלצת למישהו לעשות מנגנון פיצוי/ניקוד, על מה מדובר?

                      pcinfogmachP מנותק
                      pcinfogmachP מנותק
                      pcinfogmach
                      מדריכים
                      כתב נערך לאחרונה על ידי
                      #58

                      @עידו300
                      מחילה
                      אם אתה רוצה שאעזור לך תגיד לי בקצרה במה מדובר ואל תעלה לי םה מה שהבינה אמרה לך
                      אין לי זמן לקרוא מגילות וגם לא לפענח רמזים
                      רק תתאמץ קצת אין לך מה להסתיר וכבר תקבל כל מה שאתה רוצה על מגש של כסף

                      גמ"ח עזרה וייעוץ בנושאי מחשבים

                      ע תגובה 1 תגובה אחרונה
                      0
                      • pcinfogmachP pcinfogmach

                        @עידו300
                        מחילה
                        אם אתה רוצה שאעזור לך תגיד לי בקצרה במה מדובר ואל תעלה לי םה מה שהבינה אמרה לך
                        אין לי זמן לקרוא מגילות וגם לא לפענח רמזים
                        רק תתאמץ קצת אין לך מה להסתיר וכבר תקבל כל מה שאתה רוצה על מגש של כסף

                        ע מנותק
                        ע מנותק
                        עידו300
                        כתב נערך לאחרונה על ידי
                        #59

                        @pcinfogmach אני מאוד מעריך את את העזרה של כולם, ואני לא רואה בעין יפה שזורקים פלט של AI לעוזרים.
                        לכן בקשתי מהבינה שתכתוב לי איך המנגנון כיום אחרי השינויים שהציעו כאן עובד (אין לי מושג איך היא בנתה אותו הייתי חייב לברר לפני שאני שואל כאן) ואני לקחתי ותמצתתי וכתבתי את כל הקטע הנ"ל במו ידי על אף השעה. השתדלתי שיהיה בצורה מאוד קלילה וברורה בלי אריכות וסיבוכים של AI (אם יש דבר אחד שAI לא יודע לעשות, או לפחות לא עושה את זה כברירת מחדל, זה לכתוב כמו שצריך, במקום משפט הוא כותב 2-3), אם חשבתם שפשוט זרקתי לכם את התוצאה של הAI, עמכם הסליחה! (אולי גם עימי על "חושד בכשרים", אבל לא משנה 🙂 ).

                        בכל אופן, המטרה של הפרויקט היא יצירת מערכת בוטי מידע ושירות לקוחות (לפחות בשלב זה) לבעלי עסקים.

                        הלב של הפרויקט הוא מערכת שמכילה את המוצרים והמידע של העסק ושיודעת לחפש בהם ולהפיק הצעות מחיר. וגם לנהל את המידע עם API (לטובת שימוש בAI)..

                        מכאן זה מתחלק לבוטים במייל, טלפון ובהמשך צ'אטים וכו'.

                        הבעיה מתחילה בבוט הטלפוני שם התמלול עושה שמות וצריך חיפוש שידע להתאים את זה נכון, אבל לא יהיה רך מידי וימצא גם דברים שממש לא קשורים.

                        בגלל שעיקר הבעיה היא בבוט הטלפוני אז חלק מהכללים צריכים להיות רק בו ולא במנגנון הראשי, אין טעם לאלץ את כל הבוטים בגלל האילוצים שלו.

                        תגובה 1 תגובה אחרונה
                        0

                        שלום! נראה שהשיחה הזו מעניינת אותך, אבל עדיין אין לך חשבון.

                        נמאס לכם לגלול בין אותם הפוסטים בכל ביקור? כשנרשמים לחשבון, תמיד תחזרו בדיוק למקום שבו הייתם קודם, ותוכלו לבחור לקבל התראות על תגובות חדשות (בין אם במייל, ובין אם בהתראת פוש). תוכלו גם לשמור סימניות ולפרגן ב-upvote לפוסטים כדי להביע הערכה לחברי קהילה אחרים.

                        בעזרת התרומה שלך, הפוסט הזה יכול להיות אפילו טוב יותר 💗

                        הרשמה התחברות

                        • התחברות

                        • אין לך חשבון עדיין? הרשמה

                        • התחברו או הירשמו כדי לחפש.
                        • פוסט ראשון
                          פוסט אחרון
                        0
                        • חוקי הפורום
                        • פופולרי
                        • לא נפתר
                        • משתמשים
                        • חיפוש גוגל בפורום
                        • צור קשר