Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
poc-api
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
poc
poc-api
Commits
7ccfc95c
Commit
7ccfc95c
authored
Feb 27, 2025
by
alex yao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:记录对话的模型推理内容
parent
da705bb9
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
134 additions
and
18 deletions
+134
-18
AgentApplicationInfoService.java
...nt_application/aggregate/AgentApplicationInfoService.java
+5
-4
AgentApplicationInfoServiceImpl.java
...ation/aggregate/impl/AgentApplicationInfoServiceImpl.java
+17
-7
BizAgentApplicationDialoguesRecordConvert.java
...on/convert/BizAgentApplicationDialoguesRecordConvert.java
+4
-0
BizAgentApplicationDialoguesRecordDto.java
...pplication/dto/BizAgentApplicationDialoguesRecordDto.java
+14
-0
AgentResultEntity.java
...n/com/poc/agent_application/entity/AgentResultEntity.java
+28
-0
BizAgentApplicationDialoguesRecordEntity.java
...tion/entity/BizAgentApplicationDialoguesRecordEntity.java
+14
-0
BizAgentApplicationDialoguesRecordModel.java
...cation/model/BizAgentApplicationDialoguesRecordModel.java
+16
-0
AgentApplicationDialoguesRecordQuery.sql
...pplication/query/AgentApplicationDialoguesRecordQuery.sql
+1
-0
AgentApplicationDialoguesRecordQueryItem.java
...ation/query/AgentApplicationDialoguesRecordQueryItem.java
+13
-0
BizAgentApplicationDialoguesRecordServiceImpl.java
...e/impl/BizAgentApplicationDialoguesRecordServiceImpl.java
+3
-0
AgentApplicationApiServiceImpl.java
...expose/aggregate/impl/AgentApplicationApiServiceImpl.java
+2
-2
AgentApplicationServiceImpl.java
...oc/expose/aggregate/impl/AgentApplicationServiceImpl.java
+4
-5
DialoguesContextDto.java
src/main/java/cn/com/poc/expose/dto/DialoguesContextDto.java
+12
-0
AgentApplicationRestImpl.java
...cn/com/poc/expose/rest/impl/AgentApplicationRestImpl.java
+1
-0
No files found.
src/main/java/cn/com/poc/agent_application/aggregate/AgentApplicationInfoService.java
View file @
7ccfc95c
package
cn
.
com
.
poc
.
agent_application
.
aggregate
;
import
cn.com.poc.agent_application.domain.FunctionResult
;
import
cn.com.poc.agent_application.entity.AgentResultEntity
;
import
cn.com.poc.agent_application.entity.BizAgentApplicationInfoEntity
;
import
cn.com.poc.agent_application.entity.CreateAgentTitleAndDescEntity
;
import
cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message
;
...
...
@@ -51,7 +52,7 @@ public interface AgentApplicationInfoService {
* @param imageUrls 图片URLs
* @param stream 是否流式传输
*/
String
callAgentApplication
(
String
agentId
,
String
identifier
,
String
largeModel
,
String
agentSystem
,
AgentResultEntity
callAgentApplication
(
String
agentId
,
String
identifier
,
String
largeModel
,
String
agentSystem
,
Integer
[]
knowledgeIds
,
Integer
communicationTurn
,
Float
topP
,
Float
temperature
,
List
<
Message
>
messages
,
List
<
Tool
>
tools
,
List
<
String
>
fileUrls
,
boolean
stream
,
List
<
String
>
imageUrls
,
HttpServletResponse
httpServletResponse
)
throws
Exception
;
...
...
@@ -73,7 +74,7 @@ public interface AgentApplicationInfoService {
* @param imageUrls 图片URLs
* @param stream 是否流式传输
*/
String
callAgentApplication
(
String
agentId
,
String
identifier
,
String
largeModel
,
String
agentSystem
,
AgentResultEntity
callAgentApplication
(
String
agentId
,
String
identifier
,
String
largeModel
,
String
agentSystem
,
Integer
[]
knowledgeIds
,
Integer
communicationTurn
,
Float
topP
,
Float
temperature
,
List
<
Message
>
messages
,
List
<
Tool
>
tools
,
FunctionCallResult
functionCallResult
,
List
<
String
>
fileUrls
,
boolean
stream
,
List
<
String
>
imageUrls
,
HttpServletResponse
httpServletResponse
)
throws
Exception
;
...
...
src/main/java/cn/com/poc/agent_application/aggregate/impl/AgentApplicationInfoServiceImpl.java
View file @
7ccfc95c
...
...
@@ -170,7 +170,7 @@ public class AgentApplicationInfoServiceImpl implements AgentApplicationInfoServ
}
@Override
public
String
callAgentApplication
(
String
agentId
,
String
dialogueId
,
String
largeModel
,
public
AgentResultEntity
callAgentApplication
(
String
agentId
,
String
dialogueId
,
String
largeModel
,
String
agentSystem
,
Integer
[]
kdIds
,
Integer
communicationTurn
,
Float
topP
,
Float
temperature
,
List
<
Message
>
messages
,
List
<
Tool
>
tools
,
List
<
String
>
fileUrls
,
boolean
stream
,
List
<
String
>
imageUrls
,
HttpServletResponse
httpServletResponse
)
throws
Exception
{
logger
.
info
(
"Call Agent Application, agentId:{}, dialogueId:{},largeModel:{},agentSystem:{},kdIds:{},communicationTurn:{},topP:{},temperature:{},messages:{}, tools:{}"
...
...
@@ -191,7 +191,7 @@ public class AgentApplicationInfoServiceImpl implements AgentApplicationInfoServ
}
@Override
public
String
callAgentApplication
(
String
agentId
,
String
dialogueId
,
String
largeModel
,
String
agentSystem
,
Integer
[]
kdIds
,
Integer
communicationTurn
,
Float
topP
,
Float
temperature
,
List
<
Message
>
messages
,
List
<
Tool
>
tools
,
FunctionCallResult
functionCallResult
,
List
<
String
>
fileUrls
,
boolean
stream
,
List
<
String
>
imageUrls
,
HttpServletResponse
httpServletResponse
)
throws
Exception
{
public
AgentResultEntity
callAgentApplication
(
String
agentId
,
String
dialogueId
,
String
largeModel
,
String
agentSystem
,
Integer
[]
kdIds
,
Integer
communicationTurn
,
Float
topP
,
Float
temperature
,
List
<
Message
>
messages
,
List
<
Tool
>
tools
,
FunctionCallResult
functionCallResult
,
List
<
String
>
fileUrls
,
boolean
stream
,
List
<
String
>
imageUrls
,
HttpServletResponse
httpServletResponse
)
throws
Exception
{
String
model
=
modelConvert
(
largeModel
);
Tool
[]
toolArray
=
tools
.
toArray
(
new
Tool
[
0
]);
...
...
@@ -528,7 +528,7 @@ public class AgentApplicationInfoServiceImpl implements AgentApplicationInfoServ
* @return 输出结果
* @throws Exception
*/
private
String
llmExecutorAndOutput
(
Float
topP
,
boolean
stream
,
String
model
,
Message
[]
messageArray
,
FunctionResult
functionResult
,
HttpServletResponse
httpServletResponse
)
throws
Exception
{
private
AgentResultEntity
llmExecutorAndOutput
(
Float
topP
,
boolean
stream
,
String
model
,
Message
[]
messageArray
,
FunctionResult
functionResult
,
HttpServletResponse
httpServletResponse
)
throws
Exception
{
if
(
stream
)
{
if
(
ObjectUtil
.
isNotNull
(
functionResult
)
&&
StringUtils
.
isNotBlank
(
functionResult
.
getFunctionName
()))
{
httpServletResponse
.
setContentType
(
TEXT_EVENT_STREAM_CHARSET_UTF_8
);
...
...
@@ -756,13 +756,16 @@ public class AgentApplicationInfoServiceImpl implements AgentApplicationInfoServ
* @param httpServletResponse
* @throws IOException
*/
private
String
textOutput
(
HttpServletResponse
httpServletResponse
,
LargeModelDemandResult
largeModelDemandResult
)
throws
private
AgentResultEntity
textOutput
(
HttpServletResponse
httpServletResponse
,
LargeModelDemandResult
largeModelDemandResult
)
throws
IOException
{
PrintWriter
writer
=
httpServletResponse
.
getWriter
();
writer
.
write
(
JsonUtils
.
serialize
(
largeModelDemandResult
));
writer
.
flush
();
writer
.
close
();
return
largeModelDemandResult
.
getMessage
();
AgentResultEntity
agentResultEntity
=
new
AgentResultEntity
();
agentResultEntity
.
setMessage
(
largeModelDemandResult
.
getMessage
());
agentResultEntity
.
setReasoningContent
(
largeModelDemandResult
.
getReasoningContent
());
return
agentResultEntity
;
}
...
...
@@ -773,12 +776,13 @@ public class AgentApplicationInfoServiceImpl implements AgentApplicationInfoServ
* @param bufferedReader
* @throws IOException
*/
private
String
textOutputStream
(
HttpServletResponse
httpServletResponse
,
BufferedReader
bufferedReader
)
throws
private
AgentResultEntity
textOutputStream
(
HttpServletResponse
httpServletResponse
,
BufferedReader
bufferedReader
)
throws
IOException
{
String
res
=
""
;
httpServletResponse
.
setContentType
(
TEXT_EVENT_STREAM_CHARSET_UTF_8
);
PrintWriter
writer
=
httpServletResponse
.
getWriter
();
StringBuilder
output
=
new
StringBuilder
();
StringBuilder
reasoningContent
=
new
StringBuilder
();
while
((
res
=
bufferedReader
.
readLine
())
!=
null
)
{
if
(
StringUtils
.
isBlank
(
res
))
{
continue
;
...
...
@@ -789,11 +793,14 @@ public class AgentApplicationInfoServiceImpl implements AgentApplicationInfoServ
logger
.
error
(
"LLM Error,code:{}"
,
result
.
getCode
());
I18nMessageException
ex
=
new
I18nMessageException
(
"exception/call.failure"
);
writer
.
write
(
EVENT_STREAM_PREFIX
+
JsonUtils
.
serialize
(
ex
.
getMessage
())
+
"\n\n"
);
writer
.
write
(
EVENT_STREAM_PREFIX
+
"[DONE]\n\n"
);
writer
.
flush
();
writer
.
close
();
throw
ex
;
}
if
(
StringUtils
.
isNotBlank
(
result
.
getMessage
()))
{
output
.
append
(
result
.
getMessage
());
reasoningContent
.
append
(
result
.
getReasoningContent
());
}
writer
.
write
(
EVENT_STREAM_PREFIX
+
res
+
"\n\n"
);
writer
.
flush
();
...
...
@@ -802,7 +809,10 @@ public class AgentApplicationInfoServiceImpl implements AgentApplicationInfoServ
writer
.
write
(
EVENT_STREAM_PREFIX
+
"[DONE]\n\n"
);
writer
.
close
();
bufferedReader
.
close
();
return
output
.
toString
();
AgentResultEntity
agentResultEntity
=
new
AgentResultEntity
();
agentResultEntity
.
setMessage
(
output
.
toString
());
agentResultEntity
.
setReasoningContent
(
reasoningContent
.
toString
());
return
agentResultEntity
;
}
private
ToolFunction
functionResultConvertToolFunction
(
FunctionResult
functionResult
)
{
...
...
src/main/java/cn/com/poc/agent_application/convert/BizAgentApplicationDialoguesRecordConvert.java
View file @
7ccfc95c
...
...
@@ -14,6 +14,7 @@ public class BizAgentApplicationDialoguesRecordConvert {
entity
.
setAgentId
(
model
.
getAgentId
());
entity
.
setMemberId
(
model
.
getMemberId
());
entity
.
setContent
(
model
.
getContent
());
entity
.
setReasoningContent
(
model
.
getReasoningContent
());
entity
.
setImageUrl
(
model
.
getImageUrl
());
entity
.
setDialogsId
(
model
.
getDialogsId
());
entity
.
setTimestamp
(
model
.
getTimestamp
());
...
...
@@ -34,6 +35,7 @@ public class BizAgentApplicationDialoguesRecordConvert {
model
.
setMemberId
(
entity
.
getMemberId
());
model
.
setDialogsId
(
entity
.
getDialogsId
());
model
.
setContent
(
entity
.
getContent
());
model
.
setReasoningContent
(
entity
.
getReasoningContent
());
model
.
setImageUrl
(
entity
.
getImageUrl
());
model
.
setTimestamp
(
entity
.
getTimestamp
());
model
.
setIsDeleted
(
entity
.
getIsDeleted
());
...
...
@@ -53,6 +55,7 @@ public class BizAgentApplicationDialoguesRecordConvert {
dto
.
setAgentId
(
entity
.
getAgentId
());
dto
.
setMemberId
(
entity
.
getMemberId
());
dto
.
setContent
(
entity
.
getContent
());
dto
.
setReasoningContent
(
entity
.
getReasoningContent
());
dto
.
setImageUrl
(
entity
.
getImageUrl
());
dto
.
setTimestamp
(
entity
.
getTimestamp
());
dto
.
setIsDeleted
(
entity
.
getIsDeleted
());
...
...
@@ -72,6 +75,7 @@ public class BizAgentApplicationDialoguesRecordConvert {
entity
.
setDialogsId
(
dto
.
getDialogsId
());
entity
.
setMemberId
(
dto
.
getMemberId
());
entity
.
setContent
(
dto
.
getContent
());
entity
.
setReasoningContent
(
dto
.
getReasoningContent
());
entity
.
setImageUrl
(
dto
.
getImageUrl
());
entity
.
setTimestamp
(
dto
.
getTimestamp
());
entity
.
setIsDeleted
(
dto
.
getIsDeleted
());
...
...
src/main/java/cn/com/poc/agent_application/dto/BizAgentApplicationDialoguesRecordDto.java
View file @
7ccfc95c
...
...
@@ -89,6 +89,20 @@ public class BizAgentApplicationDialoguesRecordDto {
}
/**
* reasoning_content
* 推理内容
*/
private
java
.
lang
.
String
reasoningContent
;
public
String
getReasoningContent
()
{
return
reasoningContent
;
}
public
void
setReasoningContent
(
String
reasoningContent
)
{
this
.
reasoningContent
=
reasoningContent
;
}
/**
* image_url
* 图片链接
...
...
src/main/java/cn/com/poc/agent_application/entity/AgentResultEntity.java
0 → 100644
View file @
7ccfc95c
package
cn
.
com
.
poc
.
agent_application
.
entity
;
/**
* @author alex.yao
* @date 2025/2/27
*/
public
class
AgentResultEntity
{
private
String
message
;
private
String
reasoningContent
;
public
String
getMessage
()
{
return
message
;
}
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
public
String
getReasoningContent
()
{
return
reasoningContent
;
}
public
void
setReasoningContent
(
String
reasoningContent
)
{
this
.
reasoningContent
=
reasoningContent
;
}
}
src/main/java/cn/com/poc/agent_application/entity/BizAgentApplicationDialoguesRecordEntity.java
View file @
7ccfc95c
...
...
@@ -75,6 +75,20 @@ public class BizAgentApplicationDialoguesRecordEntity {
}
/**
* reasoning_content
* 推理内容
*/
private
java
.
lang
.
String
reasoningContent
;
public
String
getReasoningContent
()
{
return
reasoningContent
;
}
public
void
setReasoningContent
(
String
reasoningContent
)
{
this
.
reasoningContent
=
reasoningContent
;
}
/**
* image_url
* 图片链接
...
...
src/main/java/cn/com/poc/agent_application/model/BizAgentApplicationDialoguesRecordModel.java
View file @
7ccfc95c
...
...
@@ -114,6 +114,22 @@ public class BizAgentApplicationDialoguesRecordModel extends BaseModelClass impl
}
/**
* reasoning_content
* 推理内容
*/
private
java
.
lang
.
String
reasoningContent
;
@Column
(
name
=
"reasoning_content"
,
length
=
2147483647
)
public
java
.
lang
.
String
getReasoningContent
()
{
return
this
.
reasoningContent
;
}
public
void
setReasoningContent
(
java
.
lang
.
String
reasoningContent
)
{
this
.
reasoningContent
=
reasoningContent
;
super
.
addValidField
(
"reasoningContent"
);
}
/**
* content
* 内容
...
...
src/main/java/cn/com/poc/agent_application/query/AgentApplicationDialoguesRecordQuery.sql
View file @
7ccfc95c
...
...
@@ -4,6 +4,7 @@ select
baadr
.
dialogs_id
,
baadr
.
member_id
,
baadr
.
content
,
baadr
.
reasoning_content
,
baadr
.
image_url
,
baadr
.
`timestamp`
,
baap
.
agent_avatar
,
...
...
src/main/java/cn/com/poc/agent_application/query/AgentApplicationDialoguesRecordQueryItem.java
View file @
7ccfc95c
...
...
@@ -89,6 +89,19 @@ public class AgentApplicationDialoguesRecordQueryItem extends BaseItemClass impl
this
.
content
=
content
;
}
/**
* reasoning_content
*/
private
String
reasoningContent
;
@Column
(
name
=
"reasoning_content"
)
public
String
getReasoningContent
()
{
return
reasoningContent
;
}
public
void
setReasoningContent
(
String
reasoningContent
)
{
this
.
reasoningContent
=
reasoningContent
;
}
/**
* image_url
...
...
src/main/java/cn/com/poc/agent_application/service/impl/BizAgentApplicationDialoguesRecordServiceImpl.java
View file @
7ccfc95c
...
...
@@ -95,6 +95,9 @@ public class BizAgentApplicationDialoguesRecordServiceImpl extends BaseServiceIm
if
(
entity
.
getContent
()
!=
null
)
{
model
.
setContent
(
entity
.
getContent
());
}
if
(
entity
.
getReasoningContent
()
!=
null
)
{
model
.
setReasoningContent
(
entity
.
getReasoningContent
());
}
if
(
entity
.
getTimestamp
()
!=
null
)
{
model
.
setTimestamp
(
entity
.
getTimestamp
());
}
...
...
src/main/java/cn/com/poc/expose/aggregate/impl/AgentApplicationApiServiceImpl.java
View file @
7ccfc95c
...
...
@@ -162,10 +162,10 @@ public class AgentApplicationApiServiceImpl implements AgentApplicationApiServic
//对话
try
{
String
output
=
agentApplicationInfoService
.
callAgentApplication
(
agentId
,
conversationId
,
infoEntity
.
getLargeModel
(),
AgentResultEntity
agentResultEntity
=
agentApplicationInfoService
.
callAgentApplication
(
agentId
,
conversationId
,
infoEntity
.
getLargeModel
(),
infoEntity
.
getAgentSystem
(),
kdIdList
.
toArray
(
new
Integer
[
0
]),
infoEntity
.
getCommunicationTurn
(),
infoEntity
.
getTopP
(),
infoEntity
.
getTemperature
(),
messages
,
tools
,
checkPluginUseEntity
.
getFunctionCallResult
(),
fileUrls
,
stream
,
imageUrls
,
httpServletResponse
);
saveRecord
(
conversationId
,
query
,
agentId
,
profileEntity
,
inputTimestamp
,
infoEntity
,
output
);
saveRecord
(
conversationId
,
query
,
agentId
,
profileEntity
,
inputTimestamp
,
infoEntity
,
agentResultEntity
.
getMessage
()
);
}
catch
(
Exception
e
)
{
memberEquityService
.
rollbackPoint
(
reduceSn
);
}
...
...
src/main/java/cn/com/poc/expose/aggregate/impl/AgentApplicationServiceImpl.java
View file @
7ccfc95c
...
...
@@ -15,7 +15,6 @@ import cn.com.poc.common.utils.BlContext;
import
cn.com.poc.common.utils.JsonUtils
;
import
cn.com.poc.data_analyze.aggregate.DataAnalyzeReportService
;
import
cn.com.poc.data_analyze.constants.DataAnalyzeChannelEnum
;
import
cn.com.poc.data_analyze.constants.DataAnalyzeTypeEnum
;
import
cn.com.poc.equity.aggregate.MemberEquityService
;
import
cn.com.poc.equity.aggregate.PointDeductionRulesService
;
import
cn.com.poc.equity.constants.ModifyEventEnum
;
...
...
@@ -43,7 +42,6 @@ import org.springframework.stereotype.Service;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpServletResponse
;
import
java.math.BigDecimal
;
import
java.security.SecureRandom
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
...
...
@@ -166,7 +164,7 @@ public class AgentApplicationServiceImpl implements AgentApplicationService {
//计算扣分数
// 判断是否调用function
CheckPluginUseEntity
checkPluginUseEntity
=
AgentApplicationTools
.
checkPluginUse
(
messages
,
tools
,
fileUrls
,
imageUrls
);
CheckPluginUseEntity
checkPluginUseEntity
=
AgentApplicationTools
.
checkPluginUse
(
messages
,
tools
,
fileUrls
,
imageUrls
);
Long
pointDeductionNum
=
pointDeductionRulesService
.
calculatePointDeductionNum
(
infoEntity
.
getLargeModel
(),
infoEntity
.
getCommunicationTurn
(),
checkPluginUseEntity
.
getDeductionTools
());
AgentUseModifyEventInfo
agentUseModifyEventInfo
=
new
AgentUseModifyEventInfo
();
agentUseModifyEventInfo
.
setAgentId
(
agentId
);
...
...
@@ -182,12 +180,13 @@ public class AgentApplicationServiceImpl implements AgentApplicationService {
}
}
//对话
String
output
=
agentApplicationInfoService
.
callAgentApplication
(
agentId
,
dialogsId
,
infoEntity
.
getLargeModel
(),
AgentResultEntity
agentResultEntity
=
agentApplicationInfoService
.
callAgentApplication
(
agentId
,
dialogsId
,
infoEntity
.
getLargeModel
(),
infoEntity
.
getAgentSystem
(),
kdIdList
.
toArray
(
new
Integer
[
0
]),
infoEntity
.
getCommunicationTurn
(),
infoEntity
.
getTopP
(),
infoEntity
.
getTemperature
(),
messages
,
tools
,
checkPluginUseEntity
.
getFunctionCallResult
(),
fileUrls
,
true
,
imageUrls
,
httpServletResponse
);
//保存对话记录
outputRecord
.
setContent
(
output
);
outputRecord
.
setContent
(
agentResultEntity
.
getMessage
());
outputRecord
.
setReasoningContent
(
agentResultEntity
.
getReasoningContent
());
bizAgentApplicationDialoguesRecordService
.
save
(
outputRecord
);
//数据采集
if
(
StringUtils
.
isBlank
(
channel
))
{
...
...
src/main/java/cn/com/poc/expose/dto/DialoguesContextDto.java
View file @
7ccfc95c
...
...
@@ -47,6 +47,18 @@ public class DialoguesContextDto implements Serializable {
this
.
content
=
content
;
}
/**
* 推理内容
*/
private
String
reasoningContent
;
public
String
getReasoningContent
()
{
return
reasoningContent
;
}
public
void
setReasoningContent
(
String
reasoningContent
)
{
this
.
reasoningContent
=
reasoningContent
;
}
/**
* timestamp
...
...
src/main/java/cn/com/poc/expose/rest/impl/AgentApplicationRestImpl.java
View file @
7ccfc95c
...
...
@@ -241,6 +241,7 @@ public class AgentApplicationRestImpl implements AgentApplicationRest {
dto
.
setRole
(
value
.
getRole
());
dto
.
setAgentId
(
value
.
getAgentId
());
dto
.
setContent
(
value
.
getContent
());
dto
.
setReasoningContent
(
value
.
getReasoningContent
());
dto
.
setImageUrl
(
value
.
getImageUrl
());
dto
.
setTimestamp
(
value
.
getTimestamp
());
dto
.
setAgentTitle
(
value
.
getAgentTitle
());
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment