
    %i6                        U d Z ddlZddlmc mZ ddlZddlZddl	Z	ddl
Z
ddlZddlmZ ddlmZmZ ddlZddlZe
j&                  j)                  dd       ddlmZmZ ddlmc mZ ddlmZmZmZmZm Z m!Z!m"Z"  e# e	jH                  dd	            Z%d
gez  Z&ee'   e(d<   	 	 	 	 	 	 dde)de)de)de)de)de)defdZ*de)dee'   fdZ+ G d d      Z, G d d      Z- G d d      Z. G d d      Z/y)u  
Story 4.05 — Embedder Integration Test Suite
=============================================
Tests for MODULE 4: Gemini Embedder

Black-box and white-box tests covering:
  - embed_text()           (4.01)
  - embed_batch()          (4.02)
  - embed_with_cache()     (4.03)
  - build_embedding_text() (4.04)

Tests that call the real Gemini API are skipped when GEMINI_API_KEY is not set.
All unit tests use mocking and fakeredis — no API quota consumed.
    N)List)	MagicMockpatchz/mnt/e/genesis-system)ChunkEmbeddedChunk)EMBED_MODELMAX_EMBEDDING_CHARS
VECTOR_DIMbuild_embedding_textembed_batch
embed_textembed_with_cacheGEMINI_API_KEY g{Gz?_FAKE_VECTORtextplatformheading_contexttitlechunk_idcustomer_idreturnc                 ,    t        |d|||| |ddi 
      S )Nzhttps://example.com/docsr      )
r   
source_urlr   r   r   r   r   chunk_indextotal_chunksmetadata)r   )r   r   r   r   r   r   s         >/mnt/e/genesis-system/tests/kb/test_m4_embedder_integration.py_make_chunkr    4   s/     -'     c                     t         S )z=Fake embed_text that returns a deterministic 3072-dim vector.)r   r   s    r   mock_embed_textr$   J   s    r!   c                       e Zd ZdZd Zd Zej                  j                  e	 d      d        Z
ej                  j                  e	 d      d        Zd Zd	 Zd
 Zy)TestEmbedTextz/Black-box and white-box tests for embed_text().c                 p   d}t         |k(  }|st        j                  d|fdt         |f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)	z<Verify the model constant is exactly 'gemini-embedding-001'.gemini-embedding-001==z%(py0)s == %(py3)sr   py0py3assert %(py5)spy5N)	r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)self@py_assert2@py_assert1@py_format4@py_format6s        r   test_correct_model_usedz%TestEmbedText.test_correct_model_usedW   s^    44{44444{4444444{444{44444444444r!   c                 f   ddl m}  |       }|s{t        j                  d      dz   ddt	        j
                         v st        j                  |      rt        j                  |      ndiz  }t        t        j                  |            t        |      }d}||kD  }|st        j                  d|fd	||f      d
t	        j
                         v st        j                  t              rt        j                  t              nd
dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}}y)z=API key should be non-empty (loaded from env or secrets.env).r   )_load_api_keyz7GEMINI_API_KEY must be loadable from env or secrets.envz
>assert %(py0)sr-   key
   )>)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slenr-   py1r.   py6z%API key appears too short to be validz
>assert %(py8)spy8N)core.kb.embedderr@   r1   _format_assertmsgr3   r4   r5   r6   r7   r8   rD   r2   )	r9   r@   rA   @py_format1r:   @py_assert5@py_assert4@py_format7@py_format9s	            r   test_api_key_loadedz!TestEmbedText.test_api_key_loaded\   s    2oMMMMMMMMMsMMMsMMMMM3xE"Ex"}EEEx"EEEEEEsEEEsEEEEEE3EEE3EEExEEE"EEEEEEEEEEEr!   u1   GEMINI_API_KEY not set — skipping live API test)reasonc                 b   dt         _        t        d      }t        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}t        |      }|t        k(  }|s/t        j                  d|fd	|t        f      d
t        j                         v st        j                  t              rt        j                  t              nd
dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                  |            dx}}d |D        }t        |      }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)u2   embed_text('hello world') → list of 3072 floats.Nzhello worldz5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancevectorlist)r-   rF   py2py4r)   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py5)srD   r
   r-   rF   r.   r0   assert %(py7)spy7c              3   <   K   | ]  }t        |t                y wNrS   float.0vs     r   	<genexpr>z8TestEmbedText.test_embed_returns_3072.<locals>.<genexpr>l        8A:a'8   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allr-   rV   rW   )embedder_module_genai_clientr   rS   rU   r3   r4   r1   r5   r6   r7   r8   rD   r
   r2   rg   )	r9   rT   @py_assert3@py_format5r:   rM   r=   @py_format8r;   s	            r   test_embed_returns_3072z%TestEmbedText.test_embed_returns_3072d   s    )-%M*&$''''''''z'''z''''''&'''&''''''$'''$''''''''''6{({j(((({j((((((s(((s((((((6(((6((({((((((j(((j(((((((888s888888888s888s88888888888888r!   c                    dt         _        ddz  }t        |dd       }t        |      }|t        k(  }|s/t        j                  d|fd|t        f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	t        j                         v st        j                  t              rt        j                  t              nd	d
