Skip to content

Commit b776126

Browse files
authored
Added doc for deploying langchain application. (#464)
2 parents 5859927 + 705ac05 commit b776126

File tree

6 files changed

+227
-0
lines changed

6 files changed

+227
-0
lines changed

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Oracle Accelerated Data Science (ADS)
6868
user_guide/logs/logs
6969
user_guide/pipeline/index
7070
user_guide/secrets/index
71+
user_guide/large_language_model/index
7172

7273
.. toctree::
7374
:hidden:
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
############################
2+
Deploy LangChain Application
3+
############################
4+
5+
Oracle ADS SDK now supports the deployment of LangChain application to OCI data science model deployment and you can easily do so just by writing a couple lines of code.
6+
7+
.. versionadded:: 2.9.1
8+
9+
Configuration
10+
*************
11+
12+
Ensure that you have created the necessary `policies, authentication, and authorization for model deployments <https://docs.oracle.com/en-us/iaas/data-science/using/model-dep-policies-auth.htm#model_dep_policies_auth>`_.
13+
Here we're using the ``resource_principal`` as auth type and you can configure the policy as below.
14+
15+
.. code-block:: shell
16+
17+
allow dynamic-group <dynamic-group-name> to manage data-science-model-deployments in compartment <compartment-name>
18+
19+
Create LangChain Application
20+
****************************
21+
22+
Create a simple LangChain application that links prompt and cohere model as below. Remember to replace the ``<cohere_api_key>`` with the actual cohere api key.
23+
24+
.. code-block:: python3
25+
26+
import os
27+
from langchain.llms import Cohere
28+
from langchain.chains import LLMChain
29+
from langchain.prompts import PromptTemplate
30+
os.environ["COHERE_API_KEY"] = "<cohere_api_key>"
31+
32+
cohere = Cohere()
33+
prompt = PromptTemplate.from_template("Tell me a joke about {subject}")
34+
llm_chain = LLMChain(prompt=prompt, llm=cohere, verbose=True)
35+
36+
Now you have a LangChain object ``llm_chain``. Try running it with the prompt ``{"subject": "animals"}`` and it should give you the corresponding result.
37+
38+
.. code-block:: python3
39+
40+
llm_chain.run({"subject": "animals"})
41+
42+
Initialize the ChainDeployment
43+
******************************
44+
45+
Initialize class ``ChainDeployment`` from ADS SDK and pass the LangChain object ``llm_chain`` from previous step as parameter.
46+
The ``artifact_dir`` is an optional parameter which points to the folder where the model artifacts will be put locally.
47+
In this example, we're using a temporary folder generated by ``tempfile``.
48+
49+
.. code-block:: python3
50+
51+
import tempfile
52+
from ads.llm.deploy import ChainDeployment
53+
54+
artifact_dir = tempfile.mkdtemp()
55+
56+
chain_deployment = ChainDeployment(
57+
chain=llm_chain,
58+
artifact_dir=artifact_dir
59+
)
60+
61+
Prepare the Model Artifacts
62+
***************************
63+
64+
Call ``prepare`` from ``ChainDeployment`` to generate the ``score.py`` and serialize the LangChain application to ``chain.yaml`` file under ``artifact_dir`` folder.
65+
Parameters ``inference_conda_env`` and ``inference_python_version`` are passed to define the conda environment where your LangChain application will be running on OCI cloud.
66+
Here we're using ``pytorch21_p39_gpu_v1`` with python 3.9.
67+
68+
.. code-block:: python3
69+
70+
chain_deployment.prepare(
71+
inference_conda_env="pytorch21_p39_gpu_v1",
72+
inference_python_version="3.9",
73+
)
74+
75+
Below is the ``chain.yaml`` file that was saved from ``llm_chain`` object. For more information regarding LLMs model serialization, see `here <https://python.langchain.com/docs/modules/model_io/llms/llm_serialization>`_.
76+
77+
.. code-block:: YAML
78+
79+
_type: llm_chain
80+
llm:
81+
_type: cohere
82+
frequency_penalty: 0.0
83+
k: 0
84+
max_tokens: 256
85+
model: null
86+
p: 1
87+
presence_penalty: 0.0
88+
temperature: 0.75
89+
truncate: null
90+
llm_kwargs: {}
91+
memory: null
92+
metadata: null
93+
output_key: text
94+
output_parser:
95+
_type: default
96+
prompt:
97+
_type: prompt
98+
input_types: {}
99+
input_variables:
100+
- subject
101+
output_parser: null
102+
partial_variables: {}
103+
template: Tell me a joke about {subject}
104+
template_format: f-string
105+
validate_template: false
106+
return_final_only: true
107+
tags: null
108+
verbose: true
109+
110+
Save Artifacts to OCI Model Catalog
111+
***********************************
112+
113+
Call ``save`` to pack and upload the artifacts under ``artifact_dir`` to OCI data science model catalog. Once the artifacts are successfully uploaded, you should be able to see the id of the model.
114+
115+
.. code-block:: python3
116+
117+
chain_deployment.save(display_name="LangChain Model")
118+
119+
Deploy the Model
120+
****************
121+
122+
Deploy the LangChain model from previous step by calling ``deploy``. Remember to replace the ``<cohere_api_key>`` with the actual cohere api key in the ``environment_variables``.
123+
It usually takes a couple of minutes to deploy the model and you should see the model deployment in the output once the process completes.
124+
125+
.. code-block:: python3
126+
127+
chain_deployment.deploy(
128+
display_name="LangChain Model Deployment",
129+
environment_variables={"COHERE_API_KEY":"<cohere_api_key>"},
130+
)
131+
132+
Invoke the Deployed Model
133+
*************************
134+
135+
Now the OCI data science model deployment endpoint is ready and you can invoke it to ``tell a joke about animals``.
136+
137+
.. code-block:: python3
138+
139+
chain_deployment.predict(data={"subject": "animals"})["output"]
140+
141+
.. figure:: figures/prediction.png
142+
:width: 800
143+
144+
Alternatively, you can use OCI CLI to invoke the model deployment. Remember to replace the ``langchain_application_model_deployment_url`` with the actual model deployment url which you can find in the output from deploy step.
145+
146+
.. code-block:: shell
147+
148+
oci raw-request --http-method POST --target-uri <langchain_application_model_deployment_url>/predict --request-body '{"subject": "animals"}' --auth resource_principal
149+
150+
.. figure:: figures/cli_prediction.png
151+
:width: 800
Loading
Loading
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.. _large_language_model:
2+
3+
####################
4+
Large Language Model
5+
####################
6+
7+
8+
.. toctree::
9+
:hidden:
10+
:maxdepth: 2
11+
12+
deploy_langchain_application
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import os
2+
import tempfile
3+
from unittest.mock import MagicMock, patch
4+
5+
from ads.llm.deploy import ChainDeployment
6+
7+
from langchain.chains import LLMChain
8+
from langchain.prompts import PromptTemplate
9+
from tests.unitary.with_extras.langchain.test_guardrails import FakeLLM
10+
11+
class TestLangChainDeploy:
12+
13+
def generate_chain_application(self):
14+
prompt = PromptTemplate.from_template("Tell me a joke about {subject}")
15+
llm_chain = LLMChain(prompt=prompt, llm=FakeLLM(), verbose=True)
16+
return llm_chain
17+
18+
@patch("ads.model.datascience_model.DataScienceModel._to_oci_dsc_model")
19+
def test_initialize(self, mock_to_oci_dsc_model):
20+
chain_application = self.generate_chain_application()
21+
chain_deployment = ChainDeployment(chain_application, auth=MagicMock())
22+
mock_to_oci_dsc_model.assert_called()
23+
assert isinstance(chain_deployment.chain, LLMChain)
24+
25+
@patch("ads.model.runtime.env_info.get_service_packs")
26+
@patch("ads.common.auth.default_signer")
27+
@patch("ads.model.datascience_model.DataScienceModel._to_oci_dsc_model")
28+
def test_prepare(self, mock_to_oci_dsc_model, mock_default_signer, mock_get_service_packs):
29+
mock_default_signer.return_value = MagicMock()
30+
inference_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1"
31+
inference_python_version="3.7"
32+
mock_get_service_packs.return_value = (
33+
{
34+
inference_conda_env : ("mlcpuv1", inference_python_version),
35+
},
36+
{
37+
"mlcpuv1" : (inference_conda_env, inference_python_version),
38+
}
39+
)
40+
artifact_dir = tempfile.mkdtemp()
41+
chain_application = self.generate_chain_application()
42+
chain_deployment = ChainDeployment(
43+
chain_application,
44+
artifact_dir=artifact_dir,
45+
auth=MagicMock()
46+
)
47+
48+
mock_to_oci_dsc_model.assert_called()
49+
mock_default_signer.assert_called()
50+
51+
chain_deployment.prepare(
52+
inference_conda_env="oci://service-conda-packs@ociodscdev/service_pack/cpu/General_Machine_Learning_for_CPUs/1.0/mlcpuv1",
53+
inference_python_version="3.7"
54+
)
55+
56+
mock_get_service_packs.assert_called()
57+
58+
score_py_file_location = os.path.join(chain_deployment.artifact_dir, "score.py")
59+
chain_yaml_file_location = os.path.join(chain_deployment.artifact_dir, "chain.yaml")
60+
runtime_yaml_file_location = os.path.join(chain_deployment.artifact_dir, "runtime.yaml")
61+
assert os.path.isfile(score_py_file_location) and os.path.getsize(score_py_file_location) > 0
62+
assert os.path.isfile(chain_yaml_file_location) and os.path.getsize(chain_yaml_file_location) > 0
63+
assert os.path.isfile(runtime_yaml_file_location) and os.path.getsize(runtime_yaml_file_location) > 0

0 commit comments

Comments
 (0)