Taking your question word-for-word and using TinkerGraph I guess you could do:
gremlin> v = g.addV('person').property('empId',4944).property('personalDetails',[name:"Tony Stark",company:"Stark Industries",strength:"AI"]).next()
==>v[13]
gremlin> g.V(v).property(list, 'keywords', 'Stark')
==>v[13]
gremlin> g.V(v).property(list, 'keywords', 'Love you 3000')
==>v[13]
gremlin> g.V(v).property(list, 'keywords', 'IRON MAN')
==>v[13]
gremlin> g.V().valueMap()
==>[empId:[4944],keywords:[Stark,Love you 3000,IRON MAN],personalDetails:[[name:Tony Stark,company:Stark Industries,strength:AI]]]
gremlin> g.V().has('keywords','Stark').has('keywords','IRON MAN')
==>v[13]
gremlin> g.V().has('personalDetails').filter(values('personalDetails').select('company').is('Stark Industries'))
==>v[13]
Note that I used multiproperties to store the keywords as that seems like the most natural way to query them for TinkerGraph. I stored your "personalDetails" as a Map as you required and I can produce an answer well enough but that feels a bit clunky to me. Not only does it feel "wrong" but this query won't result in an index hit and is basically a full graph scan. I think I'd much prefer to see you remove "personalDetails" and promote the keys of the Map to first class property keys because then you get the possibility for index lookup and much nicer gremlin:
gremlin> v = g.addV('person').property('empId',4945).property('name',"Tony Stark").property('company',"Stark Industries").property('strength',"AI").next()
==>v[26]
gremlin> g.V().has('company','Stark Industries')
==>v[26]
That's much more intuitive. All that said, this is mostly a solution for TinkerGraph. If you use other graphs (like JanusGraph, DS Graph, Neptune, CosmosDB, etc) they might have other schema definition and index creation functions that will better suit what you're trying to do.