z  }dd|iz  }t        t        j                  |            dx}}y)uF   10,000 char text → valid 3072-dim vector (API truncates internally).Nz Genesis knowledge base content. i9  i'  r)   rX   rD   rT   r
   rY   rZ   r[   )ri   rj   r   rD   r
   r1   r2   r3   r4   r5   r6   r7   r8   )r9   	long_textrT   r:   rM   r=   rm   s          r   test_embed_long_textz"TestEmbedText.test_embed_long_texto   s     )-%6<	Igv./6{({j(((({j((((((s(((s((((((6(((6((({((((((j(((j(((((((r!   c                 z    t        j                  t        d      5  t        d       ddd       y# 1 sw Y   yxY w)z=Empty string must raise ValueError, not a silent zero vector.emptymatchr   Npytestraises
ValueErrorr   r9   s    r   test_embed_empty_stringz%TestEmbedText.test_embed_empty_stringx   s,    ]]:W5 	rN	 	 	   1:c                 z    t        j                  t        d      5  t        d       ddd       y# 1 sw Y   yxY w)z-Whitespace-only string must raise ValueError.rs   rt   z   
	  Nrv   rz   s    r   test_embed_whitespace_onlyz(TestEmbedText.test_embed_whitespace_only~   s-    ]]:W5 	${#	$ 	$ 	$r|   c                    t               }t        |j                  d   _        t	        j
                  t        d      5 }t               }||j                  j                  _	        ||_	        t        d      }ddd       t              }|t        k(  }|s/t        j                  d|fd|t        f      dt        j                          v st        j"                  t              rt        j$                  t              nddt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      d	t        j                          v st        j"                  t              rt        j$                  t              nd	d
z  }dd|iz  }t'        t        j(                  |            dx}}d |D        }	t+        |	      }
|
sddt        j                          v st        j"                  t*              rt        j$                  t*              ndt        j$                  |	      t        j$                  |
      dz  }t'        t        j(                  |            dx}	}
