o
    ưi                  -   @   s  d dl 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mZmZ d dlZd dlZd dlmZ d dlmZ d dlmZ e
rMd dlmZ neZeje  dZedd	Zed	krfe  d d
lmZ dZ G dd deZ!dee" de#de"fddZ$G dd dZ%e& ej'dddddej'dddddej'dedddej'd dd!d"ej'd#d$d%d"ej'd&d'dd(d"ej'd)dd*d"ej'd+dd(d"ej'd,dd-d"ej'd.d/e(d0d1ej'd2d3d/e(d4d5d6ej'd7d3d/e(d8d9d6ej'd:d3d/e(d;d<ej'd=de)d>d?ej'd@de*dAd?ej'dBde*dCd?ej'dDd/dEdFej'dGd/dHdFej'dIdJddKd"ej'dLde)dMd?ej'dNd/e(dOd?ej'dPde"dQd?ej'dRdSd3d/e(dTd<ej'dUd/dVdWej'dXd/dYdWej'dZd3d/d[d\ej'd]d3d/d^d\ej'd_d`e*dad?ej'dbd3d/dcd\ej'ddd3d/ded\ej'dfde"dgdhdiej'djde"dkdldiej'dmde"dnd?ej'dod/d3dpdqej'drd/d3dsdqej'dtd/d3dudqej'dvde*dwdxdiej'dyde*dzd{did|e(fd}d~Z+e,dkre+  dS dS )    N)TYPE_CHECKINGAnyOptionalUnion)load_dotenv)!DEFAULT_NUM_WORKERS_LITELLM_PROXY)get_secret_bool)FastAPIzlitellm.secretsZLITELLM_MODEZDEV)Enumc                   @   s   e Zd ZdZdZdS )LiteLLMDatabaseConnectionPool
   <   N)__name__
__module____qualname__database_connection_pool_limit database_connection_pool_timeout r   r   N/home/app/Keep/.python/lib/python3.10/site-packages/litellm/proxy/proxy_cli.pyr   #   s    r   urlparamsreturnc                 C   s   ddl m} |d|   |d|  t| tr| dkr&|d dS t| }t|j}|	| tj
|dd}t|j|d	}|S )
Nr   )verbose_proxy_loggerzurl: zparams:  zLappend_query_params received empty or non-string URL, returning empty stringT)doseq)query)litellm._loggingr   debug
isinstancestrwarningurlparseparse_qsr   update	urlencode
urlunparse_replace)r   r   r   
parsed_urlZparsed_queryZencoded_querymodified_urlr   r   r   append_query_params(   s   


r)   c                   @   s  e Zd Zedd Zedd Zededededee	ef fd	d
Z
e		d$dededee dee def
ddZe	d%dedededededee fddZe	d%dededededededee fddZedd Zedd Zedd  Zeded!ee ddfd"d#ZdS )&ProxyInitializationHelpersc                  C   s"   t jd} td|  d d S )Nlitellmz
LiteLLM: Current Version = 
)	importlibmetadataversionclickecho)Zpkg_versionr   r   r   _echo_litellm_version;   s   z0ProxyInitializationHelpers._echo_litellm_versionc                 C   s<   t d tjd|  d| dd}t tj| dd d S )Nz)
LiteLLM: Health Testing models in confighttp://:z/health)r      )indent)printhttpxgetjsondumps)hostportresponser   r   r   _run_health_check@   s   z,ProxyInitializationHelpers._run_health_checkr<   r=   modeltestc                 C   s   |pd}t d|  dd l}d|  d| }t|tr |}ntd|jd|d}|jjj	|d	d
dgdd}t d|  t
d|  |jjj	|d	d
dgdd}	|	D ]
}
t d|
  qXt
d |jj	|d
d}t
| d S )Nzgpt-3.5-turbozE
LiteLLM: Making a test ChatCompletions request to your proxy. Model=r   r3   r4   zInvalid test valuez
My API Key)Zapi_keybase_urluserz*this is a test request, write a short poem)Zrolecontent   )r@   messages
max_tokensz
LiteLLM: response from proxy zN
 LiteLLM: Making a test ChatCompletions + streaming r equest to proxy. Model=T)r@   rF   streamz'LiteLLM: streaming response from proxy z$
 making completion request to proxy)r@   prompt)r0   r1   openair   r   
