contentgrid-assistant-api 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. contentgrid_assistant_api-0.1.0/LICENSE +13 -0
  2. contentgrid_assistant_api-0.1.0/PKG-INFO +401 -0
  3. contentgrid_assistant_api-0.1.0/README.md +358 -0
  4. contentgrid_assistant_api-0.1.0/pyproject.toml +43 -0
  5. contentgrid_assistant_api-0.1.0/setup.cfg +4 -0
  6. contentgrid_assistant_api-0.1.0/setup.py +3 -0
  7. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/app.py +131 -0
  8. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/config.py +55 -0
  9. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/db/repositories/thread_repository.py +78 -0
  10. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/db/types/message.py +25 -0
  11. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/db/types/thread.py +46 -0
  12. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/dependencies.py +79 -0
  13. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/routers/agent_home.py +41 -0
  14. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/routers/message_router.py +256 -0
  15. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/routers/thread_router.py +129 -0
  16. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/types/agents.py +50 -0
  17. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api/types/context.py +9 -0
  18. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api.egg-info/PKG-INFO +401 -0
  19. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api.egg-info/SOURCES.txt +22 -0
  20. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api.egg-info/dependency_links.txt +1 -0
  21. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api.egg-info/requires.txt +17 -0
  22. contentgrid_assistant_api-0.1.0/src/contentgrid_assistant_api.egg-info/top_level.txt +1 -0
  23. contentgrid_assistant_api-0.1.0/tests/test_thread_access_control.py +427 -0
  24. contentgrid_assistant_api-0.1.0/tests/test_tools_endpoint.py +317 -0