y# 1 sw Y   xY w)z/Mocked embed returns exactly VECTOR_DIM floats.r   _get_genai_clientztest contentNr)   rX   rD   rT   r
   rY   rZ   r[   c              3   <   K   | ]  }t        |t                y wr]   r^   r`   s     r   rc   zFTestEmbedText.test_embed_returns_correct_dim_mocked.<locals>.<genexpr>   rd   re   rf   rg   rh   )r   r   
embeddingsvaluesr   objectri   modelsembed_contentreturn_valuer   rD   r
   r1   r2   r3   r4   r5   r6   r7   r8   rg   )r9   mock_resultmock_clientclient_instancerT   r:   rM   r=   rm   r;   rk   rl   s               r   %test_embed_returns_correct_dim_mockedz3TestEmbedText.test_embed_returns_correct_dim_mocked   sk   k+7q!(\\/+>? 	0;'kO@KO""00='6K$/F	0 6{({j(((({j((((((s(((s((((((6(((6((({((((((j(((j(((((((888s888888888s888s88888888888888	0 	0s   8I77JN)__name__
__module____qualname____doc__r>   rP   rw   markskipifGEMINI_API_KEY_PRESENTrn   rq   r{   r~   r    r!   r   r&   r&   S   s{    95
F [[22;no9 p9 [[22;no) p)$9r!   r&   c                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)TestBuildEmbeddingTextz9Black-box and white-box tests for build_embedding_text().c                 |   t        d      }t        |      }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
z2heading_context must appear in the embedding text.zAPI Reference > Authenticationr   inz%(py1)s in %(py3)sresultrF   r.   r/   r0   N
r    r   r1   r2   r6   r3   r4   r5   r7   r8   r9   chunkr   @py_assert0r:   r<   r=   s          r   *test_build_embedding_text_contains_headingzATestBuildEmbeddingText.test_build_embedding_text_contains_heading   ss    ,LM%e,/9/69999/6999/999999699969999999r!   c                    t        d      }t        |      }|j                  }d} ||      }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}}y)zCPlatform tag '[hubspot]' must appear at the very start of the text.hubspot)r   z	[hubspot]zLassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.startswith
}(%(py4)s)
}r   )r-   rV   rW   rG   N)
r    r   
startswithr3   r4   r1   r5   r6   r7   r8   )r9   r   r   r;   rk   rL   rN   s          r   +test_build_embedding_text_contains_platformzBTestBuildEmbeddingText.test_build_embedding_text_contains_platform   s    Y/%e,  -- --------v---v--- -------------r!   c                    ddz  }t        |      }t        |      }t        |      }|t        k  }|s/t	        j
                  d|fd|t        f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndd	z  }d
d|iz  }t        t	        j                  |            dx}}y)u>   20,000-char text must be truncated to ≤ MAX_EMBEDDING_CHARS.xi N  r#   )<=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} <= %(py5)srD   r   r	   rY   rZ   r[   N)r    r   rD   r	   r1   r2   r3   r4   r5   r6   r7   r8   )r9   rp   r   r   r:   rM   r=   rm   s           r   $test_build_embedding_text_truncationz;TestBuildEmbeddingText.test_build_embedding_text_truncation   s    &L	+%e,6{1{11111{1111111s111s11111161116111{111111111111111111r!   c                    t        d      }t        |      }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d
x}}d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d
x}}y
)z;Multiple consecutive spaces must be collapsed to one space.zfoo    bar    bazr#   zfoo bar bazr   r   r   r   r/   r0   Nz  not inz%(py1)s not in %(py3)sr   r   s          r   test_whitespace_normalizationz4TestBuildEmbeddingText.test_whitespace_normalization   s    !45%e,&}&&&&}&&&}&&&&&&&&&&&&&&&&!t6!!!!t6!!!t!!!!!!6!!!6!!!!!!!r!   c                 \   t        d      }t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d
x}}|j                  }||v }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }	dd|	iz  }
t        t        j                  |
            d
x}}y
)zEEmpty heading_context must produce valid text without empty brackets.r   r   z[]r   r   r   r   r/   r0   Nr   )z-%(py2)s
{%(py2)s = %(py0)s.title
} in %(py4)sr   rh   zassert %(py6)srG   )r    r   r1   r2   r6   r3   r4   r5   r7   r8   r   )r9   r   r   r   r:   r<   r=   r;   rk   rl   rN   s              r   test_empty_heading_handledz1TestBuildEmbeddingText.test_empty_heading_handled   s    B/%e,!t6!!!!t6!!!t!!!!!!6!!!6!!!!!!!{{${f$$$${f$$$$$$u$$$u$$${$$$$$$f$$$f$$$$$$$r!   c                 ~   t        dd      }t        |      }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d x}}y )
NzMy TitlezSome content)r   r   r   r   r   r   r/   r0   r   r   s          r   test_title_in_outputz+TestBuildEmbeddingText.test_title_in_output   sq    *>B%e,#zV####zV###z######V###V#######r!   c                 |   t        d      }t        |      }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d x}}y )	NzUnique content herer#   r   r   r   r   r/   r0   r   r   s          r   test_text_in_outputz*TestBuildEmbeddingText.test_text_in_output   ss    !67%e,$.$....$...$................r!   c                 |   t        d      }t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d x}}y )
Nzline1




line2r#   z


r   r   r   r   r/   r0   r   r   s          r   !test_excessive_newlines_collapsedz8TestBuildEmbeddingText.test_excessive_newlines_collapsed   sp    !78%e,%xv%%%%xv%%%x%%%%%%v%%%v%%%%%%%r!   N)r   r   r   r   r   r   r   r   r   r   r   r   r   r!   r   r   r      s-    C:.2"%$/&r!   r   c                   D    e Zd ZdZdedee   fdZd Zd Z	d Z
d Zd	 Zy
)TestEmbedBatchz0Tests for embed_batch() using mocked embed_text.nr   c           	      b    t        |      D cg c]  }t        d| d|d       c}S c c}w )NzChunk content chunk_03d)r   r   )ranger    )r9   r   is      r   _make_chunkszTestEmbedBatch._make_chunks   s4    [`ab[cdVW>!!5&3@PQddds   ,c                 *   | j                  d      }t        j                  t        dt              5  t        |d      }ddd       t              }d}||k(  }|st        j                  d|fd||f      d	t        j                         v st        j                  t              rt        j                  t              nd	d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}d |D        }t        |      }	|	sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |	      dz  }
t        t        j                  |
            dx}}	y# 1 sw Y   xY w)u4   embed_batch of 5 chunks → 5 EmbeddedChunk objects.   r   side_effectrB   