ValueErrorZOpenAIZchatZcompletionscreater7   )r<   r=   r@   rA   Zrequest_modelrJ   api_baseclientr>   Zstream_responsechunkZcompletion_responser   r   r   _run_test_chat_completionF   sJ   


z4ProxyInitializationHelpers._run_test_chat_completionN
log_configkeepalive_timeoutr   c                 C   sd   ddl }ddlm} d| |d}|dur td|  ||d< n|jr(| |d< |dur0||d< |S )	z8
        Get the arguments for `uvicorn` worker
        r   N)_get_uvicorn_json_log_configzlitellm.proxy.proxy_server:app)appr<   r=   zUsing log_config: rQ   Ztimeout_keep_alive)r+   r   rS   r7   	json_logs)r<   r=   rQ   rR   r+   rS   uvicorn_argsr   r   r   _get_default_unvicorn_init_args|   s   


z:ProxyInitializationHelpers._get_default_unvicorn_init_argsrT   ssl_certfile_pathssl_keyfile_pathciphersc           
      C   s   ddl }ddlm} ddlm} td| d| d | }	| d| g|	_|durG|durGtd| d	| d
 ||	_||	_|durG||	_	|
|| |	 dS )z5
        Initialize litellm with `hypercorn`
        r   N)serve)Config)[1;32mLiteLLM Proxy: Starting server on r4   z using Hypercorn[0m
/[1;32mLiteLLM Proxy: Using SSL with certfile:  and keyfile: [0m
)asyncioZhypercorn.asyncior[   Zhypercorn.configr\   r7   bindcertfilekeyfilerZ   run)
rT   r<   r=   rX   rY   rZ   ra   r[   r\   configr   r   r   _init_hypercorn_server   s"   z1ProxyInitializationHelpers._init_hypercorn_servernum_workersmax_requests_before_restartc                    s   t jdkrnddl}G fddd|jjj}td|  d d| d	 |  d |d
ddddd}	|dur<||	d< t jdrRddl	m
   fdd}
|
|	d< |durm|durmtd| d| d ||	d< ||	d< |||	d  dS )z-
        Run litellm with `gunicorn`
        ntr   Nc                       s0   e Zd Zd fdd	Zdd Zdd Z  ZS )	zNProxyInitializationHelpers._run_gunicorn_server.<locals>.StandaloneApplicationNc                    sh   |pi | _ || _t   d d}|d }t  td td| d td td d d S )	Nz curl --location 'http://0.0.0.0:z/chat/completions' \ai  
                --header 'Content-Type: application/json' \
                --data ' {
                "model": "gpt-3.5-turbo",
                "messages": [
                    {
                    "role": "user",
                    "content": "what llm are you"
                    }
                ]
                }'
                

                z[1;34mLiteLLM: Test your local proxy with: "litellm --test" This runs an openai.ChatCompletion request to your proxy [In a new terminal tab][0m
z8[1;34mLiteLLM: Curl Command Test for your local proxy
 z [0m
z;[1;34mDocs: https://docs.litellm.ai/docs/simple_proxy[0m
z5[1;34mSee all Router/Swagger docs on http://0.0.0.0:)optionsapplicationsuper__init__r7   )selfrT   rk   Z_endpoint_strZcurl_command)	__class__r=   r   r   rn      s,   




zWProxyInitializationHelpers._run_gunicorn_server.<locals>.StandaloneApplication.__init__c                    sZ    j d ur fdd j D }ni }| D ]\}} j d ur* j | | qd S )Nc                    s*   i | ]\}}| j jv r|d ur||qS N)cfgsettings).0keyvaluero   r   r   
<dictcomp>   s
    znProxyInitializationHelpers._run_gunicorn_server.<locals>.StandaloneApplication.load_config.<locals>.<dictcomp>)rr   rk   itemssetlower)ro   rf   ru   rv   r   rw   r   load_config   s   


