Skip to content

Commit

Permalink
Support for OpenAI's .with_raw_response. (#1138)
Browse files Browse the repository at this point in the history
* Add initial fixes and tests

* Update v1 mock server responses

* Remove commented out code

* Use attribute checks instead

* Change try/except to hasattr checks

* Remove psuedo code in comments

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
lrafeei and mergify[bot] committed Jun 10, 2024
1 parent 2ab12c5 commit 60c5549
Show file tree
Hide file tree
Showing 7 changed files with 1,004 additions and 278 deletions.
22 changes: 18 additions & 4 deletions newrelic/hooks/mlmodel_openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import logging
import sys
import traceback
Expand Down Expand Up @@ -251,11 +252,17 @@ def _record_embedding_success(transaction, embedding_id, linking_metadata, kwarg
response_headers = getattr(response, "_nr_response_headers", {})
input = kwargs.get("input")

attribute_response = response
# In v1, response objects are pydantic models so this function call converts the
# object back to a dictionary for backwards compatibility.
attribute_response = response
if OPENAI_V1:
attribute_response = response.model_dump()
if hasattr(response, "model_dump"):
attribute_response = response.model_dump()
elif hasattr(response, "http_response") and hasattr(response.http_response, "text"):
# This is for the .with_raw_response. wrapper. This is expected
# to change, but the return type for now is the following:
# openai._legacy_response.LegacyAPIResponse
attribute_response = json.loads(response.http_response.text.strip())

request_id = response_headers.get("x-request-id")
response_model = attribute_response.get("model")
Expand Down Expand Up @@ -441,11 +448,18 @@ def _handle_completion_success(transaction, linking_metadata, completion_id, kwa
# If response is not a stream generator, record the event data.
# At this point, we have a response so we can grab attributes only available on the response object
response_headers = getattr(return_val, "_nr_response_headers", {})
response = return_val

# In v1, response objects are pydantic models so this function call converts the
# object back to a dictionary for backwards compatibility.
response = return_val
if OPENAI_V1:
response = response.model_dump()
if hasattr(response, "model_dump"):
response = response.model_dump()
elif hasattr(response, "http_response") and hasattr(response.http_response, "text"):
# This is for the .with_raw_response. wrapper. This is expected
# to change, but the return type for now is the following:
# openai._legacy_response.LegacyAPIResponse
response = json.loads(response.http_response.text.strip())

_record_completion_success(transaction, linking_metadata, completion_id, kwargs, ft, response_headers, response)
except Exception:
Expand Down
294 changes: 61 additions & 233 deletions tests/mlmodel_openai/_mock_external_openai_server.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/mlmodel_openai/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def _wrap_httpx_client_send(wrapped, instance, args, kwargs):
# Send request
response = wrapped(*args, **kwargs)

if response.status_code >= 400 or response.status_code < 200:
if response.status_code >= 500 or response.status_code < 200:
prompt = "error"

rheaders = getattr(response, "headers")
Expand Down
Loading

0 comments on commit 60c5549

Please sign in to comment.