repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | import os |
| #2 | from unittest.mock import Mock, patch |
| #3 | |
| #4 | import pytest |
| #5 | |
| #6 | from mem0.configs.llms.openai import OpenAIConfig |
| #7 | from mem0.llms.openai import OpenAILLM |
| #8 | |
| #9 | |
| #10 | @pytest.fixture |
| #11 | def mock_openai_client(): |
| #12 | with patch("mem0.llms.openai.OpenAI") as mock_openai: |
| #13 | mock_client = Mock() |
| #14 | mock_openai.return_value = mock_client |
| #15 | yield mock_client |
| #16 | |
| #17 | |
| #18 | def test_openai_llm_base_url(): |
| #19 | # case1: default config: with openai official base url |
| #20 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key") |
| #21 | llm = OpenAILLM(config) |
| #22 | # Note: openai client will parse the raw base_url into a URL object, which will have a trailing slash |
| #23 | assert str(llm.client.base_url) == "https://api.openai.com/v1/" |
| #24 | |
| #25 | # case2: with env variable OPENAI_API_BASE |
| #26 | provider_base_url = "https://api.provider.com/v1" |
| #27 | os.environ["OPENAI_BASE_URL"] = provider_base_url |
| #28 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key") |
| #29 | llm = OpenAILLM(config) |
| #30 | # Note: openai client will parse the raw base_url into a URL object, which will have a trailing slash |
| #31 | assert str(llm.client.base_url) == provider_base_url + "/" |
| #32 | |
| #33 | # case3: with config.openai_base_url |
| #34 | config_base_url = "https://api.config.com/v1" |
| #35 | config = OpenAIConfig( |
| #36 | model="gpt-4.1-nano-2025-04-14", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key", openai_base_url=config_base_url |
| #37 | ) |
| #38 | llm = OpenAILLM(config) |
| #39 | # Note: openai client will parse the raw base_url into a URL object, which will have a trailing slash |
| #40 | assert str(llm.client.base_url) == config_base_url + "/" |
| #41 | |
| #42 | |
| #43 | def test_generate_response_without_tools(mock_openai_client): |
| #44 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14", temperature=0.7, max_tokens=100, top_p=1.0) |
| #45 | llm = OpenAILLM(config) |
| #46 | messages = [ |
| #47 | {"role": "system", "content": "You are a helpful assistant."}, |
| #48 | {"role": "user", "content": "Hello, how are you?"}, |
| #49 | ] |
| #50 | |
| #51 | mock_response = Mock() |
| #52 | mock_response.choices = [Mock(message=Mock(content="I'm doing well, thank you for asking!"))] |
| #53 | mock_openai_client.chat.completions.create.return_value = mock_response |
| #54 | |
| #55 | response = llm.generate_response(messages) |
| #56 | |
| #57 | mock_openai_client.chat.completions.create.assert_called_once_with( |
| #58 | model="gpt-4.1-nano-2025-04-14", messages=messages, temperature=0.7, max_tokens=100, top_p=1.0, store=False |
| #59 | ) |
| #60 | assert response == "I'm doing well, thank you for asking!" |
| #61 | |
| #62 | |
| #63 | def test_generate_response_with_tools(mock_openai_client): |
| #64 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14", temperature=0.7, max_tokens=100, top_p=1.0) |
| #65 | llm = OpenAILLM(config) |
| #66 | messages = [ |
| #67 | {"role": "system", "content": "You are a helpful assistant."}, |
| #68 | {"role": "user", "content": "Add a new memory: Today is a sunny day."}, |
| #69 | ] |
| #70 | tools = [ |
| #71 | { |
| #72 | "type": "function", |
| #73 | "function": { |
| #74 | "name": "add_memory", |
| #75 | "description": "Add a memory", |
| #76 | "parameters": { |
| #77 | "type": "object", |
| #78 | "properties": {"data": {"type": "string", "description": "Data to add to memory"}}, |
| #79 | "required": ["data"], |
| #80 | }, |
| #81 | }, |
| #82 | } |
| #83 | ] |
| #84 | |
| #85 | mock_response = Mock() |
| #86 | mock_message = Mock() |
| #87 | mock_message.content = "I've added the memory for you." |
| #88 | |
| #89 | mock_tool_call = Mock() |
| #90 | mock_tool_call.function.name = "add_memory" |
| #91 | mock_tool_call.function.arguments = '{"data": "Today is a sunny day."}' |
| #92 | |
| #93 | mock_message.tool_calls = [mock_tool_call] |
| #94 | mock_response.choices = [Mock(message=mock_message)] |
| #95 | mock_openai_client.chat.completions.create.return_value = mock_response |
| #96 | |
| #97 | response = llm.generate_response(messages, tools=tools) |
| #98 | |
| #99 | mock_openai_client.chat.completions.create.assert_called_once_with( |
| #100 | model="gpt-4.1-nano-2025-04-14", messages=messages, temperature=0.7, max_tokens=100, top_p=1.0, tools=tools, tool_choice="auto", store=False |
| #101 | ) |
| #102 | |
| #103 | assert response["content"] == "I've added the memory for you." |
| #104 | assert len(response["tool_calls"]) == 1 |
| #105 | assert response["tool_calls"][0]["name"] == "add_memory" |
| #106 | assert response["tool_calls"][0]["arguments"] == {"data": "Today is a sunny day."} |
| #107 | |
| #108 | |
| #109 | def test_response_callback_invocation(mock_openai_client): |
| #110 | # Setup mock callback |
| #111 | mock_callback = Mock() |
| #112 | |
| #113 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14", response_callback=mock_callback) |
| #114 | llm = OpenAILLM(config) |
| #115 | messages = [{"role": "user", "content": "Test callback"}] |
| #116 | |
| #117 | # Mock response |
| #118 | mock_response = Mock() |
| #119 | mock_response.choices = [Mock(message=Mock(content="Response"))] |
| #120 | mock_openai_client.chat.completions.create.return_value = mock_response |
| #121 | |
| #122 | # Call method |
| #123 | llm.generate_response(messages) |
| #124 | |
| #125 | # Verify callback called with correct arguments |
| #126 | mock_callback.assert_called_once() |
| #127 | args = mock_callback.call_args[0] |
| #128 | assert args[0] is llm # llm_instance |
| #129 | assert args[1] == mock_response # raw_response |
| #130 | assert "messages" in args[2] # params |
| #131 | |
| #132 | |
| #133 | def test_no_response_callback(mock_openai_client): |
| #134 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14") |
| #135 | llm = OpenAILLM(config) |
| #136 | messages = [{"role": "user", "content": "Test no callback"}] |
| #137 | |
| #138 | # Mock response |
| #139 | mock_response = Mock() |
| #140 | mock_response.choices = [Mock(message=Mock(content="Response"))] |
| #141 | mock_openai_client.chat.completions.create.return_value = mock_response |
| #142 | |
| #143 | # Should complete without calling any callback |
| #144 | response = llm.generate_response(messages) |
| #145 | assert response == "Response" |
| #146 | |
| #147 | # Verify no callback is set |
| #148 | assert llm.config.response_callback is None |
| #149 | |
| #150 | |
| #151 | def test_callback_exception_handling(mock_openai_client): |
| #152 | # Callback that raises exception |
| #153 | def faulty_callback(*args): |
| #154 | raise ValueError("Callback error") |
| #155 | |
| #156 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14", response_callback=faulty_callback) |
| #157 | llm = OpenAILLM(config) |
| #158 | messages = [{"role": "user", "content": "Test exception"}] |
| #159 | |
| #160 | # Mock response |
| #161 | mock_response = Mock() |
| #162 | mock_response.choices = [Mock(message=Mock(content="Expected response"))] |
| #163 | mock_openai_client.chat.completions.create.return_value = mock_response |
| #164 | |
| #165 | # Should complete without raising |
| #166 | response = llm.generate_response(messages) |
| #167 | assert response == "Expected response" |
| #168 | |
| #169 | # Verify callback was called (even though it raised an exception) |
| #170 | assert llm.config.response_callback is faulty_callback |
| #171 | |
| #172 | |
| #173 | def test_callback_with_tools(mock_openai_client): |
| #174 | mock_callback = Mock() |
| #175 | config = OpenAIConfig(model="gpt-4.1-nano-2025-04-14", response_callback=mock_callback) |
| #176 | llm = OpenAILLM(config) |
| #177 | messages = [{"role": "user", "content": "Test tools"}] |
| #178 | tools = [ |
| #179 | { |
| #180 | "type": "function", |
| #181 | "function": { |
| #182 | "name": "test_tool", |
| #183 | "description": "A test tool", |
| #184 | "parameters": { |
| #185 | "type": "object", |
| #186 | "properties": {"param1": {"type": "string"}}, |
| #187 | "required": ["param1"], |
| #188 | }, |
| #189 | } |
| #190 | } |
| #191 | ] |
| #192 | |
| #193 | # Mock tool response |
| #194 | mock_response = Mock() |
| #195 | mock_message = Mock() |
| #196 | mock_message.content = "Tool response" |
| #197 | mock_tool_call = Mock() |
| #198 | mock_tool_call.function.name = "test_tool" |
| #199 | mock_tool_call.function.arguments = '{"param1": "value1"}' |
| #200 | mock_message.tool_calls = [mock_tool_call] |
| #201 | mock_response.choices = [Mock(message=mock_message)] |
| #202 | mock_openai_client.chat.completions.create.return_value = mock_response |
| #203 | |
| #204 | llm.generate_response(messages, tools=tools) |
| #205 | |
| #206 | # Verify callback called with tool response |
| #207 | mock_callback.assert_called_once() |
| #208 | # Check that tool_calls exists in the message |
| #209 | assert hasattr(mock_callback.call_args[0][1].choices[0].message, 'tool_calls') |
| #210 |