zZProxyInitializationHelpers._run_gunicorn_server.<locals>.StandaloneApplication.load_configc                 S   s   | j S rq   )rl   rw   r   r   r   load  s   zSProxyInitializationHelpers._run_gunicorn_server.<locals>.StandaloneApplication.loadrq   )r   r   r   rn   r|   r}   __classcell__r   )r=   )rp   r   StandaloneApplication   s    &r   r]   r4   z with z workers[0m
zuvicorn.workers.UvicornWorkerT-iX  z+%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s)rb   workersZworker_classZpreloadZ	accesslogtimeoutZaccess_log_formatZmax_requestsPROMETHEUS_MULTIPROC_DIRmark_worker_exitc                    s    |j  d S rq   )pid)serverZworkerr   r   r   
child_exit  s   zCProxyInitializationHelpers._run_gunicorn_server.<locals>.child_exitr   r^   r_   r`   rc   rd   )rT   rk   )osnameZgunicorn.app.baserT   baseZBaseApplicationr7   environr9    litellm.proxy.prometheus_cleanupr   re   )r<   r=   rT   rh   rX   rY   ri   Zgunicornr   Zgunicorn_optionsr   r   )r   r=   r   _run_gunicorn_server   s8   
9z/ProxyInitializationHelpers._run_gunicorn_serverc               
   C   s   z'ddg} t tjd}tj| ||d W d    W d S 1 s w   Y  W d S  tyB } ztd| d W Y d }~d S d }~ww )Nollamar[   w)stdoutstderrzh
                LiteLLM Warning: proxy started with `ollama` model
`ollama serve` failed with Exceptionz-. 
Ensure you run `ollama serve`
            )openr   devnull
subprocessPopen	Exceptionr7   )commandr   er   r   r   _run_ollama_serve*  s   &z,ProxyInitializationHelpers._run_ollama_servec                 C   sN   dd l }| |j|j}|d| fdkW  d    S 1 s w   Y  d S )Nr   	localhost)socketAF_INETSOCK_STREAM
connect_ex)r=   r   sr   r   r   _is_port_in_use8  s   $z*ProxyInitializationHelpers._is_port_in_usec                   C   s   t jdv rdS dS )zBHelper function to determine the event loop type based on platform)win32cygwincliNZuvloop)sysplatformr   r   r   r   _get_loop_type?  s   
z)ProxyInitializationHelpers._get_loop_typelitellm_settingsc                 C   s   ddl }| dks|du rdS |dpg }|dpg }|dp"g }|| | }d|vr/dS ddlm} tjd	p@tjd
}| }	|sTtj| d}|tjd	< tj	|dd || |	rcdnd}
t
d|
 d|  dS )z
        Auto-create PROMETHEUS_MULTIPROC_DIR when running with multiple workers
        and prometheus is configured as a callback.
        r   N   	callbacksZsuccess_callbackZfailure_callbackZ
prometheus)wipe_directoryr   Zprometheus_multiproc_dirZlitellm_prometheus_multiprocT)exist_okzAuto-createdzUsing existingz	LiteLLM: z PROMETHEUS_MULTIPROC_DIR=)tempfiler9   r   r   r   r   pathjoin
gettempdirmakedirsr7   )rh   r   r   r   Zsuccess_callbacksZfailure_callbacksZall_callbacksr   Zmultiproc_dirZauto_createdactionr   r   r   %_maybe_setup_prometheus_multiproc_dirF  s.   	

z@ProxyInitializationHelpers._maybe_setup_prometheus_multiproc_dir)NNrq   )r   r   r   staticmethodr2   r?   r   intr   boolrP   r   dictrW   r	   rg   r   r   r   r   r   r   r   r   r   r*   :   s    


5"n


r*   z--hostz0.0.0.0z!Host for the server to listen on.ZHOST)defaulthelpenvvarz--port  zPort to bind the server to.ZPORTz--num_workerszfNumber of uvicorn / gunicorn workers to spin up. Default is 1 (from DEFAULT_NUM_WORKERS_LITELLM_PROXY)ZNUM_WORKERSz
--api_basezAPI base URL.)r   r   z--api_versionz2024-07-01-previewz$For azure - pass in the api version.z--modelz-mz)The model name to pass to litellm expectsz--aliaszThe alias for the model - use this to give a litellm model name (e.g. "huggingface/codellama/CodeLlama-7b-Instruct-hf") a more user-friendly name ("codellama")z	--add_keyz	--headerszheaders for the API callz--saveTzSave the model-specific config)is_flagtyper   z--debugFzTo debug the inputDEBUG)r   r   r   r   r   z--detailed_debugzTo view detailed debug logsZDETAILED_DEBUGz--use_queuez)To use celery workers for async endpoints)r   r   r   r   z--temperaturezSet temperature for the model)r   r   r   z--max_tokenszSet max tokens for the modelz--request_timeoutz+Set timeout in seconds for completion callsz--drop_paramszDrop any unmapped params)r   r   z--add_function_to_promptz5If function passed but unsupported, pass it as promptz--configz-cz]Path to the proxy configuration file (e.g. config.yaml). Usage `litellm --config config.yaml`z--max_budgetz`Set max budget for API calls - works for hosted models like OpenAI, TogetherAI, Anthropic, etc.`z--telemetryzZHelps us know if people are using this feature. Turn this off by doing `--telemetry False`z--log_configz&Path to the logging configuration filez	--versionz-vzPrint LiteLLM versionz--healthz:Make a chat/completions request to all llms in config.yaml)
flag_valuer   z--testz4proxy chat completions url to make a test request toz--test_asyncz9Calls async endpoints /queue/requests and /queue/response)r   r   r   z--iam_token_db_authz!Connects to RDS DB with IAM tokenz--num_requestsr   z-Number of requests to hit async endpoint withz--run_gunicornzTStarts proxy via gunicorn, instead of uvicorn (better for managing multiple workers)z--run_hypercornz@Starts proxy via hypercorn, instead of uvicorn (supports HTTP/2)z--ssl_keyfile_pathz^Path to the SSL keyfile. Use this when you want to provide SSL certificate when starting proxyZSSL_KEYFILE_PATH)r   r   r   r   z--ssl_certfile_pathz_Path to the SSL certfile. Use this when you want to provide SSL certificate when starting proxyZSSL_CERTFILE_PATHz	--ciphersz!Ciphers to use for the SSL setup.z--use_prisma_db_pushzHUse prisma db push instead of prisma migrate for database schema updates)r   r   r   z--localzfor local debuggingz--skip_server_startupzASkip starting the server after setup (useful for migrations only)z--keepalive_timeoutzSSet the uvicorn keepalive timeout in seconds (uvicorn timeout_keep_alive parameter)ZKEEPALIVE_TIMEOUTz--max_requests_before_restartz]Restart worker after this many requests (uvicorn: limit_max_requests, gunicorn: max_requests)ZMAX_REQUESTS_BEFORE_RESTARTuse_prisma_db_pushc&           P   
   C   s  t  }&|rddlm}'m}(m})m}* nHzddlm}'m}(m})m}* W n9 ty4 }+ ztd|+ dd }+~+w tyY }+ zdt|+v rC|+ddlm}'m}(m})m}* W Y d }+~+nd }+~+ww |du rdt	
  d S |rrd|v rr|d u rrt	  |du r~t	| | d S |du rt	| ||| d S |rt|}|*d[i d	|d
|d|d|d|	d|
d|d|d|d|d|d|d|d|d|d|d| zdd l},W n ty   tdw d}-d}.i }/|stdr5ddlm}0 td}1td }2td!}3td"}4td#}5|0|1|2|3d$}6d%|3 d&|6 d'|1 d&|2 d(|4 
}7|5r+|7d)|5 7 }7|7tjd*< d+tjd< dd,lm}8 td-d d ur^td-d+kr^|8 }9|9 D ]
\}:};|;tj|:< qS|d urJ	 zdd l}<W n tyv   td.w |( }=|<|=j|d/}>|>d0d }?|?d urd1|?v r|?d1 du rdd l}@d|@_ |@!  |>d2i }/|/d u ri }/|/d3d }A|Ad urdd l}@|'d[i |A|@_"|/r|/d4d }B|=j#|B|d5 |/d6d }C|Cd u rtd*d u rdd7l$m%}D |D }C|Cr|Ctjd*< |/d8t&j'j(}-|/d9t&j)j(}.|Cr:|C*d:r:t+ }Et,j-.dtj-/d; dd l}@dd<lm0}F |F|Cd d=}Ct1|E |Cd urJt2|CtrJ|Ctjd*< |d u rhtd*d u rhdd7l$m%}D |D }C|Crh|Ctjd*< |d u rut&j'j(}-t&j)j(}.td*d d ustd>d d urzMdd?l3m4}G td*d d ur|-|.d@}H|Gd*d d=}Ct5|C|H}I|Itjd*< td>d d ur|-|.d@}Htd>}Ct5|C|H}I|Itjd>< t6jdAgddB d}JW n t7y   dC}JY nw |Jr
ddDl8m9}K ddEl:m;}Lm<}M |M|/dFdCu r|Kd dG n|Lj=|" dH nt>dI |dJkrt	?|rt@AdKdL}dd l}@|
du r,|@B  ddMlCm}) t	jD||r:|?nd dN |#rGt>dO d S t	jE| ||!|$dP}N|%d urY|%|NdQ< |dCu r|dCu r|d ur|d urt>dR| dS| dT ||NdU< ||NdV< t	F }O|Or|O|NdW< |,jd[i |NdX|i d S |du rt	jG| ||)||||%dY d S |du rt	jH|)| |||| dZ d S d S )\Nr   )KeyManagementSettingsProxyConfigrT   save_worker_configr   zMissing dependency z$. Run `pip install 'litellm[proxy]'`zlitellm[proxy]Tr   r@   aliasrM   api_versionr   detailed_debugtemperaturerG   request_timeout
max_budget	telemetrydrop_paramsadd_function_to_promptheaderssaverf   	use_queuezLuvicorn, gunicorn needs to be imported. Run - `pip install 'litellm[proxy]'`d   r   ZIAM_TOKEN_DB_AUTH)generate_iam_auth_tokenZDATABASE_HOSTZDATABASE_PORTZDATABASE_USERZDATABASE_NAMEZDATABASE_SCHEMA)db_hostdb_portdb_userzpostgresql://r4   @/z?schema=ZDATABASE_URLTrue)decrypt_env_varZUSE_AWS_KMSz?yaml needs to be imported. Run - `pip install 'litellm[proxy]'`)config_file_pathr   rU   general_settingskey_management_settingskey_management_system)r   r   database_url)$construct_database_url_from_env_varsr   r   zos.environ/z../..)get_secret_str)default_valueZ
DIRECT_URL)
get_secret)Zconnection_limitpool_timeoutZprisma)capture_outputF)check_prisma_schema_diff)PrismaManagershould_update_prisma_schemaZdisable_prisma_schema_update)Zdb_url)Zuse_migratezYUnable to connect to DB. DATABASE_URL found in environment, but prisma package not found.r   i   i   )rT   )rh   r   z>LiteLLM: Setup complete. Skipping server startup as requested.)r<   r=   rQ   rR   Zlimit_max_requestsr^   r_   r`   Zssl_keyfileZssl_certfileloopr   )r<   r=   rT   rh   rX   rY   ri   )rT   r<   r=   rX   rY   rZ   r   )IlocalsZproxy_serverr   r   rT   r   ModuleNotFoundErrorImportErrorr   r*   r2   r   r?   rP   r:   loadsuvicornr   r   Z litellm.proxy.auth.rds_iam_tokenr   r   getenvr   Z*litellm.secret_managers.aws_secret_managerr   ry   ra   re   Z
get_configr9   r+   rU   Z_turn_on_jsonZ_key_management_settingsZinitialize_secret_managerZlitellm.proxy.utilsr   r   r   rv   r   
startswithgetcwdr   r   insertabspathr   chdirr   litellm.secret_managers.mainr   r)   r   FileNotFoundErrorZ litellm.proxy.db.check_migrationr   Zlitellm.proxy.db.prisma_clientr   r   Zsetup_databaser7   r   randomrandintZ_turn_on_debugZlitellm.proxy.proxy_serverr   rW   r   r   rg   )Pr<   r=   rM   r   r@   r   Zadd_keyr   r   r   r   r   rG   r   r   r   rf   r   r   rA   localrh   Z
test_asyncZiam_token_db_authnum_requestsr   Zhealthr/   Zrun_gunicornZrun_hypercornrY   rX   rZ   rQ   r   Zskip_server_startuprR   ri   argsr   r   rT   r   r   r   Zdb_connection_pool_limitZdb_connection_timeoutr   r   r   r   r   Zdb_nameZ	db_schematokenZ_db_urlr   Znew_env_varkvra   proxy_config_configr   r+   r   r   r   r   Zoriginal_dirr   r   r   r(   Zis_prisma_runnabler   r   r   rV   Z	loop_typer   r   r   
run_serverp  s
   g
$
	





"





















	
r   __main__)-r-   r:   r   r   r   r   urllib.parseparser!   typingr   r   r   r   r0   r8   Zdotenvr   Zlitellm.constantsr   r   r   Zfastapir	   r   appendr   Zconfig_filenamer   Zlitellm_modeenumr
   r   r   r   r   r)   r*   r   optionr   floatr   r   r   r   r   r   r   <module>   s    8#X  
|