@@ -0,0 +1,13 @@
1
+ Copyright 2024 Xenit Solutions
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,401 @@
1
+ Metadata-Version: 2.4
2
+ Name: contentgrid-assistant-api
3
+ Version: 0.1.0
4
+ Summary: FastAPI wrapper for contentgrid assistants
5
+ Author-email: Ranec Belpaire <ranec.belpaire@xenit.eu>
6
+ License: Copyright 2024 Xenit Solutions
7
+
8
+ Licensed under the Apache License, Version 2.0 (the "License");
9
+ you may not use this file except in compliance with the License.
10
+ You may obtain a copy of the License at
11
+
12
+ http://www.apache.org/licenses/LICENSE-2.0
13
+
14
+ Unless required by applicable law or agreed to in writing, software
15
+ distributed under the License is distributed on an "AS IS" BASIS,
16
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ See the License for the specific language governing permissions and
18
+ limitations under the License.
19
+ Classifier: Development Status :: 3 - Alpha
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Requires-Python: >=3.5
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: fastapi>=0.124.0
26
+ Requires-Dist: openai>=2.7.2
27
+ Requires-Dist: pydantic<3,>=2.11.9
28
+ Requires-Dist: pydantic-settings>=2.12.0
29
+ Requires-Dist: langchain>=1.2.3
30
+ Requires-Dist: langchain_openai>=1.1.7
31
+ Requires-Dist: langgraph>=1.0.5
32
+ Requires-Dist: langgraph-checkpoint-postgres>=3.0.2
33
+ Requires-Dist: python-dotenv>=1.1.1
34
+ Requires-Dist: requests<3,>=2.32.5
35
+ Requires-Dist: types-requests>=2.32.4
36
+ Requires-Dist: uri-template<2,>=1.3.0
37
+ Requires-Dist: sqlalchemy>=2.0.45
38
+ Requires-Dist: psycopg[binary]>=3.3.2
39
+ Requires-Dist: contentgrid_extension_helpers>=0.0.3
40
+ Requires-Dist: sqlmodel>=0.0.31
41
+ Requires-Dist: python-multipart>=0.0.21
42
+ Dynamic: license-file
43
+
44
+ # ContentGrid Assistant API
45
+
46
+ A FastAPI framework for building conversational AI assistants with LangGraph integration, designed for the ContentGrid ecosystem.
47
+
48
+ ## Overview
49
+
50
+ ContentGrid Assistant API provides a comprehensive framework for creating multi-agent conversational assistants with persistent chat threads, streaming responses, and HAL (Hypertext Application Language) compliant REST APIs. Built on FastAPI and LangGraph, it offers a structured approach to deploying AI agents with built-in authentication, database persistence, and tool calling capabilities.
51
+
52
+ ## Key Features
53
+
54
+ - **Multi-Agent Architecture**: Support for multiple independent agents with their own tools and configurations
55
+ - **Thread-Based Conversations**: Persistent conversation threads with PostgreSQL or SQLite storage
56
+ - **LangGraph Integration**: Built-in checkpoint persistence and state management for complex agent workflows
57
+ - **Streaming Support**: Real-time streaming responses for interactive chat experiences
58
+ - **HAL REST APIs**: Hypermedia-driven APIs following HAL specification for discoverability
59
+ - **Authentication**: Integrated ContentGrid user authentication and authorization
60
+ - **File Upload Support**: Handle images, audio, PDFs, and other file attachments in conversations
61
+ - **Tool Calling**: Built-in support for LangChain tools with automatic execution and response handling
62
+ - **Database Flexibility**: PostgreSQL for production or SQLite for development/testing
63
+ - **CORS & Middleware**: Configurable CORS and exception handling middleware
64
+
65
+ ## Architecture
66
+
67
+ ### Core Components
68
+
69
+ - **ContentGridAssistantAPI**: Specialized FastAPI application with pre-configured routes and middleware
70
+ - **Agent**: Configurable agent with custom tools, authentication, and context management
71
+ - **Thread Management**: CRUD operations for conversation threads with user isolation
72
+ - **Message Handling**: Support for Human, AI, System, and Tool messages with content blocks
73
+ - **Dependency Injection**: Structured dependency resolution for database, authentication, and agent access
74
+
75
+ ### API Structure
76
+
77
+ ```
78
+ /{agent_name}/
79
+ ├── GET / # Agent home with HAL links
80
+ ├── GET /tools # List available agent tools
81
+ └── /threads
82
+ ├── GET / # List user's threads
83
+ ├── POST / # Create new thread
84
+ └── /{thread_id}
85
+ ├── GET / # Get thread details
86
+ ├── PATCH / # Update thread
87
+ ├── DELETE / # Delete thread
88
+ └── /messages
89
+ ├── GET / # List messages in thread
90
+ └── POST / # Add message to thread (supports streaming)
91
+ ```
92
+
93
+ ## Installation
94
+
95
+ ```bash
96
+ pip install contentgrid-assistant-api
97
+ ```
98
+
99
+ Or install from source:
100
+
101
+ ```bash
102
+ git clone <repository-url>
103
+ cd contentgrid-assistant-api/contentgrid_assistant_api
104
+ pip install -e .
105
+ ```
106
+
107
+ ## Quick Start
108
+
109
+ ```python
110
+ from contentgrid_assistant_api.app import ContentGridAssistantAPI
111
+ from contentgrid_assistant_api.types.agents import Agent
112
+ from contentgrid_extension_helpers.authentication.user import ContentGridUser
113
+
114
+ def get_current_user() -> ContentGridUser:
115
+ # Implement your authentication logic
116
+ return ContentGridUser(...)
117
+
118
+ def compile_my_agent(checkpointer):
119
+ # Return your LangGraph compiled agent
120
+ return compiled_graph
121
+
122
+ agents = [
123
+ Agent(
124
+ name="my_agent",
125
+ version="v1.0.0",
126
+ get_current_user_override=get_current_user,
127
+ get_agent_override=compile_my_agent,
128
+ tools=my_tools
129
+ )
130
+ ]
131
+
132
+ app = ContentGridAssistantAPI(agents=agents)
133
+ ```
134
+
135
+ ## How to Use the Library
136
+
137
+ ### Step 1: Create Your Tools
138
+
139
+ Define tools that your agent can use. Tools are LangChain-compatible functions decorated with `@tool`:
140
+
141
+ ```python
142
+ from langchain_core.tools import tool
143
+
144
+ @tool("get_weather")
145
+ def get_weather(location: str) -> str:
146
+ """Get the current weather for a location"""
147
+ # Your implementation
148
+ return f"Weather in {location}: Sunny, 72°F"
149
+
150
+ @tool("send_message")
151
+ def send_message(recipient: str, message: str) -> str:
152
+ """Send a message to a recipient"""
153
+ # Your implementation
154
+ return f"Message sent to {recipient}"
155
+
156
+ tools = [get_weather, send_message]
157
+ ```
158
+
159
+ ### Step 2: Define Agent Context
160
+
161
+ Create a context class that extends `AgentState` to hold thread-specific data:
162
+
163
+ ```python
164
+ from langgraph.graph import MessagesState
165
+
166
+ class ThreadContext(MessagesState):
167
+ """Context for your agent's conversation thread"""
168
+ user_id: str = None
169
+ conversation_type: str = None
170
+ # Add any other context fields your agent needs
171
+ pass
172
+ ```
173
+
174
+ ### Step 3: Create the LLM Model
175
+
176
+ Initialize your language model using your preferred provider (OpenAI, Anthropic, Google, etc.):
177
+
178
+ ```python
179
+ from langchain_openai import ChatOpenAI
180
+
181
+ model = ChatOpenAI(
182
+ model="gpt-4o",
183
+ api_key="your-api-key"
184
+ )
185
+ model_with_tools = model.bind_tools(tools, parallel_tool_calls=False)
186
+ ```
187
+
188
+ ### Step 4: Build the Agent Graph
189
+
190
+ Create a LangGraph state graph that defines your agent's workflow:
191
+
192
+ ```python
193
+ from langgraph.graph import StateGraph, START, END
194
+ from langgraph.prebuilt import ToolNode
195
+ from langchain_core.messages import SystemMessage, AIMessage
196
+ import typing
197
+
198
+ class AgentState(MessagesState):
199
+ pass
200
+
201
+ tool_node = ToolNode(tools)
202
+
203
+ @typing.no_type_check
204
+ def llm_call(state: AgentState) -> AgentState:
205
+ """Call the LLM with the current conversation"""
206
+ system_prompt = "You are a helpful assistant"
207
+ messages = state['messages']
208
+
209
+ new_message = model_with_tools.invoke(
210
+ [SystemMessage(content=system_prompt)] + messages
211
+ )
212
+
213
+ state['messages'] = [new_message]
214
+ return state
215
+
216
+ def should_continue(state: AgentState):
217
+ """Decide if we should call tools or end"""
218
+ messages = state["messages"]
219
+ last_message = messages[-1]
220
+
221
+ if isinstance(last_message, AIMessage) and last_message.tool_calls:
222
+ return "tool_node"
223
+ return END
224
+
225
+ # Build the graph
226
+ agent_builder = StateGraph(AgentState, context_schema=ThreadContext)
227
+ agent_builder.add_node("llm_call", llm_call)
228
+ agent_builder.add_node("tool_node", tool_node)
229
+ agent_builder.add_edge(START, "llm_call")
230
+ agent_builder.add_conditional_edges("llm_call", should_continue, ["tool_node", END])
231
+ agent_builder.add_edge("tool_node", "llm_call")
232
+
233
+ def compile_my_agent(checkpointer):
234
+ """Compile the agent with checkpointer for persistence"""
235
+ if checkpointer:
236
+ return agent_builder.compile(checkpointer=checkpointer)
237
+ return agent_builder.compile()
238
+ ```
239
+
240
+ ### Step 5: Initialize the Application
241
+
242
+ Create your FastAPI application with one or more agents:
243
+
244
+ ```python
245
+ from contentgrid_assistant_api.app import ContentGridAssistantAPI
246
+ from contentgrid_assistant_api.types.agents import Agent
247
+ from contentgrid_extension_helpers.authentication.user import ContentGridUser
248
+
249
+ def get_current_user() -> ContentGridUser:
250
+ """Provide authentication context"""
251
+ return ContentGridUser(
252
+ ...
253
+ )
254
+
255
+ agents = [
256
+ Agent(
257
+ name="my_assistant",
258
+ version="v1.0.0",
259
+ get_current_user_override=get_current_user,
260
+ get_agent_override=compile_my_agent,
261
+ thread_context=ThreadContext,
262
+ tools=tools
263
+ )
264
+ ]
265
+
266
+ app = ContentGridAssistantAPI(agents=agents)
267
+
268
+ if __name__ == "__main__":
269
+ import uvicorn
270
+ uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)
271
+ ```
272
+
273
+ ### Step 6: Using the API
274
+
275
+ The API provides REST endpoints for each agent. All requests require authentication via the ContentGrid user context. The endpoints follow this pattern: `/api/{agent_name}/...`
276
+
277
+ **Thread Management:**
278
+ - `POST /api/{agent_name}/threads` - Create a new conversation thread
279
+ - `GET /api/{agent_name}/threads` - List all threads for the current user (with pagination)
280
+ - `GET /api/{agent_name}/threads/{thread_id}` - Retrieve a specific thread
281
+ - `PATCH /api/{agent_name}/threads/{thread_id}` - Update thread metadata
282
+ - `DELETE /api/{agent_name}/threads/{thread_id}` - Delete a thread
283
+
284
+ **Message Management:**
285
+ - `GET /api/{agent_name}/threads/{thread_id}/messages` - Retrieve all messages in a thread
286
+ - `POST /api/{agent_name}/threads/{thread_id}/messages` - Send a message to the agent
287
+
288
+ The message endpoint supports two modes:
289
+ - **Non-streaming**: Returns the human message immediately while the agent response is processed in the background
290
+ - **Streaming**: Stream the agent's response in real-time by including the `Accept: text/event-stream` header. The response is sent as server-sent events (SSE) with message chunks and completion signals
291
+
292
+ **File Uploads:**
293
+ When posting a message, you can optionally attach a file.
294
+ The file content is automatically converted into appropriate content blocks and sent to the agent for analysis.
295
+
296
+ ### Example: Multi-Agent Server
297
+
298
+ See `example_server/server.py` for a complete example with multiple agents:
299
+
300
+ ```python
301
+ from agents.joke_agent.agent import compile_joke_agent
302
+ from agents.order_agent.agent import compile_order_agent
303
+ # ... imports ...
304
+
305
+ agents = [
306
+ Agent(name="joker", version="v0.0.0",
307
+ get_current_user_override=get_dummy_user,
308
+ get_agent_override=compile_joke_agent,
309
+ thread_context=ThreadContext,
310
+ tools=joke_tools),
311
+ Agent(name="order_bot", version="v0.0.0",
312
+ get_current_user_override=get_dummy_user,
313
+ get_agent_override=compile_order_agent,
314
+ thread_context=OrderThreadContext,
315
+ tools=order_tools)
316
+ ]
317
+
318
+ app = ContentGridAssistantAPI(agents=agents)
319
+ ```
320
+
321
+ This creates two separate conversation assistants accessible at:
322
+ - `/api/joker/threads` - For the joke agent
323
+ - `/api/order_bot/threads` - For the order agent
324
+
325
+ ## Configuration
326
+
327
+ ### Environment Variables
328
+
329
+ Configure via `.env` file or environment variables:
330
+
331
+ ```bash
332
+ # Server Configuration
333
+ SERVER_PORT=8000
334
+ SERVER_URL=http://localhost:8000
335
+ PRODUCTION=false
336
+ WEB_CONCURRENCY=1
337
+
338
+ # Database Configuration
339
+ PG_DBNAME=assistant
340
+ PG_USER=assistant
341
+ PG_PASSWD=assistant
342
+ PG_HOST=postgres
343
+ PG_PORT=5432
344
+ USE_SQLITE_DB=false
345
+
346
+ # Assistant Configuration
347
+ GRAPH_RECURSION_LIMIT=100
348
+ OPENING_MESSAGE="Hello! How can I help you today?"
349
+
350
+ # Path Configuration
351
+ EXTENSION_PATH_PREFIX=/api
352
+ ```
353
+
354
+ ### Configuration Classes
355
+
356
+ - **AssistantExtensionConfig**: Application-level configuration
357
+ - **DatabaseConfig**: Database connection and initialization settings
358
+
359
+ ## Message Types
360
+
361
+ The API supports rich message content including:
362
+
363
+ - **Text**: Plain text messages
364
+ - **Images**: Base64-encoded images with MIME type
365
+ - **Audio**: Audio file attachments
366
+ - **Files**: PDF and other document attachments
367
+ - **Tool Calls**: Agent tool invocations and responses
368
+
369
+ ## Database Schema
370
+
371
+ ### Threads Table
372
+ - `id`: UUID primary key
373
+ - `name`: Thread name
374
+ - `origin`: Optional origin URL/identifier
375
+ - `component`: Component type (default: datamodel)
376
+ - `user_sub`: User subject identifier
377
+ - `created_at`: Timestamp
378
+
379
+ ### Messages
380
+ Messages are stored in LangGraph's checkpoint system with support for:
381
+ - Conversation history
382
+ - Tool call results
383
+ - State snapshots
384
+ - Rollback capabilities
385
+
386
+ ## Development
387
+
388
+ ### Running Tests
389
+
390
+ ```bash
391
+ cd contentgrid_assistant_api
392
+ pytest
393
+ ```
394
+
395
+ ## License
396
+
397
+ See LICENSE file for details.
398
+
399
+ ## Author
400
+
401
+ Ranec Belpaire (ranec.belpaire@xenit.eu)