batch_sizeNr)   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)srD   r   rE   zassert %(py8)srH   c              3   <   K   | ]  }t        |t                y wr]   )rS   r   )ra   ecs     r   rc   zJTestEmbedBatch.test_batch_embed_creates_embedded_chunks.<locals>.<genexpr>   s     BR:b-0Bre   rf   rg   rh   )r   r   r   ri   r$   r   rD   r1   r2   r3   r4   r5   r6   r7   r8   rg   )r9   chunksr   r:   rL   rM   rN   rO   r;   rk   rl   s              r   (test_batch_embed_creates_embedded_chunksz7TestEmbedBatch.test_batch_embed_creates_embedded_chunks   s.   ""1%\\/<_U 	8 B7F	86{a{a{ass66{aB6BBsBBBBBBBBBsBBBsBBBBBBBBBBBBBB	8 	8s   HHc           	         | j                  d      }t        j                  t        dt              5  t        |d      }ddd       D ]o  }|j                  }t        |      }|t        k(  }|sCt        j                  d|fd|t        f      d	t        j                         v st        j                  t              rt        j                  t              nd	d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                   |            dx}x}}r y# 1 sw Y   xY w)z3All EmbeddedChunk vectors must be exactly 3072-dim.r   r   r   rB   r   Nr)   )zL%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.vector
})
} == %(py7)srD   r   r
   )r-   rF   r.   r0   r[   assert %(py9)spy9)r   r   r   ri   r$   r   rT   rD   r
   r1   r2   r3   r4   r5   r6   r7   r8   )	r9   r   r   r   r:   rM   @py_assert6rm   @py_format10s	            r   test_all_vectors_same_dimz(TestEmbedBatch.test_all_vectors_same_dim   s   ""1%\\/<_U 	8 B7F	8 	0Byy/3y>/>Z////>Z//////3///3//////r///r///y///>//////Z///Z///////	0	8 	8s   F>>Gc                 D   | j                  d      }t        j                  t        dt              5  t        |      }ddd       D ]  }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}} y# 1 sw Y   xY w)zGEach EmbeddedChunk must have embedding_model == 'gemini-embedding-001'.   r   r   Nr(   r)   )z7%(py2)s
{%(py2)s = %(py0)s.embedding_model
} == %(py5)sr   )r-   rV   r0   rZ   r[   )r   r   r   ri   r$   r   embedding_modelr1   r2   r3   r4   r5   r6   r7   r8   )	r9   r   r   r   r;   rM   rk   r=   rm   s	            r   test_embedded_chunk_has_modelz,TestEmbedBatch.test_embedded_chunk_has_model   s    ""1%\\/<_U 	) (F	) 	@B%%?)??%)?????%)???????2???2???%???)????????	@	) 	)s   DDc                    | j                  d      }t        j                  t        dt              5  t        |      }d d d        t              D ]  \  }}|j                  }|j                  }d|d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      d	z  }	d
d|	iz  }
t        t        j                   |
            d x}x}x}} y # 1 sw Y   xY w)N   r   r   r   r   r)   )zK%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.chunk
}.chunk_id
} == %(py7)sr   )r-   rV   rW   r[   r   r   )r   r   r   ri   r$   r   	enumerater   r   r1   r2   r3   r4   r5   r6   r7   r8   )r9   r   r   r   r   r;   rk   r   rL   rm   r   s              r    test_chunk_preserved_on_embeddedz/TestEmbedBatch.test_chunk_preserved_on_embedded   s    ""1%\\/<_U 	) (F	)v& 	9EAr8888$$8&3(88$(88888$(8888888288828888888$888(88888888	9	) 	)s   EEc                 f   t        g       }g }||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d x}}y )Nr)   r+   r   r,   r/   r0   )	r   r1   r2   r3   r4   r5   r6   r7   r8   )r9   r   r:   r;   r<   r=   s         r   test_empty_batchzTestEmbedBatch.test_empty_batch  sc    Rv|vvvr!   N)r   r   r   r   intr   r   r   r   r   r   r   r   r   r!   r   r   r      s:    :ec ed5k eC0@9r!   r   c                   4    e Zd ZdZd Zd Zd Zd Zd Zd Z	y)	TestEmbedWithCachez-Tests for embed_with_cache() using fakeredis.c                 *    t        j                         S )z0Return a fakeredis server instance for patching.)	fakeredis	FakeRedisrz   s    r   _make_fake_redisz#TestEmbedWithCache._make_fake_redis  s    ""$$r!   c                    t        j                         }t        j                  |      }t        d|      5  t        j                  t
        dt              5 }t        d      }ddd       ddd       j                  d       t              }|t        k(  }|s/t        j                  d|fd	|t        f      d
t        j                         v st        j                  t              rt        j                   t              nd
dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      dt        j                         v st        j                  t              rt        j                   t              nddz  }dd|iz  }t#        t        j$                  |            dx}}y# 1 sw Y   nxY w# 1 sw Y   sxY w)z0On a cache miss, embed_text must be called once.serverredis.from_urlr   r   r   zbrand new textNr)   rX   rD   r   r
   rY   rZ   r[   )r   
FakeServerr   r   r   ri   r$   r   assert_called_once_withrD   r
   r1   r2   r3   r4   r5   r6   r7   r8   )	r9   r   
fake_redis
mock_embedr   r:   rM   r=   rm   s	            r   test_cache_miss_calls_apiz,TestEmbedWithCache.test_cache_miss_calls_api  s   %%'((7
#*= 	8\\/<_U	8Yc%&67F	8 	8 	**+;<6{({j(((({j((((((s(((s((((((6(((6((({((((((j(((j(((((((	8 	8 	8 	8s#   !GG%GG	GG(c                    t        j                         }t        j                  |      }d}t        j                  |j                               j                         }d| }|j                  |dt        j                  t                     t        d|      5  t        j                  t        dt              5 }t        |      }d	d	d	       d	d	d	       j!                          t        k(  }|st#        j$                  d
|fd|t        f      dt'        j(                         v st#        j*                  |      rt#        j,                  |      nddt'        j(                         v st#        j*                  t              rt#        j,                  t              nddz  }	dd|	iz  }
t/        t#        j0                  |
            d	}y	# 1 sw Y   xY w# 1 sw Y   xY w)z.On a cache hit, embed_text must NOT be called.r   zcached content heregenesis:kb:embed:  r   r   r   r   Nr)   z%(py0)s == %(py2)sr   r   r-   rV   assert %(py4)srW   )r   r   r   hashlibsha256encode	hexdigestsetexjsondumpsr   r   r   ri   r$   r   assert_not_calledr1   r2   r3   r4   r5   r6   r7   r8   )r9   r   r   r   	cache_keyfull_keyr   r   r;   @py_format3rl   s              r   test_cache_hit_skips_apiz+TestEmbedWithCache.test_cache_hit_skips_api!  s1   %%'((7
$NN4;;=1;;=	&yk24L)AB#*= 	,\\/<_U	,Yc%d+F	, 	, 	$$&%%%%v%%%%%%v%%%v%%%%%%%%%%%%%%%%	, 	, 	, 	,s$   !G;GGG	GGc                    t               }t        d      |j                  _        t	        d|      5  t	        j
                  t        dt              5  t        d      }ddd       ddd       t              }|t        k(  }|s/t        j                  d|fd	|t        f      d
t        j                         v st        j                  t              rt        j                   t              nd
dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      dt        j                         v st        j                  t              rt        j                   t              nddz  }dd|iz  }t#        t        j$                  |            dx}}y# 1 sw Y   ]xY w# 1 sw Y   bxY w)zRWhen Redis is completely unreachable, embed_with_cache must still return a vector.z
Redis downr   r   r   r   zfallback textNr)   rX   rD   r   r
   rY   rZ   r[   )r   ConnectionErrorpingr   r   r   ri   r$   r   rD   r
   r1   r2   r3   r4   r5   r6   r7   r8   )r9   broken_redisr   r:   rM   r=   rm   s          r   #test_redis_unavailable_still_embedsz6TestEmbedWithCache.test_redis_unavailable_still_embeds3  s    {(7(E%#,? 	7\\/<_U	7%o6F	7 	7 6{({j(((({j((((((s(((s((((((6(((6((({((((((j(((j(((((((		7 	7 	7 	7s#   !GF:G:G	?GGc                 d   t        j                         }t        j                  |      }d}d| }|j                  |dt	        j
                  t                     t        d|      5  t        j                  t        dt              5 }t        d	|
      }ddd       ddd       j                          t        k(  }|st        j                  d|fd|t        f      dt        j                          v st        j"                  |      rt        j$                  |      nddt        j                          v st        j"                  t              rt        j$                  t              nddz  }dd|iz  }	t'        t        j(                  |	            d}y# 1 sw Y   xY w# 1 sw Y   xY w)z@When a custom cache_key is provided, it must be used as the key.r   my_custom_key_xyzr   r   r   r   r   r   zany text)r   Nr)   r   r   r   r   r   rW   )r   r   r   r   r   r   r   r   r   ri   r$   r   r   r1   r2   r3   r4   r5   r6   r7   r8   )
r9   r   r   
custom_keyr   r   r   r;   r   rl   s
             r   test_custom_cache_key_usedz-TestEmbedWithCache.test_custom_cache_key_used?  s   %%'((7
(
&zl34L)AB#*= 	H\\/<_U	HYc%jJGF	H 	H 	$$&%%%%v%%%%%%v%%%v%%%%%%%%%%%%%%%%	H 	H 	H 	Hs$   )!F%
FF%F"	F%%F/c                    t        j                         }t        j                  |      }d}t        d|      5  t        j                  t
        dt              5  t        |       ddd       ddd       t        j                  |j                               j                         }d| }|j                  |      }d}||u}|st        j                  d	|fd
||f      dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      dz  }	dd|	iz  }
t'        t        j(                  |
            dx}}t*        j,                  } ||      }|t.        k(  }|sCt        j                  d|fd|t.        f      dt        j                          v st        j"                  t*              rt        j$                  t*              ndt        j$                  |      dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      dt        j                          v st        j"                  t.              rt        j$                  t.              nddz  }dd|iz  }t'        t        j(                  |            dx}x}}y# 1 sw Y   lxY w# 1 sw Y   qxY w)z7After a cache miss, the vector must be stored in Redis.r   zstore me pleaser   r   r   r   Nr   )is not)z%(py0)s is not %(py3)sstoredr,   r/   r0   r)   )zK%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.loads
}(%(py3)s)
} == %(py7)sr   r   )r-   rV   r.   r0   r[   r   r   )r   r   r   r   r   ri   r$   r   r   r   r   r   getr1   r2   r3   r4   r5   r6   r7   r8   r   loadsr   )r9   r   r   r   r   r   r  r:   r;   r<   r=   rM   r   rm   r   s                  r   test_cache_stored_after_missz/TestEmbedWithCache.test_cache_stored_after_missP  s   %%'((7
 #*= 	#\\/<_U	#T"	# 	# NN4;;=1;;=	&yk2)!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!zz1z&!1!\1111!\111111t111t111z111111&111&111!111111\111\1111111	# 	# 	# 	#s#   !KK'KK	KK(N)
r   r   r   r   r   r   r   r  r  r  r   r!   r   r   r     s#    7%

)&$	)&"2r!   r   )zSample chunk text.r   zGetting Started > InstallationzQuick Start Guide	chunk_001N)0r   builtinsr3   _pytest.assertion.rewrite	assertionrewriter1   r   r   ossystimetypingr   unittest.mockr   r   r   rw   pathinsertcore.kb.contractsr   r   rI   kbembedderri   r   r	   r
   r   r   r   r   boolgetenvr   r   r_   __annotations__strr    r$   r&   r   r   r   r   r!   r   <module>r     s'      	 
   *   * + 2 * *   ibii(8"=> !FZ/d5k / %;$
  	
   ,# $u+ >9 >9J:& :&B, ,fR2 R2r!   